Play 2.6 Messages迁移问题:自定义错误处理器报隐式Messages实例未找到
解决Play 2.6迁移中自定义ErrorHandler的
An implicit Messages instance was not found错误 我刚帮同事处理过类似的Play版本迁移问题,你的情况很典型——Play 2.6在国际化消息的处理逻辑上做了不小调整,尤其是隐式Messages实例的获取方式,和2.5差异很大。
先拆解问题根源:Play 2.6里,Messages不再是全局隐式可用的了,它必须和当前请求的语言偏好绑定。你虽然注入了MessagesApi并混入了I18nSupport,但ErrorHandler的默认处理方法里并没有自动帮你把RequestHeader转换成隐式上下文,所以编译器找不到需要的隐式Messages实例。
下面给你两种可行的解决方案,选哪种看你的代码习惯:
方案一:手动创建Messages实例(直观易懂)
在你重写的错误处理方法里,直接用注入的messagesApi结合RequestHeader生成Messages实例,然后显式使用或者传递给视图:
class ErrorHandler @Inject()( env: Environment, conf: Configuration, sourceMapper: OptionalSourceMapper, router: Provider[Router], override val messagesApi: MessagesApi ) extends DefaultHttpErrorHandler(env, conf, sourceMapper, router) { override def onClientError(request: RequestHeader, statusCode: Int, message: String): Future[Result] = { // 从请求中获取符合语言偏好的Messages实例 val messages = messagesApi.preferred(request) // 示例:用Messages获取国际化错误消息,返回视图 val errorContent = views.html.errors.clientError(statusCode, messages("error.client.generic")) Future.successful(Results.Status(statusCode)(errorContent)) } // 重写其他错误处理方法(比如onServerError)同理 override def onServerError(request: RequestHeader, exception: Throwable): Future[Result] = { val messages = messagesApi.preferred(request) val errorMsg = messages("error.server.internal") Future.successful(Results.InternalServerError(errorMsg)) } }
这种方式不需要依赖I18nSupport,逻辑清晰,适合刚迁移过来的开发者快速上手。
方案二:利用I18nSupport简化代码
如果你习惯用I18nSupport提供的隐式Messages,只需要在重写的方法里把RequestHeader转为隐式变量就行——I18nSupport会自动结合你注入的messagesApi和隐式的RequestHeader生成Messages实例:
class ErrorHandler @Inject()( env: Environment, conf: Configuration, sourceMapper: OptionalSourceMapper, router: Provider[Router], override val messagesApi: MessagesApi ) extends DefaultHttpErrorHandler(env, conf, sourceMapper, router) with I18nSupport { override def onClientError(request: RequestHeader, statusCode: Int, message: String): Future[Result] = { // 把RequestHeader声明为隐式变量 implicit val req: RequestHeader = request // 现在可以直接用隐式Messages了,比如调用messages("error.404") val errorView = views.html.errors.notFound() // 视图里如果需要隐式Messages,这里会自动传递 Future.successful(Results.NotFound(errorView)) } }
注意:如果你的视图模板依赖隐式Messages,这种方式会自动把生成的Messages传递过去,不需要手动写参数。
关键提醒
不管用哪种方案,核心都是:Play 2.6的Messages是请求上下文相关的,必须从当前请求的语言偏好生成,再也不能像2.5那样依赖全局隐式实例了。
内容的提问来源于stack exchange,提问作者felixoi
相关产品推荐
相关产品推荐

