swagger-ui 实现原理之接口解析

1,363 阅读3分钟

「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战」。

哈喽大家好,我是阿Q!

今天呢,我们就来了解一下 swagger-ui 实现原理。

/v2/api-docs 接口

正如之前所说,swagger-spring-boot-starter是客户端组件,微服务客户端使用封装好的该组件扫描项目中的swagger信息并上传到swagger注册中心。

关键的技术点是如何手动扫描项目的swagger信息。只要能拿到swagger信息,无论使用什么方式上传到swagger注册中心都很简单了。

关于这个技术点想了一会儿没想到好办法,只能去看源代码,看了一会儿觉得云里雾里的,最终突然灵光一闪,swagger-ui的实现给了我灵感。

swagger-ui会请求后端一个接口获取swagger文档:/v2/api-docs,然后根据拿到的swagger文档渲染前端页面。在intelijctrl+shift+f组合键搜索该关键字很容易能够找到相关代码(springfox 2.9.2):

springfox.documentation.swagger2.web.Swagger2Controller#getDocumentation

这段代码详细讲解了如何获取Swagger对象,这给我的实现提供了很大的参考依据。

/swagger-resources接口

源码解析

在通过网关聚合模式下查看swagger文档的时候,会发现前端会请求后端一个接口获取所有的group信息:/swagger-resources,老规矩,还是ctrl+shift+f快捷键全局查询,可以看到相关代码的实现

springfox.documentation.swagger.web.ApiResourceController#swaggerResources

可以看到,该接口仅仅是调用了swaggerResourceget方法,然后就直接返回了,那就再看看swaggerResource是什么东西

它只是个接口,那它的实现类呢,它的实现类只有一个,就是InMemorySwaggerResourcesProvider

它的GET方法是这样子的

看到这里我不禁陷入了思考,难道要给documentationCache手动填充文档?但是看这个名字就知道是基于内存的东西,要维护CRUD状态似乎有点麻烦,看看这个代码是咋写的

确实是基于内存的东西,但是只提供了add方法,没提供remove方法,那获取到documentionLookup对象之后手动移除呢?仔细看看all()方法

它被Collections工具类包装成了不可修改的了,那手动移除的方式就没戏了......

换一种思路,其实还有另外一种方法,重新实现SwaggerResourcesProvider接口,并将实现类使用@Primary注解修饰,覆盖默认的InMemorySwaggerResourcesProvider实现类,重写get()方法即可。

那这时候的自由度就大了去了,这里可以直接使用从数据库读的方式获取所有的group

返回值解析

/swagger-resources接口的返回值是List<swaggerresource>类型,SwaggerResource类的定义如下

  • name:显示的名字
  • url:前端根据该url获取swagger文档详情(默认是/v2/api-docs,其实可以修改该值让swagger-ui请求自定义的接口获取swagger文档)
  • swaggerVersion:就是swagger版本,一般就是2.0

题外篇

阿Q将持续更新java实战方面的文章,感兴趣的可以关注下公众号:阿Q说代码,也可以来技术群讨论问题呦,点赞之交值得深交!