我无法理解play.api.mvc.Request[A]
和play.api.mvc.RequestHeader
与play.api.mvc.Request[play.api.mvc.AnyContent]
之间的区别。
在编译的课程中,我有
trait Request[+A] extends scala.AnyRef with play.api.mvc.RequestHeader {
def $init$() : scala.Unit = { /* compiled code */ }
def body : A
def map[B](f : scala.Function1[A, B]) : play.api.mvc.Request[B] = { /* compiled code */ }
}
object Request extends scala.AnyRef {
def apply[A](rh : play.api.mvc.RequestHeader, a : A) : scala.AnyRef with play.api.mvc.Request[A] {
val remoteAddress : scala.Predef.String
def username : scala.None.type
val body : A
} = { /* compiled code */ }
}
Request [AnyContent] ---> RequestWithUser [play.api.mvc.AnyContent]吗?
def getLoginPage[A](implicit request: Request[A], form: Form[(String, String)], msg: Option[String]): Html = {
val req = RequestWithUser(None, request)
views.html.secure.login(form, msg)(request = req)
}
此代码在
TemplatePlugin
中有效,但在视图中不起作用:@(loginForm: play.api.data.Form[(String,String)], errorMsg: Option[String] = None)(implicit request: securesocial.core.RequestWithUser[_ <: play.api.mvc.AnyContent])
它不起作用,因为:
type mismatch; found : securesocial.core.RequestWithUser[A] required: securesocial.core.RequestWithUser[_ <: play.api.mvc.AnyContent]
因此,我尝试将
AnyContent
设置为通用类型:def getLoginPage[A](implicit request: Request[A], form: Form[(String, String)], msg: Option[String]): Html = {
val req = RequestWithUser[play.api.mvc.AnyContent](None, request)
views.html.secure.login(form, msg)(request = req)
}
但是显示下一个编译错误:
type mismatch; found : play.api.mvc.Request[A] required: play.api.mvc.Request[play.api.mvc.AnyContent]
而且play.api.mvc.AnyContent看起来像:
package play.api.mvc
sealed trait AnyContent extends scala.AnyRef {
def $init$() : scala.Unit = { /* compiled code */ }
def asFormUrlEncoded : scala.Option[scala.Predef.Map[scala.Predef.String, scala.Seq[scala.Predef.String]]] = { /* compiled code */ }
def asText : scala.Option[scala.Predef.String] = { /* compiled code */ }
def asXml : scala.Option[scala.xml.NodeSeq] = { /* compiled code */ }
def asJson : scala.Option[play.api.libs.json.JsValue] = { /* compiled code */ }
def asMultipartFormData : scala.Option[play.api.mvc.MultipartFormData[play.api.libs.Files.TemporaryFile]] = { /* compiled code */ }
def asRaw : scala.Option[play.api.mvc.RawBuffer] = { /* compiled code */ }
}
请帮我解决这个问题。
编辑-到目前为止的解决方案
我发现代码可以编译,甚至可以很好地工作。但是,这不是一种优雅的方法,因为我使用了
asInstanceOf
和强制转换类。def getLoginPage[A](implicit request: Request[A], form: Form[(String, String)], msg: Option[String]): Html = {
implicit val r = RequestWithUser[play.api.mvc.AnyContent](None, request.asInstanceOf[Request[AnyContent]])
views.html.secure.login(form, msg)(request = r)
}
最佳答案
RequestHeader
表示HTTP请求的标头。 Request[A]
是RequestHeader
加上A
的已分析请求正文。 Play中的默认主体解析器会检测一些众所周知的主体格式(application/json
,application/xml
,text/plain
,application/x-www-form-urlencoded
,multipart/form-data
),并自动将其解析为类型为AnyContent
的主体。使您可以通过调用诸如asJson
之类的方法来访问特定类型。如果您编写如下操作:
def myAction = Action { req =>
...
}
那么
req
的类型将是Request[AnyContent]
。另一方面,如果您明确指定主体解析器,则请求的类型将是该主体解析器返回的类型,例如:def myAction = Action(parse.json) { req =>
...
}
在这种情况下,
req
将为Request[JsValue]
。因此,安全的社交模板需要一个Request[AnyContent]
,因此,这首先意味着您只能在使用默认正文分析器的操作中使用它。接下来,这意味着您必须更改getLoginPage
的签名以仅接受Request[AnyContent]
,例如:def getLoginPage(implicit request: Request[AnyContent], form: Form[(String, String)], msg: Option[String]): Html = {
val req = RequestWithUser(None, request)
views.html.secure.login(form, msg)(request = req)
}
只要调用
getLoginPage
的每个动作都具有由默认主体解析器产生的请求,该命令就应该起作用。