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

比方说,我有一个已经运作的基于Play 2.0框架的应用程序在Scala中提供一个URL,如:

HTTP://本地主机:9000 /生日

其中列出了所有已知的生日

我现在想通过添加限制结果的能力来增强这个function,可选的“from”(date)和“to”请求参数,例如

HTTP://本地主机:9000 /生日从= 20120131&到= 20120229?

(这里的date解释为yyyyMMdd)

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

这些参数是否应该用“路线”规范expression? 或者,如果响应的Controller方法以某种方式从请求对象中分离参数? 有没有另外一种方法来做到这一点?

将选项参数编码为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]) 

对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) 

除了朱利安的回答。 如果您不想将其包含在路线文件中。

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

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

这将给你所需的请求参数,并保持你的路线文件干净。

这里是朱利安的例子用java重写,使用F.Option :(从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]) 

你也可以select任意查询参数作为string(你必须自己进行types转换):

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

我这样做的方式涉及使用自定义的QueryStringBindable 。 这样我在路线中expression参数:

 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只是一个applyDateFilter方法,我在我的控制器中使用,如果我想对查询应用date筛选。 显然你可以在这里使用其他的date默认值,或者在bind方法中使用一些其他的默认值而不是null作为开始date和结束date。

对于可选的Query参数,可以这样做

在路由文件中,声明API

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

您也可以给一些默认值,如果API不包含这些查询参数,它会自动分配默认值这些参数

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

在控制器内写入的方法应用程序中,如果没有默认值赋值,那么这些参数的值将为null