【问题标题】:Implicit parameter without type in play没有类型的隐式参数在播放
【发布时间】:2016-03-26 13:29:30
【问题描述】:

为什么下面的 Play 语法有效

def handleForm = Action(parse.tolerantFormUrlEncoded) { implicit request =>
  val username = request.body.get("username").map(_.head).getOrElse("");
  Ok("Username was " + username)
}

如果不指定请求的类型,编译器怎么知道如何解决隐含的?

【问题讨论】:

    标签: scala playframework implicit


    【解决方案1】:

    Play 中的 Action 可以看作是一个函数:Request[A] => Result。在内部,Action 定义为 trait Action[A] extends EssentialAction

    A 类型实际上是允许您在其中放入任何东西的类型。从代码中可以看出,Request 是这样定义的:trait Request[+A] extends RequestHeader。这里有趣的是加号(+)。也就是所谓的协变注解。这个协变类型参数是允许随着类被子类型化而向下变化的类型参数。这意味着如果你有类似的东西

    trait List[+A]

    那么List[Int]List[AnyVal] 的子类型,因为IntAnyVal 的子类型。这意味着当需要List[AnyVal] 类型的值时,您可以提供List[Int] 的实例。

    所有这些都允许您拥有一个超级通用的请求,作为您的操作的基础,因此不会出现编译时问题。


    从更与用户相关的角度来看,为什么这一切都是必要的:

    来自 Play Scala 文档:

    将请求参数标记为隐式通常很有用,因此它可以 被其他需要它的 API 隐式使用:

    Action { implicit request =>
      Ok("Got request [" + request + "]")
    }
    

    【讨论】:

      【解决方案2】:

      它实际上并没有解析隐式,将参数标记为隐式,以便在请求处理程序中进行进一步的方法调用。每当您调用一个接受隐式Request 参数的方法时,来自请求处理程序的请求参数将自动传递给它。如果您不将请求参数标记为隐式,则必须为每个需要隐式请求参数的方法调用显式传递请求参数。

      更新:根据您的评论,我用类型参数更新了您的代码以澄清。所以即使你使用不同的BodyParsers,你的请求参数仍然是请求类型,所以不需要转换它,它只是会根据你的身体解析器进行不同的参数化。 request.body 将具有与类型参数相同的类型,在此示例中为 Map[String, Seq[String]]。如果您使用 JSON 正文解析器,那么您的 request 参数将是 Request[JsValue],而 request.bodyJsValue

      def handleForm: Action[Map[String, Seq[String]]] = Action(parse.tolerantFormUrlEncoded)({ 
        implicit request: Request[Map[String, Seq[String]]] =>
          val username = request.body.get("username").map(_.head).getOrElse("")
          Ok("Username was " + username)
      })
      

      tl;dr 如果您不需要隐式 Request 以在请求处理程序中进行进一步的方法调用,则可以使用 Action(...) { request => ... }

      【讨论】:

      • 编译器如何知道该方法接受隐式请求参数?我的方法handleForm 只接受一个名为request 的隐式参数,其命名是任意的?
      • 你的方法接受一个显式的 Request 参数,该参数将隐含在方法体中以供后续函数调用,例如:playframework.com/documentation/2.4.x/…
      • 哦,我明白了,那么一定有一种方法可以将parse.tolerantFormUrlEncoded 转换为request 类型对吧?由于parse.tolerantFormUrlEncoded.body 返回错误。
      • @Kevin 我添加了一些解释,希望清楚。 parse.tolerantFormUrlEncoded.body 返回错误是正常的,因为parse.tolerantFormUrlEncoded 是一个正文解析器,而不是Request。但是request.body 将是正确的类型,对应于您的类型解析器
      猜你喜欢
      • 2021-10-28
      • 2021-08-09
      • 2021-11-12
      • 1970-01-01
      • 1970-01-01
      • 2018-09-23
      • 2018-05-30
      • 2018-09-25
      相关资源
      最近更新 更多