假设我在Scala中已经运行了一个基于Play 2.0框架的应用程序,它可以提供以下URL:
http://localhost:9000/birthdays
以所有已知生日的列表作出回应
我现在希望通过添加使用可选的“from”(日期)和“to”请求参数来限制结果的功能来增强此功能,例如
http://localhost:9000/birthdays?from=20120131&to=20120229
(此处的日期解释为yyyyMMdd)
我的问题是如何使用Scala处理Play 2.0中的请求参数绑定和解释,特别是考虑到这两个参数都应该是可选的。
这些参数是否应以某种方式在“路线”规范中表达?或者,响应的Controller方法应该以某种方式从请求对象中分离出params吗?还有另一种方法吗?
答案 0 :(得分:57)
将可选参数编码为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])
答案 1 :(得分:17)
为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)
答案 2 :(得分:10)
除了朱利安的回答。如果您不想将其包含在路线文件中。
您可以使用RequestHeader
在控制器方法中获取此属性String from = request().getQueryString("from");
String to = request().getQueryString("to");
这将为您提供所需的请求参数,并保持您的路由文件清洁。
答案 3 :(得分:7)
这是朱利安在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])
您也可以选择任意查询参数作为字符串(您必须自己进行类型转换):
public static Result birthdays(Option<String> from, Option<String> to) {
String blarg = request().getQueryString("blarg"); // null if not in URL
// …
}
答案 4 :(得分:4)
对于可选的Query参数,您可以这样做
在路线文件中,声明API
GET /birthdays controllers.Application.method(from: Long, to: Long)
你也可以给出一些默认值,如果API不包含这些查询参数,它会自动为这些参数分配默认值
GET /birthdays controllers.Application.method(from: Long ?= 0, to: Long ?= 10)
在控制器内部编写的方法中,如果没有为默认值分配默认值,这些参数将具有值null
。
答案 5 :(得分: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) + "&" + "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
只是我在控制器中使用的一种便利方法。显然你可以在这里使用其他日期默认值,或者在bind
方法中使用其他默认值来表示开始日期和结束日期。