Springfox 3.0.0 中增加了对OpenAPI 3的支持,同时仍默认同时开放Swagger 2的接口。接口地址分别为:
- OpenAPI 3:
\v3\api-docs
- Swagger 2:
\v2\api-docs
因为开发者已经很久没有维护,目前有一些遗留的bug及兼容性问题没有解决,其中有些可以通过有些代码和配置进行绕过。
笔者最近使用Springdoc对Springfox进行替换,整个操作比较简单,主要工作量在于将注解从Swagger 2升级到OpenAPI 3,具体操作可以参考Springdoc官方文档 [Migrating from SpringFox](https://springdoc.org/#migrating-from-springfox). 但上游服务及底层依赖库仍在使用Swagger 2生成客户端代码生成,需要Service中保留Swagger 2地址,所以需要将依赖回退到Springfox,但注解仍然使用OpenAPI 3版本,以便未来再次替换回来。
Springfox文档中表明支持OpenAPI 3的注解,可以通过增加@EnableOpenApi
,实测下来,除了@OpenAPIDefinition
里的文档信息以外,其他基本支持。
部分遗留问题:
不可访问模型
当有些Model类在API规范定义中,但实际方法中没有直接匹配该模型时,可能会报该错误。
注解定义:因为返回值有多种,所以使用了ResponseEntity<Object>
,通用错误400
返回类DataValidationErrorResponse
没有被代码适配,所以报错。
@Operation(summary = "Decode notification", operationId = "decode-notify", description = "Decode and translate notification to internal format", security = {
@SecurityRequirement(name = "bearerAuth")}, tags = {"Decode notification"})
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "OK - the request has succeeded.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(anyOf = {
PaymentNotificationItem.class, RefundNotificationItem.class}))),
@ApiResponse(responseCode = "400", description = "Bad Request - request is not well-formed, syntactically incorrect or violates schema.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = DataValidationErrorResponse.class))),
})
@PostMapping(value = "/pay/notify", produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<Object> decodeNotify(@Valid @RequestBody String notifyBody) {
// handler logic
}
API显示Error-ModelName
错误,下为Swagger 2 API 结果:
"400": {
"description": "Bad Request - request is not well-formed, syntactically incorrect or violates schema.",
"schema": {
"$ref": "Error-ModelName{namespace='com.payments.common.model', name='DataValidationErrorResponse'}",
},
},
Swagger 2 API会打出控制台错误信息:ReferenceModelSpecificationToPropertyConverter - Unable to find a model that matches key ModelKey{qualifiedModelName=ModelName{namespace='com.payments.common.model', name='DataValidationErrorResponse'}, viewDiscriminator=null, validationGroupDiscriminators=[], isResponse=true}
解决方案
SwaggerConfig中加入配置.additionalModels(typeResolver.resolve(DataValidationErrorResponse.class))
@Bean
public Docket customImplementation() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class)).paths(PathSelectors.any()).build()
.additionalModels(typeResolver.resolve(DataValidationErrorResponse.class))
.securitySchemes(Lists.newArrayList(apiKey(), clientId(), traceId()))
.securityContexts(Lists.newArrayList(securityContext())).apiInfo(apiInfo());
}
无效/冗余参数
基本不会影响Swagger UI,Redoc等UI文档生成,但是在Swagger Editor中会报错 should NOT have additional properties
。
image.png
解决方案
在swagger-core中定义了一些Mixin规则,可以Jackson Mixin配置ObjectMapper从而进行参数过滤。 Springfox默认的依赖没有Swagger-core,在不考虑增加新的依赖的情况下,可以找到对应的Mixin配置,手动加到SwaggerConfig中,然后获取ObjectMapper进行配置。
参考Mixin设置:
- Swagger 2:
swagger-core 1.x
版本,如1.6.6
,参考地址:https://github.com/swagger-api/swagger-core/tree/v1.6.6/modules/swagger-core/src/main/java/io/swagger/jackson/mixin - OpenAPI 3:
swagger-core 2.x
版本,如2.2.0
,参考地址: https://github.com/swagger-api/swagger-core/tree/v2.2.0/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin
代码范例:
这里过滤了Swagger 2里面的originalRef参数,以及重复response项responsesObject,OpenAPI 3里面的exampleSetFlag及extensions数组。
/**
* Logic reference: ObjectMapperFactory in swagger-core 1.6.6 & swagger-core 2.2.0
*
* @return JacksonModuleRegistrar
*/
@Bean
// Remove auto generated additionalProperty
public JacksonModuleRegistrar swaggerJacksonModuleRegistrar() {
return objectMapper -> {
// Swagger 2 cleanup additionalProperty: originalRef
objectMapper.addMixIn(RefProperty.class, Swagger2Mixin.class);
objectMapper.addMixIn(RefModel.class, Swagger2Mixin.class);
// Swagger 2 cleanup additionalProperty: responsesObject
objectMapper.addMixIn(Operation.class, Swagger2Mixin.class);
// OAS 3 cleanup additionalProperty: exampleSetFlag & extensions
objectMapper.addMixIn(Schema.class, Oas3Mixin.class);
objectMapper.addMixIn(MediaType.class, Oas3Mixin.class);
};
}
/**
* Swagger 2 cleanup additionalProperty: originalRef & responsesObject
*/
static abstract class Swagger2Mixin {
// Swagger 2 Mixin property
@JsonIgnore
public abstract String getOriginalRef();
@JsonIgnore
public abstract Responses getResponsesObject();
}
/**
* OpenAPI 3 cleanup additionalProperty: exampleSetFlag & extensions
*/
static abstract class Oas3Mixin {
@JsonAnyGetter
public abstract Map<String, Object> getExtensions();
@JsonIgnore
public abstract boolean getExampleSetFlag();
}
作者:戴意伦
链接:https://www.jianshu.com/p/c3f38f7c6e2b
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。