You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala中Play框架自定义Error Handler未生效问题求助

问题解决方法

你的问题根源在于编译时依赖注入模式下,Play不会读取play.http.errorHandler配置项,必须在自定义的Components类中显式覆盖httpErrorHandler成员才能生效。

修改步骤

  1. 修改MyComponents类,替换原有的customErrorHandler定义,直接override框架提供的httpErrorHandler:
class MyComponents(context: Context, system: ActorSystem)
    extends BuiltInComponentsFromContext(context)
    with CORSComponents
    with EhCacheComponents
    with GzipFilterComponents {
    ...
    override val httpFilters: Seq[EssentialFilter] = Seq(corsFilter, requestsCounterFilter, gzipFilter)
    ...
    // 显式覆盖httpErrorHandler,替换为自定义实现
    override lazy val httpErrorHandler: HttpErrorHandler = new CustomErrorHandler()

    lazy val myRoutesV1 = new myapp_V1.Routes(httpErrorHandler, myControllerV1)
    lazy val myRoutesV2 = new myapp_v2.Routes(httpErrorHandler, myControllerV2)  
    lazy val router = new Routes(httpErrorHandler, myRoutesV1, myRoutesV2)
}
  1. 可以删除application.conf中的play.http.errorHandler = "services.cx.CustomErrorHandler"配置,因为编译时依赖注入模式下该配置不会被框架读取。

原因说明

使用编译时依赖注入(自定义ApplicationLoader和Components)时,Play的核心组件均通过Components类手动构建,而非从配置文件自动加载。BuiltInComponentsFromContext默认提供DefaultHttpErrorHandler作为全局错误处理器,因此必须显式覆盖httpErrorHandler成员才能替换为自定义实现。

你之前仅在Routes构造器中传入customErrorHandler,这仅影响路由层面的错误处理,控制器中抛出的未捕获全局异常仍会使用Components中默认的DefaultHttpErrorHandler。


原始问题背景

已按照Play框架文档实现自定义错误处理器,并在application.conf中添加相关配置,但触发除零异常时,日志显示仍在使用DefaultHttpErrorHandler:

play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[ArithmeticException: / by zero]]
at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:255)
at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:180)

相关代码及配置详情

自定义错误处理器代码

package services.cx

import org.slf4j.LoggerFactory
import play.api.http.HttpErrorHandler
import play.api.mvc.Results._
import play.api.mvc._

import javax.inject._
import scala.concurrent._

@Singleton
class CustomErrorHandler extends HttpErrorHandler {
  lazy val logger = LoggerFactory.getLogger("myLogger")

  override def onClientError(request: RequestHeader, statusCode: Int, message: String) = {
    Future.successful(
      Status(statusCode)("A client error occurred: " + message)
    )
  }

  override def onServerError(request: RequestHeader, exception: Throwable) = {
    logger.error(
      "onServerError Exception occurred And logged In Error Handler and Exception is " + exception.getMessage
    )
    exception.printStackTrace()
    Future.successful(
      InternalServerError("A server error occurred: " + exception.getMessage)
    )
  }
}

application.conf配置

play.http.errorHandler = "services.cx.CustomErrorHandler"
play.application.loader = MyLoader

自定义ApplicationLoader代码

import org.slf4j.LoggerFactory
import play.api.ApplicationLoader.Context
import play.filters.cors.CORSComponents
import play.api.mvc.EssentialFilter
import play.filters.gzip.GzipFilterComponents
...

class MyLoader extends ApplicationLoader {
  def load(context: Context) = {
    LoggerConfigurator(context.environment.classLoader).foreach {
      _.configure(context.environment)
    }
    val actorSystem = ActorSystem.create()
    new MyComponents(context, actorSystem).application
  }
}

class MyComponents(context: Context, system: ActorSystem)
    extends BuiltInComponentsFromContext(context)
    with CORSComponents
    with EhCacheComponents
    with GzipFilterComponents {
    ...
    override val httpFilters: Seq[EssentialFilter] = Seq(corsFilter, requestsCounterFilter, gzipFilter)
    ...
    lazy val customErrorHandler = new CustomErrorHandler()

    lazy val myRoutesV1 = new myapp_V1.Routes(customErrorHandler, myControllerV1)
    lazy val myRoutesV2 = new myapp_v2.Routes(customErrorHandler, myControllerV2)  
    lazy val router = new Routes(customErrorHandler, myRoutesV1, myRoutesV2)
}

使用环境

  • Play框架版本2.6
  • Scala版本2.11
  • 采用编译时依赖注入

内容的提问来源于stack exchange,提问作者aditt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 04:05:59