SpringBoot3 - Spring Doc 2.0 Migration

Spring Doc 2.0 Migration

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).

SpringBoot3 - Spring Doc 2.0 Migration_第1张图片

问题排查

查了半天,作者的说法是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,只是在我们的配置中把他排到了第三个,重新调整一下位置将它排在前面问题得以解决

你可能感兴趣的:(Spingboot3,SpringDoc2,spring,boot)