GET 请求参数到 Play & Scala 中的 case class
GET request parameters to case class in Play & Scala
我继承了 2 个控制器方法(用于 GET 请求),它们接受相同的 10 个请求参数,如下所示:
class Application @Inject() (cc: ControllerComponents) extends AbstractController(cc) {
def func1(param1: String,
param2: String,
param3: String
...
param10: String
) = Action {
...
}
def func2(param1: String,
param2: String,
param3: String
...
param10: String
) = Action {
...
}
}
这些映射如下:
GET /f1 blah.blah.Application.func1(p1: String, p2: String...p10: String)
GET /f2 blah.blah.Application.func2(p1: String, p2: String...p10: String)
我喜欢避免重复。我想知道是否可以用请求参数命名的 10 个字段定义一个 case class,让控制器方法接受一个 case-class 类型的参数,并让 Play 匹配请求参数名称到字段名称并绑定值?
如果在 POST 请求正文中提交相同的值,则可以轻松实现这一点。但这不是一个选项,因为这个端点已经暴露给客户。
Query string binders 用于此。基本上,您告诉 Play 如何解析参数,将它们分组为 class 并反转(将它们转回字符串表示形式)。假设您想要一个 Page
抽象:
case class Page(from: Int, to: Int)
implicit def pageQSB(implicit intBinder: QueryStringBindable[Int]) = new QueryStringBindable[Page] {
override def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, Page]] = {
for {
from <- intBinder.bind("from", params)
to <- intBinder.bind("to", params)
} yield {
(from, to) match {
case (Right(from), Right(to)) => Right(Page(from, to))
case _ => Left("Unable to bind a Page")
}
}
}
override def unbind(key: String, page: Page): String = {
intBinder.unbind("from", page.from) + "&" + intBinder.unbind("to", page.to)
}
}
请注意,您必须将这些隐式导入路由范围(在您的build.sbt中),例如
routesImport += "utils.MyBinders._"
我继承了 2 个控制器方法(用于 GET 请求),它们接受相同的 10 个请求参数,如下所示:
class Application @Inject() (cc: ControllerComponents) extends AbstractController(cc) {
def func1(param1: String,
param2: String,
param3: String
...
param10: String
) = Action {
...
}
def func2(param1: String,
param2: String,
param3: String
...
param10: String
) = Action {
...
}
}
这些映射如下:
GET /f1 blah.blah.Application.func1(p1: String, p2: String...p10: String)
GET /f2 blah.blah.Application.func2(p1: String, p2: String...p10: String)
我喜欢避免重复。我想知道是否可以用请求参数命名的 10 个字段定义一个 case class,让控制器方法接受一个 case-class 类型的参数,并让 Play 匹配请求参数名称到字段名称并绑定值?
如果在 POST 请求正文中提交相同的值,则可以轻松实现这一点。但这不是一个选项,因为这个端点已经暴露给客户。
Query string binders 用于此。基本上,您告诉 Play 如何解析参数,将它们分组为 class 并反转(将它们转回字符串表示形式)。假设您想要一个 Page
抽象:
case class Page(from: Int, to: Int)
implicit def pageQSB(implicit intBinder: QueryStringBindable[Int]) = new QueryStringBindable[Page] {
override def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, Page]] = {
for {
from <- intBinder.bind("from", params)
to <- intBinder.bind("to", params)
} yield {
(from, to) match {
case (Right(from), Right(to)) => Right(Page(from, to))
case _ => Left("Unable to bind a Page")
}
}
}
override def unbind(key: String, page: Page): String = {
intBinder.unbind("from", page.from) + "&" + intBinder.unbind("to", page.to)
}
}
请注意,您必须将这些隐式导入路由范围(在您的build.sbt中),例如
routesImport += "utils.MyBinders._"