如何在Play框架中处理可选查询参数


72

可以说我在Scala中有一个已经运行的基于Play 2.0框架的应用程序,该应用程序提供URL,例如:

http:// localhost:9000 /生日

它以所有已知生日的列表作为响应

我现在想通过添加使用可选的“ from”(日期)和“ to”请求参数来限制结果的功能来增强此功能,例如

http:// localhost:9000 / birthdays?from = 20120131&to = 20120229

(此处的日期解释为yyyyMMdd)

我的问题是如何使用Scala在Play 2.0中处理请求参数的绑定和解释,特别是考虑到这两个参数都应该是可选的。

这些参数是否应在“路线”规范中以某种方式表达?或者,响应的Controller方法是否应该以某种方式从请求对象中分离参数?还有另一种方法吗?

Answers:


60

将您的可选参数编​​码为Option[String](或Option[java.util.Date],但您必须实现自己的QueryStringBindable[Date]):

def birthdays(from: Option[String], to: Option[String]) = Action {
  // …
}

并声明以下路线:

GET   /birthday       controllers.Application.birthday(from: Option[String], to: Option[String])

8
对我来说,这还不足以进行没有参数的路由。我将其扩展至GET /birthday controllers.Application.birthday(from: Option[String] ?= None, to: Option[String] ?= None)
Marius Soutier,2012年

更简洁:GET /birthday controllers.Application.birthday(Option[from], Option[to])
Paul Draper


此处介绍了可选参数(v2.7 +)=> playframework.com/documentation/2.7.x/…–
sentenza

19

为Java用户执行此操作的一种较不干净的方法是设置默认值:

GET  /users  controllers.Application.users(max:java.lang.Integer ?= 50, page:java.lang.Integer ?= 0)

并在控制器中

public static Result users(Integer max, Integer page) {...}

还有一个问题,每当您链接到模板中的页面时,都必须重复默认设置

@routes.Application.users(max = 50, page = 0)

有人可以确认(max:java.lang.Integer = null)有效吗?'max'总是以我为空...
ejain 2012年

1
我已确定答案,应该是?=
Somatik 2012年

6
在Java中,您可以使用play.libs.F.OptionScala代替Option
Julien Richard-Foy

1
您是否有使用Scala或F选项的完整示例。困扰我的是模板中默认值的重复。我总是得到将_应用于部分应用函数的建议
Somatik 2012年

12

除了朱利安的答案。如果您不想将其包括在路由文件中。

您可以使用RequestHeader在控制器方法中获取此属性

String from = request().getQueryString("from");
String to = request().getQueryString("to");

这将为您提供所需的请求参数,并保持路由文件整洁。


您的路由器文件看起来如何?我有类似的东西GET /url @com.mycompany.controllers.MyClass.fetchget(),但找不到路线
Zennichimaro


8

这是朱利安(Julien)的示例,使用F.Option用Java重写:(从play 2.1开始工作)

import play.libs.F.Option;
public static Result birthdays(Option<String> from, Option<String> to) {
  // …
}

路线:

GET   /birthday       controllers.Application.birthday(from: play.libs.F.Option[String], to: play.libs.F.Option[String])

您还可以选择任意查询参数作为字符串(您必须自己进行类型转换):

public static Result birthdays(Option<String> from, Option<String> to) {
  String blarg = request().getQueryString("blarg"); // null if not in URL
  // …
}

5

对于可选的查询参数,您可以采用这种方式

在路由文件中,声明API

GET   /birthdays     controllers.Application.method(from: Long, to: Long)

您还可以提供一些默认值,以防API不包含这些查询参数,它将自动为这些参数分配默认值

GET   /birthdays    controllers.Application.method(from: Long ?= 0, to: Long ?= 10)

在控制器应用程序内部编写的方法中,null如果未分配默认值,则这些参数将具有值,否则将默认值。


感谢您提供此答案,现在它以带有默认值的字段的形式显示。就我而言,我有一个强制性参数和一个可选参数。
karsten314159

2

我的方法涉及使用自定义QueryStringBindable。这样,我将路由参数表示为:

GET /birthdays/ controllers.Birthdays.getBirthdays(period: util.Period)

Period的代码如下所示。

public class Period implements QueryStringBindable<Period> {

  public static final String PATTERN = "dd.MM.yyyy";
  public Date start;

  public Date end;

  @Override
  public F.Option<Period> bind(String key, Map<String, String[]> data) {
      SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);

      try {
          start = data.containsKey("startDate")?sdf.parse(data.get("startDate")  [0]):null;
          end = data.containsKey("endDate")?sdf.parse(data.get("endDate")[0]):null;
      } catch (ParseException ignored) {
          return F.Option.None();
      }
      return F.Option.Some(this);
  }

  @Override
  public String unbind(String key) {
      SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);
      return "startDate=" + sdf.format(start) + "&amp;" + "endDate=" + sdf.format(end);
  }

  @Override
  public String javascriptUnbind() {
      return null;
  }

  public void applyDateFilter(ExpressionList el) {
      if (this.start != null)
          el.ge("eventDate", this.start);
      if (this.end != null)
          el.le("eventDate", new DateTime(this.end.getTime()).plusDays(1).toDate());
  }

}

applyDateFilter如果要将日期过滤应用于查询,这只是我在控制器中使用的一种便捷方法。显然,您可以在此处使用其他日期默认值,或者在方法中使用除null以外的其他默认值作为开始日期和结束日期bind

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.