Spring Boot中@ControllerAdvice致Swagger异常响应展示错误的解决问询
解决Swagger全局异常响应重复展示的问题
你的问题核心是Swagger默认会把@RestControllerAdvice中定义的所有异常处理逻辑,统一附加到每个接口的响应文档里,而不管接口实际是否会抛出对应异常。下面给你几种可行的解决思路:
1. 手动给接口标注专属响应
直接在每个Controller的方法上用Swagger的@ApiResponses或@ApiResponse注解,明确指定该接口可能返回的异常响应,覆盖全局的默认行为。
示例代码:
@RestController @RequestMapping("/foo") class FooController(private val fooService: FooService) { @ApiResponses( value = [ ApiResponse(responseCode = "409", description = "Foo冲突异常"), ApiResponse(responseCode = "200", description = "操作成功") ] ) fun makeFoo() { fooService.makeFoo() } } @RestController @RequestMapping("/bar") class BarController(private val barService: BarService) { @ApiResponses( value = [ ApiResponse(responseCode = "422", description = "Bar处理异常"), ApiResponse(responseCode = "200", description = "操作成功") ] ) fun makeBar() { barService.makeBar() } }
这种方式最直接,适合接口数量不多的场景,能精准控制每个接口的响应展示。
2. 自定义Swagger处理器自动过滤响应
通过实现Swagger的OperationCustomizer接口,自动分析接口方法可能抛出的异常,过滤掉全局异常处理器中不匹配的响应。
首先整理全局异常和状态码的映射关系,再在自定义处理器里对比当前接口方法抛出的异常,只保留对应的响应:
@Component class ExceptionResponseFilter : OperationCustomizer { // 定义全局异常与状态码的映射 private val exceptionStatusMap = mapOf( FooException::class.java to HttpStatus.CONFLICT.value().toString(), BarException::class.java to HttpStatus.UNPROCESSABLE_ENTITY.value().toString() ) override fun customize(operation: Operation, handlerMethod: HandlerMethod): Operation { // 获取当前方法声明抛出的异常类型 val declaredExceptions = handlerMethod.method.declaredExceptions // 过滤掉不匹配的响应,保留200和对应异常的状态码 operation.responses = operation.responses.filter { entry -> entry.key == "200" || declaredExceptions.any { ex -> exceptionStatusMap[ex] == entry.key } }.toMutableMap() return operation } }
这种方式适合接口较多的场景,无需逐个手动标注,自动完成响应过滤。注意要确保方法签名上声明了抛出对应异常,否则无法获取到declaredExceptions。
3. 拆分全局异常处理器为局部绑定
把原来的全局@RestControllerAdvice拆分为多个和特定Controller绑定的异常处理器,Swagger会自动把对应的异常响应只关联到绑定的Controller接口上。
示例代码:
// 仅处理FooController的异常 @RestControllerAdvice(assignableTypes = [FooController::class]) class FooExceptionHandler { @ExceptionHandler(FooException::class) @ResponseStatus(HttpStatus.CONFLICT) fun handleFooException(exception: FooException): ErrorDto { return ErrorDto(HttpStatus.CONFLICT.value(), exception.message) } } // 仅处理BarController的异常 @RestControllerAdvice(assignableTypes = [BarController::class]) class BarExceptionHandler { @ExceptionHandler(BarException::class) @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY) fun handleBarException(exception: BarException): ErrorDto { return ErrorDto(HttpStatus.UNPROCESSABLE_ENTITY.value(), exception.message) } }
这种方式逻辑清晰,每个异常处理器只负责对应Controller的异常,Swagger会自动识别并关联对应的响应,无需额外配置。
内容的提问来源于stack exchange,提问作者darth jemico
相关产品推荐
相关产品推荐

