[英]Play Framework 2.2 action composition returning a custom object
我正在嘗試創建一個自定義的play.api.mvc.Action
,它可用於根據請求填充CustomerAccount
並將CustomerAccount
傳遞給控制器。
在Play 2.2.x的文檔之后,我創建了一個Action
和ActionBuilder
但我似乎無法從操作中返回CustomerAccount
。
我目前的代碼是:
case class AccountWrappedRequest[A](account: CustomerAccount, request: Request[A]) extends WrappedRequest[A](request)
case class Account[A](action: Action[A]) extends Action[A] {
lazy val parser = action.parser
def apply(request: Request[A]): Future[SimpleResult] = {
AccountService.getBySubdomain(request.host).map { account =>
// Do something to return the account like return a new AccountWrappedRequest?
action(AccountWrappedRequest(account, request))
} getOrElse {
Future.successful(NotFound(views.html.account_not_found()))
}
}
}
object AccountAction extends ActionBuilder[AccountWrappedRequest] {
def invokeBlock[A](request: Request[A], block: (AccountWrappedRequest[A]) => Future[SimpleResult]) = {
// Or here to pass it to the next request?
block(request) // block(AccountWrappedRequest(account??, request))
}
override def composeAction[A](action: Action[A]) = Account(action)
}
注意:這將無法編譯,因為block(request)
函數需要一種我無法填充的AccountWrappedRequest
類型。 它將在使用直接Request
時進行編譯
最終,我希望能夠將此帳戶操作與身份驗證操作相結合,以便可以將CustomerAccount
傳遞到身份驗證操作,並且可以根據該客戶的帳戶提供用戶身份驗證。 然后我想將客戶帳戶和用戶傳遞給控制器。
例如:
Account(Authenticated(Action))) { request => request.account; request.user ... }
Account(Authenticated(Action))) { request => request.account; request.user ... }
或更好的作為不需要自定義請求對象的單個對象。
我不確定這是否是最好的方法,但我設法提出了一個似乎運作良好的解決方案。
關鍵是匹配請求將其轉換為AccountWrappedRequest
內的invokeBlock
然后再將其傳遞給下一個請求。 如果鏈中的另一個Action期望來自鏈中較早操作的值,則可以類似地將請求轉換為您需要訪問請求參數的類型。
從原始問題更新示例:
case class AccountWrappedRequest[A](account: CustomerAccount, request: Request[A]) extends WrappedRequest[A](request)
case class Account[A](action: Action[A]) extends Action[A] {
lazy val parser = action.parser
def apply(request: Request[A]): Future[SimpleResult] = {
AccountService.getBySubdomain(request.host).map { account =>
action(AccountWrappedRequest(account, request))
} getOrElse {
Future.successful(NotFound(views.html.account_not_found()))
}
}
}
object AccountAction extends ActionBuilder[AccountWrappedRequest] {
def invokeBlock[A](request: Request[A], block: (AccountWrappedRequest[A]) => Future[SimpleResult]) = {
request match {
case req: AccountRequest[A] => block(req)
case _ => Future.successful(BadRequest("400 Invalid Request"))
}
}
override def composeAction[A](action: Action[A]) = Account(action)
}
然后在另一個Action(在我的情況下為Authenticated操作apply()
的apply()
方法內部,您可以類似地執行:
def apply(request: Request[A]): Future[SimpleResult] = {
request match {
case req: AccountRequest[A] => {
// Do something that requires req.account
val user = User(1, "New User")
action(AuthenticatedWrappedRequest(req.account, user, request))
}
case _ => Future.successful(BadRequest("400 Invalid Request"))
}
}
您可以在ActionBuilder中將操作鏈接在一起
override def composeAction[A](action: Action[A]) = Account(Authenticated(action))
如果然后將AuthenticatedWrappedRequest
傳遞給控制器,則可以訪問request.account
, request.user
和所有常用請求參數。
正如您所看到的,有幾種情況下響應未知會產生BadRequest
。 實際上,就我所知,這些應該永遠不會被調用,但它們只是在那里。
我很想得到關於這個解決方案的一些反饋,因為我對Scala還是比較新的,我不確定是否有更好的方法來做同樣的結果,但我希望這對某人也有用。
我寫了一個獨立的小(ish)示例來完成你正在尋找的東西:
https://github.com/aellerton/play-login-example
我放棄了嘗試使用play框架中存在的Security
類。 我相信他們很好,但我無法理解他們。
簡要指南......
在示例代碼中,控制器聲明為使用AuthenticatedRequests
特征:
object UserSpecificController extends Controller with AuthenticatedRequests {
...
}
使用RequireAuthentication
操作強制任何頁面要求身份驗證(或重定向以獲取它):
def authenticatedIndex = RequireAuthentication { implicit request: AuthenticatedRequest[AnyContent] =>
Ok("This content will be accessible only after logging in)
}
使用AbandonAuthentication
操作完成AbandonAuthentication
:
def signOut = AbandonAuthentication { implicit request =>
Ok("You're logged out.").withNewSession
}
請注意,為此,您必須覆蓋AuthenticatedRequests
特征中的方法,例如:
override def authenticationRequired[A](request: Request[A]): Future[SimpleResult] = {
Future.successful(
Redirect(routes.LoginController.showLoginForm).withSession("goto" -> request.path)
)
}
還有更多; 最好看看代碼。
HTH安德魯
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.