1. 前言
最近工作中需要到Knife4j, 加上自己的项目充电鸭上本来好的Knife4j文档突然不好使了,遇到的问题正好记录一下
2.个人网站遇到的问题
个人网站本来的事还挺好用的,经过我得一阵折腾之后,每次启动的时候都会报错空指针。Springboot版本是2.3.3.RELEASE
具体问题如下
java.lang.NullPointerException: null
at springfox.documentation.schema.Example.equals(Example.java:131) ~[springfox-core-3.0.0.jar!/:3.0.0]
at java.util.Objects.equals(Objects.java:59) ~[na:1.8.0_201]
at springfox.documentation.service.RequestParameter.equals(RequestParameter.java:132) ~[springfox-core-3.0.0.jar!/:3.0.0]
at java.util.HashMap.putVal(HashMap.java:635) ~[na:1.8.0_201]
at java.util.HashMap.put(HashMap.java:612) ~[na:1.8.0_201]
at java.util.HashSet.add(HashSet.java:220) ~[na:1.8.0_201]
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169) ~[na:1.8.0_201]
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_201]
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) ~[na:1.8.0_201]
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_201]
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382) ~[na:1.8.0_201]
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) ~[na:1.8.0_201]
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[na:1.8.0_201]
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) ~[na:1.8.0_201]
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_201]
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) ~[na:1.8.0_201]
at springfox.documentation.spring.web.readers.operation.OperationParameterReader.apply(OperationParameterReader.java:93) ~[springfox-spring-web-3.0.0.jar!/:3.0.0]
at springfox.documentation.spring.web.plugins.DocumentationPluginsManager.operation(DocumentationPluginsManager.java:144) ~[springfox-spring-web-3.0.0.jar!/:3.0.0]
at springfox.documentation.spring.web.readers.operation.ApiOperationReader.read(ApiOperationReader.java:72) ~[springfox-spring-web-3.0.0.jar!/:3.0.0]
at springfox.documentation.spring.web.scanners.CachingOperationReader.lambda$new$0(CachingOperationReader.java:43) ~[springfox-spring-web-3.0.0.jar!/:3.0.0]
at java.util.HashMap.computeIfAbsent(HashMap.java:1127) ~[na:1.8.0_201]
at springfox.documentation.spring.web.scanners.CachingOperationReader.read(CachingOperationReader.java:48) ~[springfox-spring-web-3.0.0.jar!/:3.0.0]
at springfox.documentation.spring.web.scanners.ApiDescriptionReader.read(ApiDescriptionReader.java:72) ~[springfox-spring-web-3.0.0.jar!/:3.0.0]
at springfox.documentation.spring.web.scanners.ApiListingScanner.scan(ApiListingScanner.java:169) ~[springfox-spring-web-3.0.0.jar!/:3.0.0]
at springfox.documentation.spring.web.scanners.ApiDocumentationScanner.scan(ApiDocumentationScanner.java:67) ~[springfox-spring-web-3.0.0.jar!/:3.0.0]
at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.scanDocumentation(AbstractDocumentationPluginsBootstrapper.java:96)[springfox-spring-web-3.0.0.jar!/:3.0.0]
at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.bootstrapDocumentationPlugins(AbstractDocumentationPluginsBootstrapper.java:82)[springfox-spring-web-3.0.0.jar!/:3.0.0]
at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:100)[springfox-spring-web-3.0.0.jar!/:3.0.0]
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182)[spring-context-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:53)[spring-context-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:360)[spring-context-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:158)[spring-context-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:122)[spring-context-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:895)[spring-context-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:554)[spring-context-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143)[spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758)[spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)[spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)[spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)[spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237)[spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)[spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at net.lesscoding.MainApp.main(MainApp.java:30)[classes!/:1.0-SNAPSHOT]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_201]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_201]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_201]
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)[charge_duck-1.0-SNAPSHOT.jar:1.0-SNAPSHOT]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)[charge_duck-1.0-SNAPSHOT.jar:1.0-SNAPSHOT]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)[charge_duck-1.0-SNAPSHOT.jar:1.0-SNAPSHOT]
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:58)[charge_duck-1.0-SNAPSHOT.jar:1.0-SNAPSHOT]
最开始以为是springfox版本的问题,然后将springfox从knife4j中排除,引入了新的springfox,结果问题依然存在
<!--knife swagger UI库--><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.3</version><exclusions><exclusion><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId></exclusion></exclusions></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version></dependency>
项目是也能正常启动,但是打开/doc.html就是会空白,什么都不展示,前端也会提示有一个
undefined
**最后在一个csdn老哥的文章下找到了问题,说是
@ApiModelProperty
中的value在同一个类或者父类里边有重复的了**,
文章暂时找不到了,等我想起来我在贴一下链接,最后把所有的
@ApiModelProperty
都注释了先,启动一下果然能用了。
3.公司项目遇到的问题
公司项目整合Knife4j,权限框架用的是SpringSecurity,CAS认证具体是啥我还没明白哈哈哈,Springboot版本
然后我就开开心心的放行了资源 2.6.6
@Configuration@EnableWebSecurity@EnableGlobalMethodSecurity(prePostEnabled =true)publicclassCasSecurityConfigextendsWebSecurityConfigurerAdapter{// knife4j 资源String[] IGNORE_URL_ARRAY ={"/swagger-resources","/v2/api-docs","/doc.html","/webjars/**","/favicon.ico"};@Overrideprotectedvoidconfigure(HttpSecurity http)throwsException{
http.cors().and().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().httpBasic().disable().addFilterBefore(tokenBasedAuthenticationFilter(casProperties),AnonymousAuthenticationFilter.class).authorizeRequests().antMatchers(IGNORE_URL_ARRAY).permitAll().anyRequest().authenticated().and().formLogin().disable();}}
美滋滋的打开localhost:8000/doc.html一看
/swagger-resources
和
/swagger-resources/xxx(具体忘了)
404了,
然后更改一下放行资源为
/swagger-resources/**
直接
/swagger-resources/xxx(403)
,
/swagger-resources(404)
了
又是一阵折腾之后发现 Springboot2.6.0版本以后需要修改配置文件才行,不然会出现各种奇怪的问题
具体的报错信息已经忘记了,下次有记录更新,改成下边这种形式就好了
spring:mvc:pathmatch:# 切勿更改此配置,否则knife4j将报错404matching-strategy: ant_path_matcher
4. 新项目遇到的新问题
项目环境依赖来瞅一眼,
SpringBoot 2.6.4
、
SpringCloud 2021.0.7
、
knife4j 3.0.3
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.4</version><relativePath/><!-- lookup parent from repository --></parent><packaging>jar</packaging><properties><java.version>1.8</java.version><!--<spring-cloud.version>Greenwich.SR2</spring-cloud.version>--><spring-cloud.version>2021.0.7</spring-cloud.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><!--spring相关--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><!--knife swagger UI库--><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.3</version></dependency></dependencies>
因为已经有了之前的经验,
SpringBoot 2.6.0
版本以后就需要改一下配置
spring:mvc:pathmatch:matching-strategy: ant_path_matcher
然鹅,启动之后华丽的报了个错 ,最主要的就是这个了
Cannot invoke "org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getPatterns()" because "this.condition" is null
org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getPatterns()" because "this.condition" is null
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181) ~[spring-context-5.3.16.jar:5.3.16]
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54) ~[spring-context-5.3.16.jar:5.3.16]
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356) ~[spring-context-5.3.16.jar:5.3.16]
at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155) ~[spring-context-5.3.16.jar:5.3.16]
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123) ~[spring-context-5.3.16.jar:5.3.16]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935) ~[spring-context-5.3.16.jar:5.3.16]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586) ~[spring-context-5.3.16.jar:5.3.16]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[spring-boot-2.6.4.jar:2.6.4]
at net.lesscoding.handmade.MainApp.main(MainApp.java:21) ~[classes/:na]
Caused by: java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getPatterns()" because "this.condition" is null
at springfox.documentation.spring.web.WebMvcPatternsRequestConditionWrapper.getPatterns(WebMvcPatternsRequestConditionWrapper.java:56) ~[springfox-spring-webmvc-3.0.0.jar:3.0.0]
at springfox.documentation.RequestHandler.sortedPaths(RequestHandler.java:113) ~[springfox-core-3.0.0.jar:3.0.0]
at springfox.documentation.spi.service.contexts.Orderings.lambda$byPatternsCondition$3(Orderings.java:89) ~[springfox-spi-3.0.0.jar:3.0.0]
at java.base/java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:473) ~[na:na]
at java.base/java.util.TimSort.countRunAndMakeAscending(TimSort.java:355) ~[na:na]
at java.base/java.util.TimSort.sort(TimSort.java:220) ~[na:na]
at java.base/java.util.Arrays.sort(Arrays.java:1307) ~[na:na]
at java.base/java.util.ArrayList.sort(ArrayList.java:1721) ~[na:na]
at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:392) ~[na:na]
at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:na]
at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:na]
at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:na]
at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682) ~[na:na]
at springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider.requestHandlers(WebMvcRequestHandlerProvider.java:81) ~[springfox-spring-webmvc-3.0.0.jar:3.0.0]
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na]
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682) ~[na:na]
at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.withDefaults(AbstractDocumentationPluginsBootstrapper.java:107) ~[springfox-spring-web-3.0.0.jar:3.0.0]
at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.buildContext(AbstractDocumentationPluginsBootstrapper.java:91) ~[springfox-spring-web-3.0.0.jar:3.0.0]
at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.bootstrapDocumentationPlugins(AbstractDocumentationPluginsBootstrapper.java:82) ~[springfox-spring-web-3.0.0.jar:3.0.0]
at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:100) ~[springfox-spring-web-3.0.0.jar:3.0.0]
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178) ~[spring-context-5.3.16.jar:5.3.16]... 14 common frames omitted
然后根据 qq_21480329的帖子解决了,解决方案如下
packagenet.lesscoding.handmade.config;importlombok.extern.slf4j.Slf4j;importorg.springframework.beans.BeansException;importorg.springframework.beans.factory.config.BeanPostProcessor;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.util.ReflectionUtils;importorg.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;importspringfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;importspringfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;importjava.lang.reflect.Field;importjava.util.List;importjava.util.stream.Collectors;/**
* @author eleven
* @date 2023/6/28 10:05
* @apiNote
*/@Slf4j@ConfigurationpublicclassBeanPostProcessorConfig{@BeanpublicBeanPostProcessorspringfoxHandlerProviderBeanPostProcessor(){returnnewBeanPostProcessor(){@OverridepublicObjectpostProcessAfterInitialization(Object bean,String beanName)throwsBeansException{if(bean instanceofWebMvcRequestHandlerProvider|| bean instanceofWebFluxRequestHandlerProvider){customizeSpringfoxHandlerMappings(getHandlerMappings(bean));}return bean;}private<TextendsRequestMappingInfoHandlerMapping>voidcustomizeSpringfoxHandlerMappings(List<T> mappings){List<T> copy = mappings.stream().filter(mapping -> mapping.getPatternParser()==null).collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);}@SuppressWarnings("unchecked")privateList<RequestMappingInfoHandlerMapping>getHandlerMappings(Object bean){try{Field field =ReflectionUtils.findField(bean.getClass(),"handlerMappings");
field.setAccessible(true);return(List<RequestMappingInfoHandlerMapping>) field.get(bean);}catch(IllegalArgumentException|IllegalAccessException e){thrownewIllegalStateException(e);}}};}}
X. 番外,Knife4j添加全局权限认证
packagenet.lesscoding.config;importcn.hutool.core.util.StrUtil;importio.swagger.annotations.Api;importio.swagger.annotations.ApiOperation;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.Profile;importspringfox.documentation.builders.ApiInfoBuilder;importspringfox.documentation.builders.PathSelectors;importspringfox.documentation.builders.RequestHandlerSelectors;importspringfox.documentation.service.Contact;importspringfox.documentation.spi.DocumentationType;importspringfox.documentation.spring.web.plugins.Docket;importio.swagger.models.auth.In;importspringfox.documentation.service.*;importspringfox.documentation.spi.service.contexts.SecurityContext;importjava.util.ArrayList;importjava.util.List;/**
* @author eleven
* @date 2023/6/20 14:07
* @apiNote
*/@ConfigurationpublicclassKnife4jConfig{@Value("${spring.profiles.active}")privateString active;@BeanpublicDocketdocket(){returnnewDocket(DocumentationType.SWAGGER_2).apiInfo(newApiInfoBuilder().description("双重预防数智化管控平台接口文档").termsOfServiceUrl("https://xxx.net").contact(newContact("双重预防数智化管控平台","https://example.net","[email protected]")).version("1.0").build())//分组名称.groupName("1.0.0版本").groupName("1.0.1版本").select()//这里指定Controller扫描包路径.apis(RequestHandlerSelectors.basePackage("cn.com.safeinfo.hesp"))// Knife4j 配置只扫描带有@ApiOperatgion注解的方法.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))// Knife4j 配置只扫描带有@Api注解的类.apis(RequestHandlerSelectors.withClassAnnotation(Api.class)).paths(PathSelectors.any()).build()// 添加全局的权限认证请求头 .securityContexts(securityContexts()).securitySchemes(securitySchemes())// 只有在非prod环境才启用.enable(!StrUtil.equals(active,"prod"));}/**
* 安全模式,这里指定token通过Authorization头请求头传递
*/privateList<SecurityScheme>securitySchemes(){// 设置请求头信息List<SecurityScheme> apiKeyList =newArrayList<SecurityScheme>();
apiKeyList.add(newApiKey("Authorization","Authorization",In.HEADER.toValue()));return apiKeyList;}/**
* 安全上下文
*/privateList<SecurityContext>securityContexts(){// 设置需要登录的认证路径List<SecurityContext> securityContexts =newArrayList<>();
securityContexts.add(SecurityContext.builder().securityReferences(defaultAuth()).operationSelector(o -> o.requestMappingPattern().matches("/.*")).build());return securityContexts;}/**
* 默认的安全上引用
*/privateList<SecurityReference>defaultAuth(){AuthorizationScope authorizationScope =newAuthorizationScope("global","accessEverything");AuthorizationScope[] authorizationScopes =newAuthorizationScope[1];
authorizationScopes[0]= authorizationScope;List<SecurityReference> securityReferences =newArrayList<>();
securityReferences.add(newSecurityReference("Authorization", authorizationScopes));return securityReferences;}}
X + 1 生产环境配置过滤掉 Knife4j
参考链接knife4j生产环境资源屏蔽
# knife4j的增强配置knife4j:enable:true# 开启生产环境屏蔽,一定要先开启knife4j增强才会生效production:true
版权归原作者 是赵敢敢啊 所有, 如有侵权,请联系我们删除。