【问题标题】:Springfox 3.0.0 is not working with Spring Boot 2.6.0 [duplicate]Springfox 3.0.0 不适用于 Spring Boot 2.6.0
【发布时间】:2022-01-07 16:45:57
【问题描述】:

Springfox 3.0.0 不适用于 Spring Boot 2.6.0,升级后出现以下错误

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)
    at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54)
    at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356)
    at java.base/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:730)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:302)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290)
    at com.enkindle.AntivirusApplication.main(AntivirusApplication.java:16)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
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)
    at springfox.documentation.RequestHandler.sortedPaths(RequestHandler.java:113)
    at springfox.documentation.spi.service.contexts.Orderings.lambda$byPatternsCondition$3(Orderings.java:89)
    at java.base/java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:473)
    at java.base/java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
    at java.base/java.util.TimSort.sort(TimSort.java:234)
    at java.base/java.util.Arrays.sort(Arrays.java:1307)
    at java.base/java.util.ArrayList.sort(ArrayList.java:1721)
    at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:392)
    at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
    at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
    at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
    at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
    at springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider.requestHandlers(WebMvcRequestHandlerProvider.java:81)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
    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)
    ... 19 common frames omitted

【问题讨论】:

  • SpringBoot 2.6.1 也有这个问题(springfox-boot-starter 3.0.0)

标签: java spring-boot swagger springfox spring-boot-2.6.0


【解决方案1】:

我知道这并不能直接解决您的问题,但请考虑移至springdocmost recent release 支持 Spring Boot 2.6.0。 Springfox 在这一点上是如此的错误,以至于使用起来很痛苦。由于 Spring WebFlux 支持,我在 2 年前搬到了 springdoc,对此我感到非常高兴。此外,它还支持 Kotlin Coroutines,我不确定 Springfox 是否支持。

如果您决定迁移,springdoc 甚至还有一个migration guide

【讨论】:

    【解决方案2】:

    到目前为止,Springfox 3.0.0 仅适用于 Spring 2.6.0-M2,但不适用于以上版本。请参阅公开的 Springfox 问题https://github.com/springfox/springfox/issues/3462。在那里,您还可以找到一些在问题得到解决之前可以使用的解决方法。

    例如将此Bean 添加到您的 Swagger 配置中:

    @Bean
    public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
        return new BeanPostProcessor() {
    
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
                    customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
                }
                return bean;
            }
    
            private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
                List<T> copy = mappings.stream()
                    .filter(mapping -> mapping.getPatternParser() == null)
                    .collect(Collectors.toList());
                mappings.clear();
                mappings.addAll(copy);
            }
    
            @SuppressWarnings("unchecked")
            private List<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) {
                    throw new IllegalStateException(e);
                }
            }
        };
    }
    

    编辑:服务器启动,但没有返回 API 信息:

    规范中没有定义操作!

    真是一团糟。

    编辑2:正如@Héctor 所说,spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER 也必须添加到application.properties,然后再次显示操作。但是,我不知道是否可以在任何情况下设置此属性,因为它可能会干扰其他约束。

    【讨论】:

    • 我在这个网址中找到,最后的解决方法:将“spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER”添加到你的application.properties。就是这样
    • @Héctor:感谢您的意见。但是,我需要定义BeanPostProcessor 并添加ANT_PATH_MATCHER。仅添加ANT_PATH_MATCHER 会导致与@Thirumal 所述相同的错误。
    【解决方案3】:

    迁移步骤:

    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-boot-starter</artifactId>
        <version>3.0.0</version>
    </dependency>
    
    1. 仅维护上述依赖项。
    2. 删除早期版本的库包含。专门删除 springfox-swagger2 和 springfox-swagger-ui 包含。
    3. 删除@EnableSwagger2 注释
    4. 添加 springfox-boot-starter
    5. Springfox 3.x 删除了对 guava 和其他 3rd 方库的依赖(还不是零依赖!依赖于 spring 插件和开放的注释和模型的 api 库),所以如果你使用了 guava 谓词/函数,则需要转换到 java 8个功能接口
    6. 如果您正在使用 WebMvc 但尚未使用 @EnableWebMvc 注解,请添加此注解。

    来源:doc_link

    【讨论】:

    • 对于绝大多数人来说,将 @EnableWebMvc 添加到 Spring Boot 应用程序是错误的做法,因为它会禁用 Spring Boot 的 Spring MVC 自动配置。
    • 使用外部依赖的 SNAPSHOT 版本不是一个好主意。这以可能非常令人惊讶的方式使构建不可重复。
    【解决方案4】:

    对于 springfox 3.0.0 和 springboot 2.6.1 使用这个配置并添加这个标签 @Configuration @EnableWebMvc

    public class SpringFoxConfig {
    
        @Bean
        public Docket api() {
            return new Docket(DocumentationType.SWAGGER_2)
                    .select()
                    .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
                    .paths(PathSelectors.any())
                    .build().apiInfo(getApiInfo());
        }
        
        private ApiInfo getApiInfo() {
            return new ApiInfo(
                    "Api Usuarios",
                    "prueba global logic",
                    "1",
                    "TERMS OF SERVICE URL",
                    new Contact("Gabriel Hernández","URL","gabriel.hernandez.u@gmail.com"),
                    "LICENSE",
                    "LICENSE URL",
                    Collections.emptyList()
            );
        }
        
        @Bean
        public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
            return new BeanPostProcessor() {
    
                @Override
                public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                    if (bean instanceof WebMvcRequestHandlerProvider ) {
                        customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
                    }
                    return bean;
                }
    
                private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
                    List<T> copy = mappings.stream()
                        .filter(mapping -> mapping.getPatternParser() == null)
                        .collect(Collectors.toList());
                    mappings.clear();
                    mappings.addAll(copy);
                }
    
                @SuppressWarnings("unchecked")
                private List<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) {
                        throw new IllegalStateException(e);
                    }
                }
            };
        }    
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-06
      • 2023-02-07
      • 2019-11-12
      • 2022-12-30
      • 2015-07-25
      • 2015-04-13
      • 2018-10-18
      • 1970-01-01
      • 2020-02-25
      相关资源
      最近更新 更多