假设我在 Scala 中有一个已经运行的基于 Play 2.0 框架的应用程序,它提供如下 URL:

http://localhost:9000/生日

它以所有已知生日的列表进行响应

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

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

(此处的日期解释为 yyyyMMdd)

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

这些参数是否应该以某种方式在“路由”规范中表达?或者,响应的控制器方法是否应该以某种方式从请求对象中分离出参数?还有其他方法可以做到这一点吗?

有帮助吗?

解决方案

将您的可选参数编​​码为 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)
.

除Julien的答案外。如果您不想在路由中包含它文件。

您可以使用RequestHeader 在Controller方法中获取此属性

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

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

这是Julien在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
  // …
}
.

对于可选的查询参数,你可以这样做

在routes文件中,声明API

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

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

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

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

我的方法是使用自定义的 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 方法。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top