Daizc
count.articles52
count.tags25
count.categories3
解决Springdoc-OAS3中Schema重复的问题

解决Springdoc-OAS3中Schema重复的问题

在使用springdoc-openapi时,如果项目中存在多个SimpleName一致的Class,
那在Schema描述中将会依照解析的先后顺序互相覆盖,从而导致Api文档的描述与预期不一致。

相似问题

解决方案

  • 启用springdoc.use-fqn属性,所有的类将解析为全限定名
  • 重写TypeNameResolver,自定义解析规则

重写TypeNameResolver

需要注意的是,父类中useFqn被限定为private,在子类中无法获取。因此重写的逻辑(除super.getNameOfClass(cls)
外)无法对开启useFqn的情况做出适配。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 用于自定义Schema生成逻辑 以区分不同包下的同名Schema
*/
public class CustomOAS3TypeNameResolver extends TypeNameResolver {

@Override
protected String getNameOfClass(Class<?> cls) {

var packageName = cls.getPackageName();
if (packageName.contains("xxxxxx")) {
return cls.getSimpleName();
} else if (packageName.contains("org.gitlab4j")) {
return "Gitlab" + cls.getSimpleName();
}
return super.getNameOfClass(cls);
}
}

替换掉原本的TypeNameResolver

  1. 原本的TypeNameResolver是个私有静态单例,上面还打了final标记,看起来是没有替换原本变量的可能了。
  2. 往上一层走到ModelResolver类中,这个类提供了两个构造,其中一个支持传入TypeNameResolver参数,可以从这里入手覆盖。
  3. ModelResolver是被ModelResolvers初始化的,虽然ModelConverters
    也是个私有静态单例改不掉他,但他本质是个对List<ModelConverter>的包装类,提供了操作其中converters
    的方法,所以我们可以通过操作内部的数组来放入自定义的TypeNameResolver
  4. 由于ModelConverters也是静态单例,只要在Spring调用它解析Model之前替换调原本的TypeNameResolver就行了,因此可以直接怼到启动类中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

@SpringBootApplication
public class BeamApplication {

public static void main(String[] args) {
customOAS3TypeConverter();
SpringApplication.run(BeamApplication.class, args);
}

/**
* 自定义OAS3类型转换器
*/
private static void customOAS3TypeConverter() {
var instance = ModelConverters.getInstance();
var converter = instance.getConverters().get(0);
instance.removeConverter(converter);
instance.addConverter(new ModelResolver(Json.mapper(), new CustomOAS3TypeNameResolver()));
}
}

重启项目后,打开openapi文档。相同SimpleName的Schema已经区分来了。
完成截图

copyright.author:Daizc
copyright.permalink:https://note.bequick.run/%E8%A7%A3%E5%86%B3Springdoc-OAS3%E4%B8%ADSchema%E9%87%8D%E5%A4%8D%E7%9A%84%E9%97%AE%E9%A2%98/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可