Appearance
Swagger文档之API接口调式
本项目的 Swagger 文档 UI 采用 knife4j ,后端注解使用 Springfox + Swagger 相关注解.
对于 acuity-cloud 项目,访问每个服务的 http://ip:端口/doc.html 都能直接访问服务的文档。 而 http://ip:18760/api/doc.html , 则访问网关聚合后的文档,区别在于
网关聚合文档可以看到整个项目所有服务的文档(前提是后台服务是正常启动状态), 调试时请求会通过网关转发, 所以必须携带
Token、TenantId、Authorition(密文)、ApplicationId
等请求头。访问服务自己的文档, 需要携带 UserId、TenentId、EmployeeId、ApplicationId 等请求头
请求通过 acuity-gateway-server 的过滤器(TokenContextFilter)时, 会将请求头中的 Token 解析成 UserId、EmployeeId,
TenentId、ApplicationId 原封不动的封装到请求头
acuity-cloud 全部项目启动成功后,会有几个 swagger 地址:
- 认证服务文档:http://127.0.0.1:18773/doc.html
- 系统服务文档:http://127.0.0.1:18778/doc.html
- 基础服务文档:http://127.0.0.1:18764/doc.html
- gateway 网关聚合文档:http://127.0.0.1:18760/api/doc.html
通过 swagger 文档调用接口
每个接口请求时,请求头中都要携带封装了用户身份的 token 请求头,请求通过网关路由到后端具体的服务,并在网关的系统会将请求头中的 token 信息解析成用户信息(userId, orgId, name, account 等信息),再次封装到请求头中。
- 大致流程:
txt
"acuity-web-pro"->"acuity-gateway-server": 1 使用账号密码登录
"acuity-gateway-server"->"acuity-oauth-server": 2 路由请求到认证服务,验证账号密码
"acuity-oauth-server" --> "acuity-web-pro": 3 返回Token、用户基本信息
"acuity-web-pro"->"acuity-gateway-server": 4 请求头中携带Token、TenantId、ApplicationId、Authorization发起任意请求
Note Right of "acuity-gateway-server": 5 gateway将请求头中参数封装到请求头
"acuity-gateway-server"-->"acuity-web-pro": 5.1 验证失败,直接返回无权限
"acuity-gateway-server"->"acuity-base-server": 5.2 验证通过,路由请求到后端服务
Note Right of "acuity-base-server": 后端拦截器解析请求头中的用户信息,封装到ThreadLocal
"acuity-base-server"-->"acuity-web-pro": 6 返回数据
"acuity-web-pro"->"acuity-gateway-server": 1 使用账号密码登录
"acuity-gateway-server"->"acuity-oauth-server": 2 路由请求到认证服务,验证账号密码
"acuity-oauth-server" --> "acuity-web-pro": 3 返回Token、用户基本信息
"acuity-web-pro"->"acuity-gateway-server": 4 请求头中携带Token、TenantId、ApplicationId、Authorization发起任意请求
Note Right of "acuity-gateway-server": 5 gateway将请求头中参数封装到请求头
"acuity-gateway-server"-->"acuity-web-pro": 5.1 验证失败,直接返回无权限
"acuity-gateway-server"->"acuity-base-server": 5.2 验证通过,路由请求到后端服务
Note Right of "acuity-base-server": 后端拦截器解析请求头中的用户信息,封装到ThreadLocal
"acuity-base-server"-->"acuity-web-pro": 6 返回数据
- 详细流程:
通过上图可以知道,正常流程中,调用后端请求时,需要在请求头中携带 Token、TenantId、ApplicationId、Authorization 等参数,在网关解析并验证 Token、TenantId 后,将 UserId、TenantId、EmployeeId、ApplicationId 等基础信息封装到请求头中,转发请求到具体的 业务服务中,每个业务服务都有一个上下文拦截器HeaderThreadLocalInterceptor
, 用于将请求头中的 UserId、TenantId、EmployeeId、ApplicationId 等信息封装到 ContextUtil 中。 这样,当请求到达 Controller->Service->Mapper 层时,程序就能通过 ContextUtil 获取当前登录人的信息和租户编码用于切换数据源和业务处理了。
由上可知,默认情况下,每个经过网关请求默认都会携带 Token、TenantId、ApplicationId、Authorization4 个请求头,他们的用途如下:
Token:当前请求来自那个用户(UserId)、员工(EmployeeId)
主要用途:封装用户信息,鉴别请求是谁发起的,请求头中携带了 Token 参数,才能进行URI 鉴权。
Token 设置了 8 小时的有效期,有效期结束表示用户登录失效。
TenantId:当前请求来自那个租户 ID
主要用途:用于切换数据源。请求头中携带了 TenantId 参数,才能操作租户库和URI 鉴权
ApplicationId:当前请求来自那个应用 ID
主要用途:请求头中携带了 ApplicationId 参数,才能进行应用鉴权和URI 鉴权
Authorization:当前请求来自那个客户端
通过网关的 swagger 文档调用接口
需要先调用登录接口获取封装了用户 Id 和员工 Id 的 Token,然后调用业务接口时,传递 Token、TenantId、base64 加密的 Authorization 和 ApplicationId。
- 调用方法生成加密后的 Authorization
前端调用: Base64.encode('acuity_web_pro:acuity_web_pro_secret') 的值为 bGFtcF93ZWI6bGFtcF93ZWJfc2VjcmV0
后端调用: Base64.getEncoder().encodeToString(new String("acuity_web_pro:acuity_web_pro_secret").getBytes())
前端调用: Base64.encode('acuity_web_pro:acuity_web_pro_secret') 的值为 bGFtcF93ZWI6bGFtcF93ZWJfc2VjcmV0
后端调用: Base64.getEncoder().encodeToString(new String("acuity_web_pro:acuity_web_pro_secret").getBytes())
- 打开网关聚合文档:http://127.0.0.1:18760/api/doc.html 。如图所示点击
oauth-认证服务
-登录接口
-登录接口
-调试
-填写请求头
-填写账号密码
- 点击发送
复制返回 登录接口 返回的
token
, 将它作为接口的的请求参数.调用任意接口, 除特殊接口外,任意接口都需要在请求头设置 Authorization、TenantId、ApplicationId、Token 4 个参数。
直接调用业务服务的 swagger 文档
无需配置 Token 和 Authorization, 但需要传递 TenantId、UserId、EmployeeId、ApplicationId
- 访问以下任意服务文档
认证服务文档:http://127.0.0.1:18773/doc.html
系统服务文档:http://127.0.0.1:18778/doc.html
基础服务文档:http://127.0.0.1:18764/doc.html
认证服务文档:http://127.0.0.1:18773/doc.html
系统服务文档:http://127.0.0.1:18778/doc.html
基础服务文档:http://127.0.0.1:18764/doc.html
- 发送请求前, 切换到
请求头部
页面, 设置 TenantId、UserId、EmployeeId、ApplicationId 等请求头参数.
新服务如何接入 swagger 文档
- server 模块加入依赖
xml
<dependency>
<groupId>top.acuity.commons</groupId>
<artifactId>acuity-swagger2-starter</artifactId>
</dependency>
<dependency>
<groupId>top.acuity.commons</groupId>
<artifactId>acuity-swagger2-starter</artifactId>
</dependency>
- SwaggerProperties 提供了动态配置 docket 文档的能力, 修改 acuity-xxx-server.yml 配置文件配置多个文档 group.
yaml
acuity:
swagger:
docket:
xxx:
title: xxx模块接口
base-package: top.acuity.box.xxx.controller
yyy:
title: yyy模块
base-package: top.acuity.box.yyy.controller
acuity:
swagger:
docket:
xxx:
title: xxx模块接口
base-package: top.acuity.box.xxx.controller
yyy:
title: yyy模块
base-package: top.acuity.box.yyy.controller
- 启动项目, 访问新建服务的 swagger 文档地址:http://ip:port/doc.html
- 在网关配置文件中加入新服务的路由即可使用网关聚合文档.
yaml
- id: xxx
uri: lb://acuity-xxx-server // 新服务名
predicates:
- Path=/xxx/**
filters:
- StripPrefix=1
- id: xxx
uri: lb://acuity-xxx-server // 新服务名
predicates:
- Path=/xxx/**
filters:
- StripPrefix=1
- 访问 http://ip:port/api/doc.html 时, 网关通过 SwaggerResourceConfig 类进行聚合. 这个类的实现原理是通过读取网关的路由配置, 然后通过 restTemplate 请求后端服务的文档数据, 所以当后端服务未启动时, 是无法聚合文档的