gpt4 book ai didi

scala - Play Framework 2.2 Action 组合返回自定义对象

转载 作者:行者123 更新时间:2023-12-02 07:52:25 25 4
gpt4 key购买 nike

我正在尝试创建一个自定义的 play.api.mvc.Action ,它可用于根据请求填充 CustomerAccount 并传递 CustomerAccount 进入 Controller 。

遵循documentation for Play 2.2.x我已经创建了 ActionActionBuilder 但我似乎无法从操作中返回 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 传递到身份验证操作中,并可以根据该客户的帐户提供用户身份验证。然后我想将客户帐户和用户传递到 Controller 中。

例如:

帐户(已验证(操作))){ request => request.account; request.user ... } 或者更好的是作为不需要自定义请求对象的单独对象。

最佳答案

我不确定这是否是最好的方法,但我已经设法想出了一个似乎效果很好的解决方案。

关键是匹配请求,将其转换为 invokeBlock 内的 AccountWrappedRequest,然后再将其传递给下一个请求。如果链中的另一个操作需要链中较早操作的值,则您可以类似地匹配请求,将其转换为访问请求参数所需的类型。

更新原始问题的示例:

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)
}

然后在另一个操作(在我的例子中是经过身份验证的操作)的 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 传递到 Controller 中,您将可以访问 request.accountrequest.user 和所有常用的请求参数.

如您所见,在某些情况下响应未知,这会生成 BadRequest。事实上,据我所知,这些永远不应该被调用,但它们就在那里以防万一。

我很想得到一些关于这个解决方案的反馈,因为我对 Scala 还很陌生,我不确定是否有更好的方法来达到相同的结果,但我希望这对也有人。

关于scala - Play Framework 2.2 Action 组合返回自定义对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19773582/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com