「这是我参与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文档渲染前端页面。在intelij下ctrl+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
可以看到,该接口仅仅是调用了swaggerResource的get方法,然后就直接返回了,那就再看看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说代码,也可以来技术群讨论问题呦,点赞之交值得深交!