SpringCloudGateway Nacos+Knife4j api接口聚合

1. 使用背景

在微服务体系下,服务划分粒度的细致,导致多个微服务模块。在开发过程中,开发负责的模块不同,存在多个模块间的业务隔离,如果存在依赖关系,在各个模块做设计时能够更好的对依赖服务更好的了解,增加各个模块之间的了解。基于以上原因,需要对微服务的api统一的展示入口。

2. Gateway 聚合api接口

gateway版本:

 org.springframework.cloudspring-cloud-starter-gateway3.0.6 

springCloud是aliba,版本为:

 com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery 2021.1 

Knife4j版本:

  com.github.xiaoymin knife4j-spring-boot-starter 3.0.3 

2.1 gateway 代码设计

gateway网关lB的策略是根据Nacos注册的服务名进行负载的,访问url形式如下:http://gatewayHost:gatewayPort/serviceName/api

增加SwaggerResourceConfig,主要用于SwaggerResource资源的获取,Knife4j UI调用接口http://localhost:8082/swagger-resources 获取,数据返回格式如下:

{"name": "paas-account",/分组名"url": "/paas-account/test/v3/api-docs",/获取sagger 接口文档原始数据"location": "/paas-account/test/v3/api-docs"}

特别说明

url:/paas-account/test/v3/api-docs 采用/serviceName/servletContextUrl/v3/api-docs 

SwaggerResource资源配置:

SwaggerResourceConfig对应代码如下

@Configuration//在网关处控制开关@ConditionalOnProperty(prefix = "gateway", name = "api-aggregation.enabled", havingValue = "true", matchIfMissing = false)@Primarypublic class SwaggerResourceConfig implements SwaggerResourcesProvider {@Autowiredprivate RouteLocator routeLocator;// 网关应用名称@Value("${spring.application.name}")private String applicationName;//接口地址 使用的是对应的swagger 版本3private static final String API_URI = "/v3/api-docs";@Overridepublic List<SwaggerResource> get() {//接口资源列表List<SwaggerResource> resources = new ArrayList<>();//服务名称列表List<String> routeHosts = new ArrayList<>();// 获取所有可用的应用名称routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null).filter(route -> !applicationName.equals(route.getUri().getHost())).subscribe(route -> {String host ;String basePath = null;Map<String, Object> metadata = route.getMetadata();if (!CollectionUtils.isEmpty(metadata)) {//nacos 中metadata中注册时上报的servletContext,为了能够在返回SwaggerResource 界面访问api信息时。basePath = (String) metadata.get(NacosMetaEnums.CONTEXT_PATH.getKey());}host = StringUtils.hasLength(basePath) ? route.getUri().getHost() + basePath:route.getUri().getHost();routeHosts.add(host);});// 去重,多负载服务只添加一次Set<String> existsServer = new HashSet<>();routeHosts.forEach(host -> {// 拼接urlString url = "/" + host + API_URI;//不存在则添加if (!existsServer.contains(url)) {existsServer.add(url);SwaggerResource swaggerResource = new SwaggerResource();swaggerResource.setUrl(url);swaggerResource.setName(host.split("/")[0]);resources.add(swaggerResource);}});return resources;}}

3. 效果

使用场景:

一个SpringCloudGateway 两个微服务网关,两个微服务名paas-account,paas-alert

Gateway knife4j界面如下:

在调试的时候需要手动添加服务名,也可以修改knife4j UI界面