For spring-boot v3 support, make sure you use springdoc-openapi v2
这是springdocgithub主页上留一下的一句话(https://github.com/springdoc/springdoc-openapi),看起来springdoc 1.x不支持Springboot3,我们按照官网的指引进行相关pom的替换
<dependency>
<groupId>org.springdocgroupId>
<artifactId>springdoc-openapi-starter-webmvc-uiartifactId>
<version>2.0.4version>
dependency>
然后重启服务打开我们的swagerUI,不出意外的出意外了
Unable to render this definition The provided definition does not specify a valid version field.
Please indicate a valid Swagger or OpenAPI version field. Supported version fields are swagger: "2.0" and those that match openapi: 3.0.n (for example, openapi: 3.0.0).
查了半天,作者的说法是MessageConvert有问题,需要使用MappingJackson2HttpMessageConverter
,看了一下我们的配置,似乎也没有问题
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setSupportedMediaTypes(Arrays.asList(MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML));
stringHttpMessageConverter.setDefaultCharset(StandardCharsets.UTF_8);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.configure(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY, false);
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(objectMapper);
mappingJackson2HttpMessageConverter.setDefaultCharset(StandardCharsets.UTF_8);
//stringHttpMessageConverter is first, mappingJackson2HttpMessageConverter is second than default converters
//mappingJackson2HttpMessageConverter should behind byteConverter for springDoc
converters.add(0, mappingJackson2HttpMessageConverter);
converters.add(0, stringHttpMessageConverter);
}
然后我尝试访问了/api-docs
这个接口,正常会返回一个json,但是在这里我得到了一个Base64编码之后的字符串
对Base64接码之后正是我们需要的Json,看起来确实是Converter这里出了问题。
随后我们对两个版本进行debug,发现了问题所在
首先是SpringDoc 1.6.x
这里可以看到返回的是一个String,实际上就是一个json字符串,这个json会被排在第一的StringHttpMessageConverter
处理返给HttpResponse,页面可以正常展示。
然后我们转到SpringDoc 2.x
可以看到返回值变成了一个byte[]
,StringHttpMessageConverter
不会处理byte数组,转而走到了排在第二的MappingJackson2HttpMessageConverter
,在这里会将byte数组转为base64字符串,SwagerUI无法解析导致了问题的产生。
又是什么原因导致了open-api的返回值发生了改变,比较一下两个版本的OpenApiWebMvcResource
就可以找到原因
//1.6.x
@Operation(
hidden = true
)
@GetMapping(
value = {"${springdoc.api-docs.path:#{T(org.springdoc.core.Constants).DEFAULT_API_DOCS_URL}}"},
produces = {"application/json"}
)
public String openapiJson(HttpServletRequest request, @Value("${springdoc.api-docs.path:#{T(org.springdoc.core.Constants).DEFAULT_API_DOCS_URL}}") String apiDocsUrl, Locale locale) throws JsonProcessingException {
return super.openapiJson(request, apiDocsUrl, locale);
}
//2.0.x
@Operation(hidden = true)
@GetMapping(value = API_DOCS_URL, produces = MediaType.APPLICATION_JSON_VALUE)
@Override
public byte[] openapiJson(HttpServletRequest request, @Value(API_DOCS_URL) String apiDocsUrl, Locale locale)
throws JsonProcessingException {
return super.openapiJson(request, apiDocsUrl, locale);
}
其实就是SpringDoc自己把返回值改了。
SpingDoc的代码我们没有办法修改,但是我们可以在MessageConvert上入手。通过debug我们发现,Spring本身会为我们配置一些convert
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, mappingJackson2HttpMessageConverter);
converters.add(0, stringHttpMessageConverter);
}
这里的converters中第一个就是ByteArrayMessageConverter
,只是在我们的配置中把他排到了第三个,重新调整一下位置将它排在前面问题得以解决