环境:jdk1.8+,spring boot(2.1.),springfox-swagger2(2.5.0),springfox-swagger-ui(2.5.0)
最近使用springfox-swagger2。本来好好的接口,有一天突然发现swagger显示的接口参数A跟原来不一致,接口参数的描述变成了另外一个类A1的描述。检查后发现接口没变。但是别的同事增加了另外一个接口,而接口中定义了一个同样类名的对象,即A跟A1的类名相同。导致springfox-swagger2在生成swagger对象时,ModelMapper在合并Model时类名相同的model会被覆盖。主要是因为DefaultModelProvider在生成model时id和name设置成了类名,存储在map中的key使用的是类名。
DefaultModelProvider会调用.
进一步调用TypeNameProviderPlugin extends Plugin<DocumentationType>.nameFor(DefaultTypeNameProvider或者ApiModelTypeNameProvider)
DefaultModelProvider
private Model modelBuilder(ResolvedType propertiesHost,
Map<String, ModelProperty> properties,
ModelContext modelContext) {
String typeName = ((modelContext, propertiesHost));
()
.id(typeName)
.type(propertiesHost)
.name(typeName)
.qualifiedType(simpleQualifiedTypeName(propertiesHost))
.properties(properties)
.description("")
.baseModel("")
.discriminator("")
.subTypes(new ArrayList<String>());
return (modelContext);
}
@Component
public class TypeNameExtractor {
private final TypeResolver typeResolver;
private final PluginRegistry<TypeNameProviderPlugin, DocumentationType> typeNameProviders;
@Autowired
public TypeNameExtractor(TypeResolver typeResolver,
@Qualifier("typeNameProviderPluginRegistry")
PluginRegistry<TypeNameProviderPlugin, DocumentationType> typeNameProviders) {
= typeResolver;
= typeNameProviders;
}
public String typeName(ModelContext context) {
ResolvedType type = asResolved(());
if (isContainerType(type)) {
return containerType(type);
}
return innerTypeName(type, context);
}
private ResolvedType asResolved(Type type) {
return (type);
}
private String genericTypeName(ResolvedType resolvedType, ModelContext context) {
......
}
private String innerTypeName(ResolvedType type, ModelContext context) {
if (().size() > 0 && ().getTypeParameters().length > 0) {
return genericTypeName(type, context);
}
return simpleTypeName(type, context);
}
private String simpleTypeName(ResolvedType type, ModelContext context) {
......
return typeName(new ModelNameContext((), ()));
}
private String typeName(ModelNameContext context) {
TypeNameProviderPlugin selected =
((), new DefaultTypeNameProvider());
return (());
}
}
@Component
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER)
public class ApiModelTypeNameProvider extends DefaultTypeNameProvider {
@Override
public String nameFor(Class<?> type) {
ApiModel annotation = findAnnotation(type, );
String defaultTypeName = (type);
if (annotation != null) {
return fromNullable(emptyToNull(())).or(defaultTypeName);
}
return defaultTypeName;
}
@Override
public boolean supports(DocumentationType delimiter) {
return (delimiter);
}
}
public class DefaultTypeNameProvider implements TypeNameProviderPlugin {
@Override
public boolean supports(DocumentationType delimiter) {
return true;
}
@Override
public String nameFor(Class<?> type) {
return ();
}
}
ModelMapper
Map<String, Model> modelsFromApiListings(Multimap<String, ApiListing> apiListings) {
Map<String, > definitions = newHashMap();
for (ApiListing each : ()) {
(());
}
return mapModels(definitions);
}
简单处理是修改类名,保证不存在相同的类名。
还可以在每个类名上添加注解@ApiModel("xxxxx").这样在生成model名时(使用ApiModelTypeNameProvider)使用配置的xxxxx.
从源码分析,似乎springfox-swagger2也是提供了很多可扩展点。待以后有时间再研究