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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:42:18