美文网首页
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