• 解决方案之‘Failed to start bean ... nested exception is java.lang.NullPoi


    ‘documentationPluginsBootstrapper’; nested exception is java.lang.NullPointe

    1.1 Bug现场

    当Spring Boot 2.6.x 和Swagger 3.0.0 整合的时候,可能会报错如下所示:

    org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
    	at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181)
    	at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54)
    	at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356)
    	at java.lang.Iterable.forEach(Iterable.java:75)
    	at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155)
    	at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123)
    	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586)
    	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
    	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740)
    	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415)
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312)
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
    	at com.br.troubleshootquerytool.TroubleShootQueryToolApplication.main(TroubleShootQueryToolApplication.java:13)
    Caused by: java.lang.NullPointerException: null
    	at springfox.documentation.spring.web.WebMvcPatternsRequestConditionWrapper.getPatterns(WebMvcPatternsRequestConditionWrapper.java:56)
    	at springfox.documentation.RequestHandler.sortedPaths(RequestHandler.java:113)
    	at springfox.documentation.spi.service.contexts.Orderings.lambda$byPatternsCondition$3(Orderings.java:89)
    	at java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469)
    	at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
    	at java.util.TimSort.sort(TimSort.java:220)
    	at java.util.Arrays.sort(Arrays.java:1512)
    	at java.util.ArrayList.sort(ArrayList.java:1462)
    	at java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:387)
    	at java.util.stream.Sink$ChainedReference.end(Sink.java:258)
    	at java.util.stream.Sink$ChainedReference.end(Sink.java:258)
    	at java.util.stream.Sink$ChainedReference.end(Sink.java:258)
    	at java.util.stream.Sink$ChainedReference.end(Sink.java:258)
    	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
    	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
    	at springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider.requestHandlers(WebMvcRequestHandlerProvider.java:81)
    	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
    	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
    	at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.withDefaults(AbstractDocumentationPluginsBootstrapper.java:107)
    	at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.buildContext(AbstractDocumentationPluginsBootstrapper.java:91)
    	at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.bootstrapDocumentationPlugins(AbstractDocumentationPluginsBootstrapper.java:82)
    	at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:100)
    	at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178)
    	... 14 common frames omitted
    
    Process finished with exit code 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    1.2 问题分析

    因为Springfox 使用的路径匹配是基于AntPathMatcher的,而Spring Boot 2.6.X使用的是PathPatternMatcher。

    1.3 修复方案

    1.3.1 修复方案一:降低Spring Boot 版本到2.6.x以下版本

    比如下面版本组合是兼容的

    Spring Boot版本

    Swagger 版本

    2.5.6

    2.9.2

    1.3.2 修复方案二: SpringBoot版本不降级解决方案

    比如下面版本组合是兼容的

    Spring Boot版本

    Swagger 版本

    2.6.5

    3.0.0

        
                io.springfox
                springfox-boot-starter
                3.0.0
        
    
    • 1
    • 2
    • 3
    • 4
    • 5

    第一步:
    application.yml 或applicaiton.properties 中添加如下配置

    spring:
      mvc:
        pathmatch:
          matching-strategy: ant_path_matcher
    
    • 1
    • 2
    • 3
    • 4

    第二步:

    项目中新建一个Java Config 类,内容如下:

    /***
     * @author qingfeng.zhao
     * @date 2022/3/26
     * @apiNote
     */
    @EnableOpenApi
    @Configuration
    public class SpringFoxSwaggerConfig {
        /**
         * 配置基本信息
         * @return
         */
        @Bean
        public ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    .title("Swagger Test App Restful API")
                    .description("swagger test app restful api")
                    .termsOfServiceUrl("https://github.com/geekxingyun")
                    .contact(new Contact("技术宅星云","https://xingyun.blog.csdn.net","fairy_xingyun@hotmail.com"))
                    .version("1.0")
                    .build();
        }
    
        /**
         * 配置文档生成最佳实践
         * @param apiInfo
         * @return
         */
        @Bean
        public Docket createRestApi(ApiInfo apiInfo) {
            return new Docket(DocumentationType.OAS_30)
                    .apiInfo(apiInfo)
                    .groupName("SwaggerGroupOneAPI")
                    .select()
                    .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
                    .paths(PathSelectors.any())
                    .build();
        }
    
        /**
        * 增加如下配置可解决Spring Boot 6.x 与Swagger 3.0.0 不兼容问题
        **/
        @Bean
        public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties, Environment environment) {
            List> allEndpoints = new ArrayList();
            Collection webEndpoints = webEndpointsSupplier.getEndpoints();
            allEndpoints.addAll(webEndpoints);
            allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
            allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
            String basePath = webEndpointProperties.getBasePath();
            EndpointMapping endpointMapping = new EndpointMapping(basePath);
            boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment, basePath);
            return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null);
        }
        private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment, String basePath) {
            return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    1.4 参考资料

  • 相关阅读:
    Meta官方吐槽大会?Connect 2022卡马克演讲全文回顾
    (附源码)mysql+ssm招聘网站 毕业设计 250858
    VMware下centos7安装k8s(Kubernetes)多master集群
    Java之JavaConfig
    msvcp140.dll是什么东西,如何解决msvcp140.dll丢失的问题的方法分享
    SparkCore编程RDD
    Go如何优雅的记录操作日志
    振南技术干货集:制冷设备大型IoT监测项目研发纪实(4)
    VGGNet架构解析
    小白也能学会的MongoDB实操
  • 原文地址:https://blog.csdn.net/m0_67391401/article/details/126608502