Spring Boot @ExceptionHandler处理IllegalArgumentException部分场景不生效问题
问题原因
@ControllerAdvice仅能捕获进入Spring MVC请求处理链路后的异常:也就是请求已经被DispatcherServlet接收,分发到Controller执行业务逻辑的整个流程中抛出的异常,你业务代码抛出的IllegalArgumentException就属于这个范围,所以可以正常处理。- 请求头过大抛出的
IllegalArgumentException是Tomcat容器层抛出的:发生在Tomcat解析HTTP请求头的阶段,此时请求还没传递到Spring的DispatcherServlet,完全处于Spring MVC的处理流程之外,所以@ControllerAdvice无法捕获该异常。
解决方案
你可以通过自定义Spring Boot全局错误控制器来统一处理所有容器层、框架层、业务层的异常,实现返回格式统一:
步骤1:实现ErrorController接口
编写自定义错误控制器,替换Spring Boot默认的BasicErrorController,代码示例:
@RestController class CustomErrorController : ErrorController { @RequestMapping("/error") fun handleError(request: HttpServletRequest): ResponseEntity<Any> { val status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE) as? Int ?: HttpStatus.INTERNAL_SERVER_ERROR.value() val exception = request.getAttribute(RequestDispatcher.ERROR_EXCEPTION) as? Throwable // 处理请求头过大的场景 if (exception is IllegalArgumentException && exception.message == "Request header is too large") { return ResponseEntity .status(MyManError.BAD_PARAM_VALIDATION.status) .body( Error( FaultDefinition( MyManError.BAD_PARAM_VALIDATION.code, MyManError.BAD_PARAM_VALIDATION.name, "'请求头大小超出限制'", "Source Name: ${Security.getUserName()}", null ) ) ) } // 其他错误场景也可以在这里统一处理 return ResponseEntity.status(status).body( Error( FaultDefinition( code = status * 100, name = HttpStatus.valueOf(status).reasonPhrase, description = exception?.message ?: "未知错误", source = "Source Name: ${Security.getUserName()}", null ) ) ) } }
步骤2:可选配置
如果需要调整Tomcat的错误映射规则,或者修改请求头大小限制的阈值,可以在application.yml中添加配置:
server: max-http-header-size: 10KB error: path: /error # 对应自定义错误控制器的请求路径
这样配置后,所有容器层抛出的错误也会进入你自定义的错误处理逻辑,返回和业务异常统一格式的响应。
内容的提问来源于stack exchange,提问作者Wicaledon
相关产品推荐
相关产品推荐

