springfox-swagger2坑

环境:jdk1.8+,spring boot(2.1.3.RELEASE),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会调用TypeNameExtractor.typeName.

进一步调用TypeNameProviderPlugin extends Plugin.nameFor(DefaultTypeNameProvider或者ApiModelTypeNameProvider)

 

DefaultModelProvider

  private Model modelBuilder(ResolvedType propertiesHost,
                             Map properties,
                             ModelContext modelContext) {
    String typeName = typeNameExtractor.typeName(ModelContext.fromParent(modelContext, propertiesHost));
    modelContext.getBuilder()
        .id(typeName)
        .type(propertiesHost)
        .name(typeName)
        .qualifiedType(simpleQualifiedTypeName(propertiesHost))
        .properties(properties)
        .description("")
        .baseModel("")
        .discriminator("")
        .subTypes(new ArrayList());
    return schemaPluginsManager.model(modelContext);
  }

 

@Component
public class TypeNameExtractor {
  private final TypeResolver typeResolver;
  private final PluginRegistry typeNameProviders;

  @Autowired
  public TypeNameExtractor(TypeResolver typeResolver,
                           @Qualifier("typeNameProviderPluginRegistry")
                           PluginRegistry typeNameProviders) {

    this.typeResolver = typeResolver;
    this.typeNameProviders = typeNameProviders;
  }

  public String typeName(ModelContext context) {
    ResolvedType type = asResolved(context.getType());
    if (isContainerType(type)) {
      return containerType(type);
    }
    return innerTypeName(type, context);
  }

  private ResolvedType asResolved(Type type) {
    return typeResolver.resolve(type);
  }

  private String genericTypeName(ResolvedType resolvedType, ModelContext context) {
    ......
  }

  private String innerTypeName(ResolvedType type, ModelContext context) {
    if (type.getTypeParameters().size() > 0 && type.getErasedType().getTypeParameters().length > 0) {
      return genericTypeName(type, context);
    }
    return simpleTypeName(type, context);
  }

  private String simpleTypeName(ResolvedType type, ModelContext context) {
    ......

    return typeName(new ModelNameContext(type.getErasedType(), context.getDocumentationType()));
  }

  private String typeName(ModelNameContext context) {
    TypeNameProviderPlugin selected =
        typeNameProviders.getPluginFor(context.getDocumentationType(), new DefaultTypeNameProvider());
    return selected.nameFor(context.getType());
  }
}

 


@Component
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER)
public class ApiModelTypeNameProvider extends DefaultTypeNameProvider {
  @Override
  public String nameFor(Class type) {
    ApiModel annotation = findAnnotation(type, ApiModel.class);
    String defaultTypeName = super.nameFor(type);
    if (annotation != null) {
      return fromNullable(emptyToNull(annotation.value())).or(defaultTypeName);
    }
    return defaultTypeName;
  }

  @Override
  public boolean supports(DocumentationType delimiter) {
    return SwaggerPluginSupport.pluginDoesApply(delimiter);
  }
}


public class DefaultTypeNameProvider implements TypeNameProviderPlugin {

  @Override
  public boolean supports(DocumentationType delimiter) {
    return true;
  }

  @Override
  public String nameFor(Class type) {
    return type.getSimpleName();
  }
}

 

 

ModelMapper

Map modelsFromApiListings(Multimap apiListings) {
  Map definitions = newHashMap();
  for (ApiListing each : apiListings.values()) {
    definitions.putAll(each.getModels());
  }
  return mapModels(definitions);
}

简单处理是修改类名,保证不存在相同的类名。

还可以在每个类名上添加注解@ApiModel("xxxxx").这样在生成model名时(使用ApiModelTypeNameProvider)使用配置的xxxxx.

从源码分析,似乎springfox-swagger2也是提供了很多可扩展点。待以后有时间再研究

 

你可能感兴趣的:(springfox-swagger2坑)