在Play和Scala中向case类获取请求参数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Play和Scala中向case类获取请求参数相关的知识,希望对你有一定的参考价值。

我继承了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-type的一个参数,并将Play匹配请求参数名称添加到字段名称并绑定值?

如果在POST请求正文中提交了相同的值,则可以轻松实现此目的。但这不是一个选择,因为这个终点已经暴露给客户。

答案

Query string binders用于此。基本上,您告诉Play如何解析参数,将它们分组到一个类并反转(将它们转回String表示)。假设你想要一个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._" 

以上是关于在Play和Scala中向case类获取请求参数的主要内容,如果未能解决你的问题,请参考以下文章

11.scala案例类(Case Classes)

如何在 Play 2.7 for Scala 中编写一个通用 JSON 解析器来验证入站请求?

scala case class

如何在 Play Framework 2.3 中向 FakeRequest 添加查询字符串参数?

Play/Scala 中的隐式参数和组合视图

Scala 必知必会