前言
之前有朋友问到怎么动态生成swagger2的文档,因为大部分swagger2的使用是给controller代码加入@API
注解,自动生成的文档,但如果在没有controller的情况下如何生成一个接口文档?
比如上文五步搭建自己的低代码平台搭建的低代码平台,接口都是自动生成,没有controller代码的,那么如何生成这种动态接口对应的swagger2接口文档
本文还是只提供思路,捎带swagger2的源码讲解,毕竟只要懂swagger2的运行原理,想凭空加入接口文档,实属轻而易举
SwaggerResource
直译为"Swagger的资源",Swagger文档是区分资源的,每个资源有自己的名字(name)、地址(url)、版本(swaggerVersion)
SwaggerResource这个资源的区分如何体现的呐?打开swagger2的前端界面
swagger-ui.html doc.html每一个选项即代表一个资源(写过gateway集成接口文档的应该很眼熟),进入前端界面第二个请求的数据就是可选项
swagger-resources如果是自动生成的接口文档,那么只有一个默认SwaggerResource,名字为“default”,url为/v2/api-docs
url
名字(name),版本(version)都挺好理解,这个url是什么意思呐?
答:是一个springweb的访问路径,每个资源有一个访问路径,而请求该路径的返回结果就是这个资源的配置,当我们前端选中某个资源时,就会对路径发起请求去获取该资源的配置(进入界面默认自动访问第一个资源的路径)
api-docs那么就有疑问了,这个访问路径可以获取配置数据,也就是一个接口,那么这个接口是谁写的呐?
自动生成文档情况下,这个接口是Swagger内部帮我们实现的,默认访问路径是/v2/api-docs
源码在springfox.documentation.swagger2.web.Swagger2Controller
,源码截取重点如下
@Controller
@ApiIgnore
public class Swagger2Controller {
public static final String DEFAULT_URL = "/v2/api-docs";
@RequestMapping(
value = DEFAULT_URL,
method = RequestMethod.GET,
produces = { APPLICATION_JSON_VALUE, HAL_MEDIA_TYPE })
@ResponseBody
public ResponseEntity<Json> getDocumentation(
@RequestParam(value = "group", required = false) String swaggerGroup,
HttpServletRequest servletRequest) {
String groupName = Optional.fromNullable(swaggerGroup).or(Docket.DEFAULT_GROUP_NAME);
// 获取扫描注解获取的接口配置信息
Documentation documentation = documentationCache.documentationByGroup(groupName);
// 返回的实体
Swagger swagger = mapper.mapDocumentation(documentation);
return new ResponseEntity<Json>(jsonSerializer.toJson(swagger), HttpStatus.OK);
}
swagger通过扫描注解等方式自动生成default资源的信息,包括资源名称,版本等基础信息,和所有接口的配置信息,封装成Swagger
对象返回给前端,前端根据这个对象信息就画出整个文档界面
Swagger对象
Swagger
对象封装的信息就是文档某资源的所有信息,看一下它的重点参数
basePath
基础路径,一般是"/", 如果通过网关访问则是"/{predicates}"
info
文档名称,版本,描述等
host
ip+端口
tags
文档目录
definitions
所有实体Model的定义,包含Model的类型,属性等,在下图可查看
Modelspaths¶meters&responses
这几个最重要的,即所有接口配置的集合,接口的配置包括路径,参数,返回等信息
扩展
以上Swagger2源码示意图如下
Swagger2研究完Swagger2机制,现在回到问题本身,如何动态生成文档(在没有controller代码情况下),以下提供两个思路
思路1
重写Swagger2Controller,再Swagger对象返回前修改,加入新的接口信息,应该可行,但我没试过
思路2
提供一个新的SwaggerResource,url指向自己写的接口,想返回什么就自己随意写了,只要符合他的返回数据规范即可,重点介绍一下这个方法
SwaggerResourcesProvider接口即SwaggerResource的提供者,它的默认实现注入到了Spring容器中
SwaggerResourcesProvider这就是一个扫描注解提供default资源的实现,我们可以在加一个SwaggerResourcesProvider的实现,并注入Spring容器,并使用@Primary
注解让其被优先使用
@Bean
@Primary
public SwaggerResourcesProvider customSwaggerResourcesProvider() throws NoSuchMethodException {
return () -> {
List<SwaggerResource> resources = new ArrayList<>();
// 添加自定义文档资源
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName("custom");
swaggerResource.setLocation("自定义接口地址...");
swaggerResource.setSwaggerVersion("2.0");
resources.add(swaggerResource);
Map<String, SwaggerResourcesProvider> beans = applicationContext.getBeansOfType(SwaggerResourcesProvider.class);
// 获取default文档资源信息,并加回
for (Map.Entry<String, SwaggerResourcesProvider> entry : beans.entrySet()) {
if (!"customSwaggerResourcesProvider".equalsIgnoreCase(entry.getKey())) {
List<SwaggerResource> defaultSwaggerResources = entry.getValue().get();
resources.addAll(defaultSwaggerResources);
}
}
return resources;
};
}
写一个Rest接口返回动态的接口文档配置信息,其访问路径与在setLocation
指向的路径对应即可
至于这个接口的写法,爱怎写都行(可以读数据库,可以读文件),只要返回数据符合他的规则即可(否则前端报错)
dynamic-api
网友评论