如何在使用ActionBuilder时链接自定义操作

时间:2014-06-28 16:13:21

标签: scala playframework

尝试更好地了解使用操作构建器创建自定义操作。

我有一个自定义操作:

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)
  }
}
  1. 我是否可以创建另一个类似于上面的自定义操作,它继承自上面的操作,并在其上构建,即在操作中链并访问用户对象

    e.g。假设我现在在我的网站上为管理员创建一个新部分,所以我在这个新操作中检查用户对象:  user.isAdmin

    如果isAdmin为false,则使用Future.successful(Forbidden)调用重定向。

    所以我会基于LogginInRequest创建LoggedInAdmin,但只是检查属性isAdmin(这只是一个例子,但我想知道我是否可以这样做)。

  2. 是否可以将参数传递给我使用动作构建器创建的自定义操作,以便我可以执行此操作?

    def someAction(...):= MyCustomActionBuilder(userService){    // ... }

  3. 即。我正在向它提出一个论点。

1 个答案:

答案 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更详细地描述了这些特征。