swagger-codegen + openAPI3.0 生成的代码无法正常分组了 !!!

1,259 阅读4分钟

你们 openAPI 少了些属性,我无法正常生成代码了!

就在昨天公司老大把我拉入一个神秘的群聊,正在我以为会发生什么 神秘 交易的时候!!!

image.png

啪!我的脸上被甩了这么个聊天记录!!! image.png

做为全村最能 摸鱼 解决问题的靓仔,我自然欣然的接受了这个 摸鱼的机会 艰巨的任务! image.png

我们后端老师傅在前后端联调时,使用了spring提供的 springdoc-openAPI 做API文档提供给前端开发,在前后端联调结束后,该功能基本上无人使用;

昨日终端开发打上门表示,我们的在线API文档有问题,不能让他们正常的生成模块代码,所有接口都在一个defaultAPI文件中,无法根据 tag注解的属性 自动生成多个文件;(他们想要调用接口,得知我们使用了openAPI后,想要通过 swagger-codegen-cli 生成模块性代码);

于是我抓来了百度,一顿严刑逼问之后,还是没能撬开百度的嘴;

image.png

不得不看这玩意的源码了!

从 github 下载 swagger-codegen-project 的源码!

准备工作

编译很简单,maven项目,没有杂七杂八的配置,jar包下载好可以直接运行

我们项目使用的时 openAPI 3.0.1,所以需要 swagger-codegen 的 3.X 版本

所幸终端同事提供了代码生成的命令

java -jar swagger-codegen-cli-3.0.31.jar generate -l java -i http://127.0.0.1:8080/v3/api-docs -o ./

从命令中可以看出生成代码调用的是 swagger-codegen-cli项目,需要 generate -l java -i http://127.0.0.1:8080/v3/api-docs -o ./ 这些启动参数;

image.png

配置完成后就可以直接运行了;

主方法 main

SwaggerCodegen.main() 方法很长,主要是做了 3 件事

  1. 加载 SwaggerCodegen 定义好的 oas3.yaml 文件(这个文件定义了怎么解析启动参数怎么解析),并通过文件定义的解析规则生成一个解析器 image.png
  2. 解析器会解析启动参数,封装在map中 image.png
  3. 获取 oas3.yaml 中的 x-class-name 属性,通过反射实例化,并将2中解析的参数设置到这个对象中,最后启动它(最主要的业务也就在这里面做了) image.png

Generate.run()

该方法主要还是在装配参数... 比较重要的就是这两行代码了

// 我们传入的是一个 http 的 openAPI-json 地址,这里会请求这个地址获取参数,并封装成一个 OpenAPI 对象
final ClientOptInput clientOptInput = configurator.toClientOptInput();
// 真正生成代码的地方
new DefaultGenerator().opts(clientOptInput).generate();

DefaultGenerator.generate()

在这里生成了 modle 文件(数据对象),API接口文件,项目依赖的接口文件 image.png

到这为止,我们终于能定位到文章开头终端同事提出的问题了,就在这个行代码!

generateApis(files, allOperations, allModels);

image.png

generateApis()

把其他不相干的代码干掉!

API文件名称是由 processPaths(this.openAPI.getPaths()) 决定的!!!

image.png

openAPI.getPaths()

image.png

processPaths(Paths paths)

遍历所有path,并根据不同请求方式进行处理 image.png

processOperation

image.png List<String> tagNames = operation.getTags()中的 operation 就事 paths 下的一个接口数据实例对象

image.png List<Tag> swaggerTags = this.openAPI.getTags(); 就是获取openAPI中的所有tags标签属性 image.png

遍历所有的标签属性,并与 tagNames 进行对比,如果能对比的上则使用 tagNames,否则使用 default 做为tag属性(有可能会导致只生成一个 defaultAPI.java 文件的情况,但是一般情况不会发生,因为就算在项目中不使用 openAPI 的tags注解,也会根据controller生成一个默认的)【问题不在这,还有往下走】

这里有一行对请求,根据tagName进行分组的代码主要问题就出现在这

config.addOperationToGroup(config.sanitizeTag(tag.getName()), resourcePath, operation, codegenOperation, operations);

如果tagName是中文,则会被转换成空字符串!!! image.png image.png

而在 generateApis() 中生成文件名字的代码中,如果tag属性为空字符串,则使用 DefaultApi 代替它!!!

String filename = config.apiFilename(templateName, tag);
👇
public String toApiFilename(String name) {
    return this.toApiName(name);
}
👇
public String toApiName(String name) {
    return name.length() == 0 ? "DefaultApi" : this.initialCaps(name) + "Api";
}

总结

通过 swagger-codegen-cli + openAPI3.0 可以生成类型丰富的模板代码,但是想要生成的API,按照不同controller 进行分组,那么需要在 controller 上添加@Tag标签的,且name属性必须是英文!!!

今日份罪魁祸首:

image.png

最后 祝大家新年快乐!!!