如何处理 Play 框架中的可选查询参数
Posted
技术标签:
【中文标题】如何处理 Play 框架中的可选查询参数【英文标题】:How to handle optional query parameters in Play framework 【发布时间】:2012-03-28 06:25:39 【问题描述】:假设我在 Scala 中有一个基于 Play 2.0 框架的应用程序,它提供如下 URL:
http://localhost:9000/birthdays
返回所有已知生日的列表
我现在想通过添加使用可选的“from”(日期)和“to”请求参数来限制结果的能力来增强这一点,例如
http://localhost:9000/birthdays?from=20120131&to=20120229
(此处的日期解释为 yyyyMMdd)
我的问题是如何使用 Scala 在 Play 2.0 中处理请求参数绑定和解释,特别是考虑到这两个参数都应该是可选的。
这些参数是否应该在“路由”规范中以某种方式表达?或者,响应控制器方法是否应该以某种方式从请求对象中挑选参数?有没有其他方法可以做到这一点?
【问题讨论】:
【参考方案1】:将您的可选参数编码为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])
【讨论】:
对我来说,这不足以在没有参数的情况下进行路由。我把它扩展到GET /birthday controllers.Application.birthday(from: Option[String] ?= None, to: Option[String] ?= None)
更成功:GET /birthday controllers.Application.birthday(Option[from], Option[to])
现在记录在playframework.com/documentation/2.4.x/…
这里描述了可选参数 (v2.7+) => playframework.com/documentation/2.7.x/…【参考方案2】:
对 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' 对我来说总是为空...... 我修正了答案,应该是 ?= 在Java中你可以使用play.libs.F.Option
而不是Scala Option
你有使用 Scala 或 F 选项的整个例子吗?困扰我的是模板中默认设置的重复。我总是收到将 _ 用于部分应用函数的建议【参考方案3】:
除了朱利安的回答。如果您不想将其包含在 routes 文件中。
你可以在控制器方法中使用RequestHeader获取这个属性
String from = request().getQueryString("from");
String to = request().getQueryString("to");
这将为您提供所需的请求参数,并保持您的 routes 文件干净。
【讨论】:
您的路由器文件看起来如何?我有类似GET /url @com.mycompany.controllers.MyClass.fetchget()
的东西,但它找不到路线
@Zennichimaro ***.com/questions/16301211/… 看看【参考方案4】:
这是 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
,否则为默认值。
【讨论】:
感谢您的回答,现在它以带有默认值的字段的形式出现。就我而言,我有一个强制参数和一个可选参数。【参考方案6】:我的做法是使用自定义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
方法中使用其他默认值而不是 null 作为开始和结束日期。
【讨论】:
知道如何让 swagger 使用这个解决方案吗?以上是关于如何处理 Play 框架中的可选查询参数的主要内容,如果未能解决你的问题,请参考以下文章