如何在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) + "&" + "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
。