[英]Play: How to implement action composition
鑒於后續的ActionBuilder
實現:
class SignedRequest[A](request: Request[A]) extends WrappedRequest[A](request) {}
object SignedAction extends ActionBuilder[SignedRequest] {
def invokeBlock[A](request: Request[A], block: SignedRequest[A] => Future[SimpleResult]) = {
block(new SignedRequest(request))
}
}
class SecuredRequest[A](request: Request[A]) extends WrappedRequest[A](request) {}
object SecuredRequest extends ActionBuilder[SecuredRequest] {
def invokeBlock[A](request: Request[A], block: SecuredRequest[A] => Future[SimpleResult]) = {
block(new SecuredRequest(request))
}
}
我如何組合它們? 我試過以下......
object MyController extends Controller {
def doSomething = SignedAction.async(parse.json) {
SecuredAction.async(parse.json) { implicit request =>
Future.successful(Ok)
}}
}
...但我總是收到以下錯誤消息:
/home/j3d/test/controllers/MyController.scala:37: type mismatch;
[error] found : play.api.mvc.Action[play.api.libs.json.JsValue]
[error] required: scala.concurrent.Future[play.api.mvc.SimpleResult]
[error] SecuredAction.async(parse.json) {
^
我錯過了什么嗎? TX。
函數async
期待Future[SimpleResult]
,但是嵌套的SecuredAction.async
將Action
返回到頂部SignedAction.async
(請注意,在示例代碼中,您省略了將請求聲明為class
並且SignedAction
被聲明兩次)。
您可以通過將其應用於簽名請求來在SignedAction
組合嵌套SecuredAction
結果。
package controllers
import scala.concurrent.Future
import play.api._
import play.api.mvc._
case class SignedRequest[A](request: Request[A])
extends WrappedRequest[A](request) {}
object SignedAction extends ActionBuilder[SignedRequest] {
def invokeBlock[A](request: Request[A],
block: SignedRequest[A] => Future[Result]) =
block(new SignedRequest(request))
}
case class SecuredRequest[A](request: Request[A])
extends WrappedRequest[A](request) {}
object SecuredAction extends ActionBuilder[SecuredRequest] {
def invokeBlock[A](request: Request[A],
block: SecuredRequest[A] => Future[Result]) =
block(new SecuredRequest(request))
}
object MyController extends Controller {
def doSomething = SignedAction.async(parse.json) { signedReq =>
SecuredAction.async(parse.json) { implicit securedReq =>
Future.successful(Ok)
} apply signedReq
}
}
這樣的動作組合也可以在沒有ActionBuilder
情況下完成(這會導致一些額外的復雜性)。
package controllers
import scala.concurrent.Future
import play.api._
import play.api.mvc._
case class SignedRequest[A](request: Request[A])
case class SecuredRequest[A](request: Request[A])
object MyController extends Controller {
def Signed[A](bodyParser: BodyParser[A])(signedBlock: SignedRequest[A] => Future[Result]): Action[A] = Action.async(bodyParser) { req =>
signedBlock(SignedRequest(req))
}
def Secured[A](bodyParser: BodyParser[A])(securedBlock: SecuredRequest[A] => Future[Result]): Action[A] = Action.async(bodyParser) { req =>
securedBlock(SecuredRequest(req))
}
def doSomething = Signed(parse.json) { signedReq =>
Secured(parse.json) { implicit securedReq =>
Future.successful(Ok)
} apply signedReq.request
}
}
組合也可以在Future[Result]
周圍完成:
package controllers
import scala.concurrent.Future
import play.api._
import play.api.mvc._
import play.api.libs.json.JsValue
case class SignedRequest[A](request: Request[A])
case class SecuredRequest[A](request: Request[A])
object MyController extends Controller {
def Signed[A](signedBlock: SignedRequest[A] => Future[Result])(implicit req: Request[A]): Future[Result] = signedBlock(SignedRequest(req))
def Secured[A](signedBlock: SecuredRequest[A] => Future[Result])(implicit req: Request[A]): Future[Result] = signedBlock(SecuredRequest(req))
def doSomething = Action.async(parse.json) { implicit req =>
Signed[JsValue] { signedReq =>
Secured[JsValue] { securedReq => Future.successful(Ok) }
}
}
}
使用action-zipper,您可以ActionBuilders
import jp.t2v.lab.play2.actzip._
object MyController extends Controller {
val MyAction = SignedAction zip SecuredAction
def doSomething = MyAction.async(parse.json) { case (signedReq, secureReqeq) =>
Future.successful(Ok)
}
}
Json解析只執行一次:)
簡化@applicius答案我認為可以在沒有Future的情況下完成,我認為async / Future是一個單獨的問題。
非常簡單地刪除期貨和異步,我們得到這個:
def signed[A](signedBlock: SignedRequest[A] => Result)(implicit req: Request[A]) = signedBlock(SignedRequest(req))
def secured[A](securedBlock: SecuredRequest[A] => Result)(implicit req: Request[A]) = securedBlock(SecuredRequest(req))
//the use is the same as with Futures except for no async
def doSomething = Action(parse.json) { implicit req =>
signed[JsValue] { signedReq => secured[JsValue] { securedReq =>
Ok
} } }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.