Spring Boot @ControllerAdvice全局异常处理器失效,抛异常返回500错误求助
问题排查与解决方案
首先,我注意到你使用的是Spring WebFlux(依赖里的spring-boot-starter-webflux),但你的全局异常处理器用的是适用于Spring MVC的@ControllerAdvice + @RestController组合——这是核心问题!WebFlux作为响应式框架,它的异常处理机制和MVC不一样,普通的@ControllerAdvice无法拦截WebFlux请求链中的异常,所以才会返回默认的500错误。
下面是具体的修复步骤:
1. 改用WebFlux兼容的异常处理器注解
把@ControllerAdvice + @RestController替换为@RestControllerAdvice,这是WebFlux和MVC都支持的注解,但在WebFlux环境下会自动适配响应式处理逻辑。同时,你的异常处理方法需要返回响应式类型(Mono<ResponseEntity<ExceptionResponse>>),而不是直接返回ResponseEntity。
修改后的处理器代码示例:
@RestControllerAdvice class CustomExceptionController { private val logger = LoggerFactory.getLogger(javaClass.name) enum class ErrorKeys { SENSOR_TYPE_NOT_FOUND // 补充你的枚举值 } // 先处理自定义异常,优先级高于通用Exception处理 @ExceptionHandler(SensorTypeNotFoundException::class) fun handleSensorTypeNotFound(ex: SensorTypeNotFoundException): Mono<ResponseEntity<ExceptionResponse>> { logger.error("Sensor type not found: ${ex.message}") return Mono.just( buildResponse( ex.message, ErrorKeys.SENSOR_TYPE_NOT_FOUND, HttpStatus.NOT_FOUND ) ) } // 通用异常兜底处理 @ExceptionHandler(Exception::class) fun handleGenericException(ex: Exception): Mono<ResponseEntity<ExceptionResponse>> { logger.error("Unhandled exception", ex) return Mono.just( buildResponse( "Internal server error", ErrorKeys.GENERIC_ERROR, // 补充对应的枚举值 HttpStatus.INTERNAL_SERVER_ERROR ) ) } private fun buildResponse( message: String?, errorKey: ErrorKeys, httpStatus: HttpStatus ): ResponseEntity<ExceptionResponse> { val response = ExceptionResponse( // 假设你的ExceptionResponse有这些字段 message = message, errorCode = errorKey.name, timestamp = System.currentTimeMillis() ) return ResponseEntity(response, httpStatus) } }
2. 确保异常在WebFlux响应式链中抛出
如果你是在非响应式代码块中抛出异常(比如普通方法里直接throw),WebFlux可能无法将其传递给异常处理器。确保你的异常是在Mono或Flux的操作链中抛出,比如:
// 正确的方式:在Mono中抛出异常 fun getSensorType(typeId: String): Mono<SensorType> { return sensorRepository.findById(typeId) .switchIfEmpty(Mono.error(SensorTypeNotFoundException("Sensor type $typeId not found"))) }
3. 升级Spring Boot版本(可选但强烈推荐)
你当前使用的Spring Boot 2.1.6.RELEASE是非常老旧的版本(已经停止维护多年),存在不少已知问题和安全漏洞。建议升级到稳定的维护版本,比如2.7.x系列(兼容Kotlin 1.6+),修改build.gradle.kts中的版本:
plugins { id("org.springframework.boot") version "2.7.15" id("io.spring.dependency-management") version "1.0.15.RELEASE" kotlin("jvm") version "1.6.21" kotlin("plugin.spring") version "1.6.21" }
验证要点
- 启动应用后,触发
SensorTypeNotFoundException,检查返回的HTTP状态码是否为404(NOT_FOUND),并且返回你自定义的ExceptionResponse结构。 - 查看日志,确认异常处理器的
logger是否打印了对应的错误信息,说明处理器已经被触发。
内容的提问来源于stack exchange,提问作者JetBrains
相关产品推荐
相关产品推荐

