迁移到 2.6 如何获得一个我不关心的 BodyParser?

Migrating to 2.6 How to get an I don't care BodyParser?

在 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?

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

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

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

关于它有一个section on the migration guide

The Scala ActionBuilder trait has been modified to specify the type of the body as a type parameter, and add an abstract parser member as the default body parsers. You will need to modify your ActionBuilders and pass the body parser directly.

措辞可能更好,但无论如何,您 "pass the body parser" 的方式是使用依赖注入。例如,来自 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