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

如何在Springdoc OpenAPI中针对特定端点隐藏全局异常处理器的403响应

问题背景

现有一个Spring Boot应用,异常处理逻辑通过通用@ControllerAdvice和多个@ExceptionHandler实现,示例如下:

@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {
    @ResponseStatus(HttpStatus.FORBIDDEN) // 403
    @ExceptionHandler(AccessDeniedCustomException.class)
    public ResponseEntity<Object> handleAccessDeniedException(Exception ex, WebRequest request) {
        ...
    }

    @ResponseStatus(HttpStatus.NOT_FOUND) // 404
    @ExceptionHandler(NotFoundCustomException.class)
    public ResponseEntity<Object> handleNotFoundException(Exception ex, WebRequest request) {
        ...
    }
}

当前配置下,Springdoc OpenAPI生成的OpenAPI YAML文件会为所有端点附带403、404的响应定义。
已知在异常处理方法上添加@Hidden注解会全局移除该响应码,不符合需求,需要实现仅对部分特定端点隐藏403响应的效果。

实现方案

方案一:通过端点本地注解覆盖全局响应配置

Springdoc的响应配置优先级为:端点方法上声明的@ApiResponse > 全局通过@ControllerAdvice扫描生成的异常响应定义。
针对单个或少量需要隐藏403的端点,直接在端点方法上显式声明所有需要展示的响应码,不包含403即可覆盖全局配置。
示例:

@RestController
public class DemoController {
    // 该端点需要隐藏403响应定义
    @GetMapping("/public/content")
    @Operation(
            summary = "公开内容接口",
            responses = {
                    @ApiResponse(responseCode = "200", description = "请求成功"),
                    @ApiResponse(responseCode = "404", description = "资源不存在")
                    // 未声明403响应,全局的403定义不会被合并到该端点的文档中
            }
    )
    public String getPublicContent() {
        return "content";
    }
}

方案二:自定义标记注解 + OpenAPI全局过滤器批量处理

如果需要批量为大量端点隐藏403响应,逐字逐句写@ApiResponse配置过于冗余,可以通过自定义注解配合OpenAPI扩展能力实现批量处理:

  1. 定义自定义标记注解,用于标记需要隐藏403的端点或整个控制器类:
    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface IgnoreForbiddenDoc {
    }
    
  2. 实现OpenApiCustomizer接口,在OpenAPI文档生成完成前,遍历所有路径配置,对打了标记注解的端点,从响应列表中移除403定义:
    @Component
    public class ForbiddenDocExcludeCustomizer implements OpenApiCustomizer {
        @Autowired
        private RequestMappingHandlerMapping requestMappingHandlerMapping;
    
        @Override
        public void customise(OpenAPI openApi) {
            // 遍历所有接口映射,匹配带标记注解的端点
            requestMappingHandlerMapping.getHandlerMethods().forEach((mappingInfo, handlerMethod) -> {
                // 检查方法或所属类上是否存在标记注解
                boolean needExclude = handlerMethod.hasMethodAnnotation(IgnoreForbiddenDoc.class)
                        || handlerMethod.getBeanType().isAnnotationPresent(IgnoreForbiddenDoc.class);
                if (!needExclude) {
                    return;
                }
                // 获取匹配的OpenAPI路径项
                String path = mappingInfo.getPatternValues().stream().findFirst().orElse(null);
                PathItem pathItem = openApi.getPaths().get(path);
                if (pathItem == null) {
                    return;
                }
                // 移除该路径下所有操作的403响应定义
                pathItem.readOperations().forEach(operation -> {
                    operation.getResponses().remove("403");
                });
            });
        }
    }
    
注意事项
  • 两种方案都不会影响未标记端点的403响应文档展示,完全避免了在全局异常处理器上加@Hidden导致的全局屏蔽问题
  • 方案一适合少量定制化端点场景,配置轻量无额外代码逻辑;如果遇到Springdoc版本差异导致全局403仍然被自动合并到端点文档的情况,直接使用方案二即可100%达成效果
  • 方案二适合批量标记的场景,只需要在需要隐藏403的端点或控制器类上加@IgnoreForbiddenDoc注解即可,维护成本更低

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.25 09:24:04