美文网首页
SpringBoot升到2.6.8出现Knife4j 3.0.3

SpringBoot升到2.6.8出现Knife4j 3.0.3

作者: 极简博客 | 来源:发表于2022-06-08 16:28 被阅读0次

    最近对SpringBoot的版本从2.5.9 升级到 2.6.8 ,出现与Knife4j(3.0.3)不兼容问题,
    以下将对该问题进行探索与解决。

    问题一: 运行程序出现NPE

    2022-06-08 15:39:38 ERROR [main] org.springframework.boot.SpringApplication Application run failed
    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:745)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:420)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1317)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
        at com.umo.server.UmoServerApplication.main(UmoServerApplication.java:14)
    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:234)
        at java.util.Arrays.sort(Arrays.java:1512)
        at java.util.ArrayList.sort(ArrayList.java:1464)
        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:483)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
        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:1384)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
        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
    

    解决方法:修改springfox相关文件

    # 1、创建重置文件
    public class SpringFoxHandlerProviderBeanPostProcessor implements 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 = Collections.filterList(mappings, mapping -> mapping.getPatternParser() == null);
            mappings.clear();
            mappings.addAll(copy);
        }
    
        @SuppressWarnings("unchecked")
        private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
            return (List<RequestMappingInfoHandlerMapping>) ReflectUtil.getFieldValue(bean, "handlerMappings");
        }
    }
    
    # 2、在swagger 配置文件中注入
    @Bean
    public SpringFoxHandlerProviderBeanPostProcessor springFoxHandlerProviderBeanPostProcessor() {
        return new SpringFoxHandlerProviderBeanPostProcessor();
    }
    

    通过以上的配置,可以成功启动应用;于是我满怀欣喜的访问API 文档,出现以下问题。

    问题二:文档上只有分组信息,没有相关的API信息

    于是我带着不愉悦的心情按下了F12,打开了浏览器控制,发现接口(api-docs)返回是空的


    带着这个问题,我通过断点调试最终确定问题在于,Json类中value值没有序列化,导致接口返回为空

    注:项目使用的是fastjson:2.0.5作为序列化工具

    import com.fasterxml.jackson.annotation.JsonRawValue;
    import com.fasterxml.jackson.annotation.JsonValue;
    
    public class Json {
      private final String value;
    
      public Json(String value) {
        this.value = value;
      }
    
      @JsonValue
      @JsonRawValue
      public String value() {
        return value;
      }
    }
    

    解决方法:自定义fastjson序列化类

    /**
         * FastJson 序列化配置
         * @return
         */
        private FastJsonConfig getFastJsonConfig() {
            FastJsonConfig fastJsonConfig = new FastJsonConfig();
            // 配置序列化器功能
            fastJsonConfig.setSerializerFeatures(
                    //全局修改日期格式,如果时间是data、时间戳类型,按照这种格式初始化时间 "yyyy-MM-dd HH:mm:ss"
                    SerializerFeature.WriteDateUseDateFormat,
                    // 保留 Map 空的字段
                    SerializerFeature.WriteMapNullValue,
                    // 将 String 类型的 null 转成""
                    SerializerFeature.WriteNullStringAsEmpty,
                    // 将 Number 类型的 null 转成 0
                    SerializerFeature.WriteNullNumberAsZero,
                    // 将 List 类型的 null 转成 []
                    SerializerFeature.WriteNullListAsEmpty,
                    // 将 Boolean 类型的 null 转成 false
                    SerializerFeature.WriteNullBooleanAsFalse,
                    // 避免循环引用
                    SerializerFeature.DisableCircularReferenceDetect,
                    //返回Json数据排版格式
                    SerializerFeature.PrettyFormat
            );
    
            // Json 类序列化
            ObjectSerializer iSerializer = (serializer, object, fieldName, fieldType, features) -> {
                if (object instanceof Json) {
                    serializer.write(((Json)object).value());
                }
            };
    
            JSON.DEFAULT_GENERATE_FEATURE &= ~SerializerFeature.SortField.getMask();
            SerializeConfig serializeConfig = new SerializeConfig();
            serializeConfig.put(Json.class, iSerializer);
            fastJsonConfig.setSerializeConfig(serializeConfig);
            return fastJsonConfig;
        }
    

    重启之后问题已解决,附上效果图


    相关文章

      网友评论

          本文标题:SpringBoot升到2.6.8出现Knife4j 3.0.3

          本文链接:https://www.haomeiwen.com/subject/yppumrtx.html