SpringBoot升到2.6.8出现Knife4j 3.0.3
2022-06-08 本文已影响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;
}
重启之后问题已解决,附上效果图