1. 前言
在「初学者商城」- 搭建基础架构(接口)# 7.3.1 Swagger 处有提到后续要聚合显示Swagger
,这里终于得到了实现。
为什么要聚合显示?
- 目前是每个工程都有一个
/swagger-ui.html
的入口,就导致:- 很麻烦,每一个服务工程都要记住对应的地址和端口号
- 不安全,鉴权等操作都写在网关;并且在部署的时候也不会对外暴露内部服务工程的端口
- 不完整,从中间某一环直接请求可能导致出现脏数据
达到的效果
- 只需访问网关的
/swagger-ui.html
页面,就能切换到不同服务工程的接口文档
2. 源码
完整项目地址:https://github.com/intomylife/osc-api
v1.4.2 标签地址:https://github.com/intomylife/osc-api/releases/tag/v1.4.2
注:对于标签的说明「初学者商城」- 写在最前面 #5.1
3. 接口
注:查看更改内容:聚合 Swagger
3.1 聚合的思路
访问每一个服务工程的/swagger-resources
接口(http://localhost:8080/swagger-resources,http://localhost:8081/swagger-resources),发现返回的信息都是[{"name":"default","url":"/v2/api-docs","swaggerVersion":"2.0","location":"/v2/api-docs"}]
这是一个什么接口:用来获取Swagger
的资源信息
我们跟着返回信息中的url
地址走一个,新开页面访问 http://localhost:8080/v2/api-docs,发现返回的是基础工程中所有接口的描述信息(json 格式)
所以在网关中把基础工程和日志工程的/swagger-resources
资源信息整合在一起后,是否就能达到想要的效果呢。答案是肯定的,Swagger
也是支持这种解决方案
3.2 重写核心接口
在网关中新增一个供访问的前端控制器SwaggerResourceController
类
/**
* @ClassName SwaggerResourceController
* @Desc TODO 重写核心接口
* @Date 2020/1/26 6:38 PM
* @Version 1.0
*/
@RestController
@RequestMapping("/swagger-resources")
public class SwaggerResourceController {
private MySwaggerResourceProvider swaggerResourceProvider;
@Autowired
public SwaggerResourceController(MySwaggerResourceProvider swaggerResourceProvider) {
this.swaggerResourceProvider = swaggerResourceProvider;
}
@RequestMapping(value = "/configuration/security")
public ResponseEntity<SecurityConfiguration> securityConfiguration() {
return new ResponseEntity<>(SecurityConfigurationBuilder.builder().build(), HttpStatus.OK);
}
@RequestMapping(value = "/configuration/ui")
public ResponseEntity<UiConfiguration> uiConfiguration() {
return new ResponseEntity<>(UiConfigurationBuilder.builder().build(), HttpStatus.OK);
}
@RequestMapping
public ResponseEntity<List<SwaggerResource>> swaggerResources() {
return new ResponseEntity<>(swaggerResourceProvider.get(), HttpStatus.OK);
}
}
- 此时对应的正是每个服务工程访问资源信息的
/swagger-resources
接口地址 - 重点就是要在
swaggerResources()
方法中把所有需要的服务工程的资源信息返回出来;可以看出,这个方法的返回类型里面刚好可以放入List
集合
3.3 获取服务工程的资源信息
3.3.1 SwaggerResource
SwaggerResource
资源信息对象,里面需要服务工程的地址和名称两个属性;在网关中,可以轻易的获取到所有工程的路由信息,所以这个时候要做的就是,遍历所有路由,把每个路由的地址和名称封装到SwaggerResource
对象中,并添加到集合,最后返回出去
3.3.2 过滤
然后并不是所有的工程都需要添加到Swagger
资源信息集合中,哪些需要:有接口的服务工程,如基础工程和日志工程;那么其他的工程就需要过滤掉。
怎么过滤?
- 在需要过滤的工程的配置文件中,修改应用名称为统一格式
application:
# 应用名称
name: base-service-core
---
application:
# 应用名称
name: log-service-core
- 在遍历添加路由的时候做判断
/**
* 特定服务名称后缀
*/
public static final String SERVICE_SUFFIX = "core";
...
.filter(route -> route.getUri().getHost().indexOf(SERVICE_SUFFIX.toUpperCase()) != -1)
3.4 其它
- 由于网关没有引入公用工程(公用工程中配置了
Swagger
的依赖),所以还需要在网关中引入springfox-swagger2
依赖
<springfox.version>2.9.2</springfox.version>
...
<!-- swagger 依赖 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox.version}</version>
</dependency>
- 版本号的升级
4. 验证
4.1 接口
- 下载
v1.4.2
标签的代码或者对照本篇博客更改v1.4.1
标签的代码 - 项目启动后,访问地址 http://localhost:8000/swagger-ui.html
- 在页面右上角
Select a spec
处可以切换不同工程的接口文档
5. 结语
如果是专门开发接口供他人调用,我觉得集成Swagger
还是非常有必要的,如我手里正在做的一个项目,专门为客户提供他们系统的接口,还又是pc
又是app
,有时候同样的接口还得整理几套接口文档;而且接口不是一次能写好的,需求的变更等原因导致接口改了,那么接口文档也要更上…这是非常浪费时间的!
如果集成了Swagger
,代码写好发布后,就可以直接获取到最新的接口文档了:
“代码即接口文档,接口文档即代码”,巴适。
希望能够帮助到你
over