要模拟向请求中注入任意数据,您可以扩展 WrappedRequest:
case class Outcome[A](
r: Request[A],
uid: Int,
startDate: String,
endDate: String,
uriDate: JodaTime) extends WrappedRequest(r)
然后创建返回自定义请求包装器实例的操作提供程序特征。例如,基本任务操作可能如下所示:
trait TaskRequest
extends DateParser {
def Task[A](p: BodyParser[A])(f: Outcome[A] => Result) = {
Action(p) { implicit r =>
f( toOutcome[A](r, r.session.get("userID").map(_.toInt) getOrElse 0) )
}
}
def Task(f: Outcome[AnyContent] => Result): Action[AnyContent] = {
import play.api.mvc.BodyParsers._
Task(parse.anyContent)(f)
}
protected def toOutcome[A](r: Request[A], uid: Int) = {
val(start,uriDate) = (startDate(r), toDate(r.uri))
val end = seasonEnd(start)
Outcome(r, uid, start.toString("yyyyMMdd"), end.toString("yyyyMMdd"), uriDate)
}
val ymdMatcher = "\\d{8}".r
protected def startDate(uri: String) = {
ymdMatcher.findFirstIn(uri). // set season start based on ymd URI param if exist
map(_.startDate) getOrElse seasonStart(new JodaTime)
}
protected def toDate(uri: String) =
ymdMatcher.findFirstIn(r.uri).map(_.to_date) getOrElse new JodaTime
}
然后从 Task 派生一个 Authenticated 动作:
trait Secured
extends TaskRequest {
def Authenticated[A](p: BodyParser[A])
(f: Outcome[A] => Result)(implicit group: RoleGroup) = {
def apply(maybeUser: Option[String])(implicit r: Request[A]) = {
maybeUser map {id =>
Cache.orElse(group.to_s+"-"+id, 3600){
repo.user.get(id.int, group) map(_.active) getOrElse false
} fold ( onFail, f( toOutcome(r, id.int)) )
}
}
然后在您的控制器中使用:
def index = Authenticated { implicit request=>
// voila, current season start date since no uri date param exist
request.startDate
}
当然,我可以在每个操作的基础上调用日期操作函数,但这仅适用于 Action scope。如何访问模板层中的 startDate?我不能,但是使用自定义请求包装器,您可以注入任何您想要的内容,并轻松地在任何地方引用数据。因此,不要将 play 的请求纳入范围:
@(model: Foo, title: String)(implicit request: play.api.mvc.Request[_])
您引用您的自定义请求包装器:
@(model: Foo, title: String)(implicit request: controllers.Outcome[_])
这项工作做得很好,全局拦截我还没有找到用途(也许重新路由一些遗留的 URI,但没有像 WrappedRequest 方法那样强大)