Spring Boot如何根据激活Profile分环境忽略Swagger URL
Swagger分环境隐藏接口实现方案
@ApiIgnore、@Hidden这类Swagger原生注解是文档初始化阶段就固定生效的,确实无法按运行环境差异化生效,下面是3种可直接落地的实现方案,覆盖不同场景需求:
方案1:自定义环境生效的隐藏注解(灵活度最高,推荐)
可以实现一个只在生产环境生效的隐藏标记注解,使用方式和原生@Hidden完全一致,仅在prod环境触发隐藏逻辑,非生产环境不生效:
- 第一步:定义自定义标记注解
import java.lang.annotation.*; // 可标记在方法、Controller类上 @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ProdHiddenApi { }
- 第二步:编写Swagger环境差异化配置,仅在prod环境加载接口隐藏逻辑
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.core.annotation.AnnotationUtils; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.service.OperationBuilderPlugin; import springfox.documentation.spi.service.contexts.OperationContext; import springfox.documentation.spring.web.plugins.Docket; import static springfox.documentation.builders.RequestHandlerSelectors.any; import static springfox.documentation.builders.PathSelectors.any; @Configuration public class SwaggerEnvConfig { // 非prod环境:加载所有接口,不做任何隐藏过滤 @Bean @Profile("!prod") public Docket nonProdDocket() { return new Docket(DocumentationType.OAS_30) .select() .apis(any()) .paths(any()) .build(); } // prod环境:注册自定义插件,扫描带@ProdHiddenApi的接口/类并隐藏 @Bean @Profile("prod") public OperationBuilderPlugin prodHiddenProcessor() { return new OperationBuilderPlugin() { @Override public void apply(OperationContext context) { // 检查接口方法上是否标记注解 boolean methodMarked = context.findAnnotation(ProdHiddenApi.class).isPresent(); // 检查接口所属Controller类上是否标记注解 boolean classMarked = AnnotationUtils.findAnnotation( context.getHandlerMethod().getBeanType(), ProdHiddenApi.class ) != null; if (methodMarked || classMarked) { context.operationBuilder().hidden(true); } } @Override public boolean supports(DocumentationType docType) { // 同时兼容Swagger2、OpenAPI3两种文档规范 return DocumentationType.SWAGGER_2.equals(docType) || DocumentationType.OAS_30.equals(docType); } }; } }
- 第三步:使用时仅需要在生产环境要隐藏的接口方法、或者整个Controller类上加上
@ProdHiddenApi即可,DEV/UAT环境下这些接口会正常展示在Swagger文档中,PROD环境自动隐藏。
如果项目用的是springdoc-openapi而不是旧版Springfox,逻辑完全一致,只需要把OperationBuilderPlugin换成springdoc提供的OpenApiCustomiser,判断handler上注解的逻辑不变即可。
方案2:按Profile配置Docket扫描规则(适合批量路径隐藏)
如果需要隐藏的接口有统一的路径/包名规则,比如所有内部接口都在/internal/**路径下、或者都存放在com.xxx.controller.internal包下,可以直接给不同环境配置不同的接口扫描范围,不需要额外自定义注解:
@Configuration public class SwaggerConfig { // prod环境只扫描对外开放的接口包,排除指定路径 @Bean @Profile("prod") public Docket prodDocket() { return new Docket(DocumentationType.OAS_30) .select() .apis(RequestHandlerSelectors.basePackage("com.xxx.controller.open")) .paths(PathSelectors.regex("^(?!/internal/).*$")) .build(); } // 非prod环境扫描所有接口 @Bean @Profile("!prod") public Docket nonProdDocket() { return new Docket(DocumentationType.OAS_30) .select() .apis(any()) .paths(any()) .build(); } }
这个方案配置成本最低,但是灵活度差,只适合规则统一的批量隐藏场景,无法精确到单个接口。
方案3:生产环境直接关闭Swagger(零代码,适合全量屏蔽场景)
如果生产环境完全不需要对外开放Swagger文档,不需要做部分接口的差异化展示,可以直接在生产环境的配置文件中关闭Swagger相关能力,不需要写任何过滤逻辑:application-prod.yml配置如下:
# Springfox版本配置 springfox: documentation: enabled: false # Springdoc-openapi版本配置 springdoc: api-docs: enabled: false swagger-ui: enabled: false
这个方案实现最简单,但是无法满足生产环境保留部分接口文档的需求,适合安全要求高、生产完全不暴露Swagger的团队。
内容的提问来源于stack exchange,提问作者vsk
相关产品推荐
相关产品推荐

