尝试更好地了解使用操作构建器创建自定义操作。
我有一个自定义操作:
class LogginInRequest[A](val currentUser: User, request: Request[A]) extends WrappedRequest[A](request)
object ActionWithContext extends ActionBuilder[LogginInRequest] {
def invokeBlock[A](request: Request[A], block: (LogginInRequest[A]) => Future[SimpleResult]) = {
val u = /// load User
block(new LogginInRequest(user, request)
}
}
我是否可以创建另一个类似于上面的自定义操作,它继承自上面的操作,并在其上构建,即在操作中链并访问用户对象
e.g。假设我现在在我的网站上为管理员创建一个新部分,所以我在这个新操作中检查用户对象: user.isAdmin
如果isAdmin为false,则使用Future.successful(Forbidden)
调用重定向。
所以我会基于LogginInRequest创建LoggedInAdmin,但只是检查属性isAdmin(这只是一个例子,但我想知道我是否可以这样做)。
是否可以将参数传递给我使用动作构建器创建的自定义操作,以便我可以执行此操作?
def someAction(...):= MyCustomActionBuilder(userService){ // ... }
即。我正在向它提出一个论点。
答案 0 :(得分:3)
使用Play 2.3,使用ActionBuilder的动作合成得到了更好的效果。下面的示例显示了如何定义创建包装请求的标准ActionBuilder
,然后将该构建器与ActionTransformer
链接在一起以创建新的包装请求。
import scala.concurrent.Future
import org.scalatest.{MustMatchers, WordSpec}
import play.api.mvc._
import play.api.test.FakeRequest
import play.api.test.Helpers._
class ChainingTest extends WordSpec with MustMatchers {
class WrappedReq1[A](val str: String, request: Request[A]) extends WrappedRequest[A](request)
object ActionWithReq1 extends ActionBuilder[WrappedReq1] {
def invokeBlock[A](request: Request[A], block: (WrappedReq1[A]) => Future[Result]) = {
block(new WrappedReq1(request.headers("1"), request))
}
}
class WrappedReq2[A](val str1: String, val str2: String, request: Request[A]) extends WrappedRequest[A](request)
val ActionWithReq2 = ActionWithReq1 andThen new ActionTransformer[WrappedReq1, WrappedReq2] {
override protected def transform[A](request: WrappedReq1[A]): Future[WrappedReq2[A]] = {
Future.successful(new WrappedReq2[A](request.str, request.headers("2"), request))
}
}
"chained actions" should {
"work" in {
val request = FakeRequest().withHeaders("1" -> "one", "2" -> "two")
val response = ActionWithReq2 { r => Results.Ok(r.str1 + "-" + r.str2) }(request)
contentAsString(response) must equal("one-two")
}
}
}
有一个ActionTransformer
特征用于修改您的请求包装,一个ActionFilter
用于拦截某些请求并立即返回结果。
ScalaActionsComposition更详细地描述了这些特征。