【问题标题】:Migrating to 2.6 How to get an I don't care BodyParser?迁移到 2.6 如何获得 I don't care BodyParser?
【发布时间】:2019-05-07 10:47:41
【问题描述】:

在 Play 2.6 之前,我有一些自定义操作,例如NoCache 操作,我只需要关心实现apply 方法,即

package actions

import play.api.http.HeaderNames
import play.api.mvc._
import scala.concurrent.Future

/**
  * Custom Action composition implementation that disables client-side browser caching
  * by changing the response header of the response adding multi-browser no-cache
  * parameters. The composition can be done as follows:
  * {{{
  *
  *   def link = NoCache {
  *     deadbolt.SubjectPresent()() { implicit request =>
  *       Future {
  *         Ok(views.html.account.link(userService, auth))
  *       }
  *     }
  *   }
  *
  * }}}
  *
  * @param action The inner action
  * @tparam A Action type
  */
case class NoCache[A](action: Action[A]) extends Action[A] with HeaderNames {
  def apply(request: Request[A]): Future[Result] = {
    action(request).map { result =>
      result.withHeaders(
        (CACHE_CONTROL -> "no-cache, no-store, must-revalidate"),
        (PRAGMA -> "no-cache"),
        (EXPIRES -> "0")
      )
    }
  }
}  

现在在 Play 2.6 中我遇到了一堆错误,因为 Action 现在需要覆盖 executionContextparser。我在这个 2.6 中看不到任何东西,但更复杂,但无论如何......我设法使用 global 覆盖前者,但我看不到为后者提供简单实现的方法。

如何为我的自定义 Action 指定我不关心的 BodyParser

import scala.concurrent.ExecutionContext.Implicits.global

override def executionContext = global
override val parser: BodyParser[A] = null // <<<<<< what else here?

【问题讨论】:

标签: scala playframework playframework-2.6


【解决方案1】:

有一个section on the migration guide关于它:

Scala ActionBuilder trait 已被修改为将 body 的类型指定为类型参数,并添加一个抽象解析器成员作为默认的 body 解析器。您需要修改 ActionBuilder 并直接传递正文解析器。

它的措辞可能会更好,但无论如何,“传递正文解析器”的方式是使用依赖注入。比如来自actions composition docs

import play.api.mvc._

class LoggingAction @Inject() (parser: BodyParsers.Default)(implicit ec: ExecutionContext) extends ActionBuilderImpl(parser) {
  override def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
    Logger.info("Calling action")
    block(request)
  }
}

然后你将你的动作注入你的控制器:

class MyController @Inject()(
  loggingAction: LoggingAction,
  cc: ControllerComponents
) extends AbstractController(cc) {

  def index = loggingAction {
    Ok("Hello World")
  }

}

当然,您可以在 NoCache 操作中使用相同的方法:

import play.api.mvc._
import scala.concurrent._
import play.api.http.HeaderNames._

class NoCache @Inject() (parser: BodyParsers.Default)(implicit ec: ExecutionContext) extends ActionBuilderImpl(parser) {
  override def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
    block(request).map { res => res.withHeaders(
      (CACHE_CONTROL -> "no-cache, no-store, must-revalidate"),
      (PRAGMA -> "no-cache"),
      (EXPIRES -> "0")
    )}
  }
}

另外,如您所见,我们没有使用全局执行上下文,而是使用依赖注入可用的上下文。这是应用程序的默认执行上下文,因此如果需要,它是easier to configure

【讨论】:

    【解决方案2】:

    查看BodyParser 的实现,您可以给出BodyParser.Empty 的值

    override val parser: BodyParser[A] = BodyParser.Empty
    

    https://www.playframework.com/documentation/2.6.7/api/java/play/mvc/BodyParser.html

    【讨论】:

    • 谢谢!但这会产生错误,因为在这里您将一个类分配给一个变量。真正的答案应该是override val parser: BodyParser[A] = new play.mvc.BodyParser.Empty().asInstanceOf[BodyParser[A]]
    猜你喜欢
    • 2016-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多