我从 Springfox Swagger 迁移到 Springdoc OpenApi。我在有关 springdoc 的配置中添加了几行:
springdoc:
pathsToMatch: /api/**
api-docs:
path: /api-docs
swagger-ui:
path: /swagger-ui.html
在配置类中MainConfig.kt
我有以下代码:
val customGson: Gson = GsonBuilder()
.registerTypeAdapter(LocalDateTime::class.java, DateSerializer())
.registerTypeAdapter(ZonedDateTime::class.java, ZonedDateSerializer())
.addSerializationExclusionStrategy(AnnotationExclusionStrategy())
.enableComplexMapKeySerialization()
.setPrettyPrinting()
.create()
override fun configureMessageConverters(converters: MutableList<HttpMessageConverter<*>>) {
converters.add(GsonHttpMessageConverter(customGson))
}
当我访问 http://localhost:8013/swagger-ui.html (在配置中我有server.port: 8013
)页面没有重定向到swagger-ui/index.html?url=/api-docs&validatorUrl=
。但这不是我的主要问题:)。当我去swagger-ui/index.html?url=/api-docs&validatorUrl=
我得到包含以下信息的页面:
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).
但是当我访问 http://localhost:8013/api-docs 时,我得到了这个结果:
"{\"openapi\":\"3.0.1\",\"info\":{(...)}}"
我尝试使用默认配置并发表评论configureMessageConverters()
方法和结果\api-docs
现在看起来像普通的 JSON:
// 20191218134933
// http://localhost:8013/api-docs
{
"openapi": "3.0.1",
"info": {(...)}
}
我记得当我使用Springfox时,序列化出了问题,我的customGson
有附加行:.registerTypeAdapter(Json::class.java, JsonSerializer<Json> { src, _, _ -> JsonParser.parseString(src.value()) })
我想知道我应该有特别的JsonSerializer
。调试后我的第一个想法是OpenApi
上课于io.swagger.v3.oas.models
包裹。我添加了这段代码:.registerTypeAdapter(OpenAPI::class.java, JsonSerializer<OpenAPI> { _, _, _ -> JsonParser.parseString("") })
to customGson
一切都没有改变......所以,我正在深入挖掘......
当我运行 Swagger 测试后:
@EnableAutoConfiguration
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@ExtendWith(SpringExtension::class)
@ActiveProfiles("test")
class SwaggerIntegrationTest(@Autowired private val mockMvc: MockMvc) {
@Test
fun `should display Swagger UI page`() {
val result = mockMvc.perform(MockMvcRequestBuilders.get("/swagger-ui/index.html"))
.andExpect(status().isOk)
.andReturn()
assertTrue(result.response.contentAsString.contains("Swagger UI"))
}
@Disabled("Redirect doesn't work. Check it later")
@Test
fun `should display Swagger UI page with redirect`() {
mockMvc.perform(MockMvcRequestBuilders.get("/swagger-ui.html"))
.andExpect(status().isOk)
.andExpect(MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.TEXT_HTML))
}
@Test
fun `should get api docs`() {
mockMvc.perform(MockMvcRequestBuilders.get("/api-docs"))
.andExpect(status().isOk)
.andExpect(MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.jsonPath("\$.openapi").exists())
}
}
我在控制台看到了这个:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /api-docs
Parameters = {}
Headers = []
Body = null
Session Attrs = {}
Handler:
Type = org.springdoc.api.OpenApiResource
Method = org.springdoc.api.OpenApiResource#openapiJson(HttpServletRequest, String)
接下来我检查openapiJson
in OpenApiResource
and...
@Operation(hidden = true)
@GetMapping(value = API_DOCS_URL, produces = MediaType.APPLICATION_JSON_VALUE)
public String openapiJson(HttpServletRequest request, @Value(API_DOCS_URL) String apiDocsUrl)
throws JsonProcessingException {
calculateServerUrl(request, apiDocsUrl);
OpenAPI openAPI = this.getOpenApi();
return Json.mapper().writeValueAsString(openAPI);
}
好的,杰克逊...我已经禁用了杰克逊@EnableAutoConfiguration(exclude = [(JacksonAutoConfiguration::class)])
因为我(和我的同事)更喜欢GSON,但它并不能解释为什么添加自定义后序列化会出错GsonHttpMessageConverter
。我不知道我做了什么坏事。这openapiJson()
是端点,也许它弄乱了一些东西......我不知道。我不知道。您有类似的问题吗?你能给一些建议或提示吗?
附言。对不起,我的英语不好 :)。