基于Gateway网关实现Swagger接口文的聚合
码友们大家好!
鲸鱼今天又来更新了,这几天一直在尝试搭建自己的项目框架,也蛮久没没有更新了。 在搭建GateWay网关时,也踩了很多坑,接下来让鲸鱼带大家尝试一下Gateway网关聚合接口文档
版本参照表
<!-- spring 版本控制区 -->
<spring-cloud.verison>Hoxton.SR3</spring-cloud.verison>
<spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
<spring-boot.version>2.2.5.RELEASE</spring-boot.version>
| 使用依赖 | 使用版本 |
|---|---|
| Spring Boot | 2.2.5.RELEASE |
| spring-cloud-alibaba | 2.2.1.RELEASE |
| spring-cloud | Hoxton.SR3 |
| loadbalancer | 2.2.2.RELEASE |
以上就是我们本次搭建Gateway聚合Swagger的Spring版本啦 接下来是本次使用的Swagger版本
<!-- springfox swagger ui界面依赖 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox.swagger.version}</version>
</dependency>
<!-- Spring fox 公共版本定义 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${springfox.swagger.version}</version>
</dependency>
具体版本号为:3.0.0,大家可以自己选择,我觉得这个UI要好看些,所以就用了这个
自定义spring-swagger-starter
- 创建新的maven项目,注意:这里需要指定parent标签,使用spring-boot-starter-parent即可
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.cattywhale</groupId>
<artifactId>hommie-component-swagger-starter</artifactId>
<version>1.0.0-Final-SNAPSHOT</version>
<name>hommie-component-swagger-starter</name>
<description>Swagger Project for Spring Boot</description>
- 导入依赖
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<springfox.swagger.version>3.0.0</springfox.swagger.version>
<!-- swagger.version -->
<xiaoymin.swagger.version>1.9.6</xiaoymin.swagger.version>
<!-- lombok.version -->
<lombok.version>1.18.18</lombok.version>
<spring-boot.version>2.2.5.RELEASE</spring-boot.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.cattywhale</groupId>
<artifactId>hommie-component-bom</artifactId>
<version>${project.version}</version>
</dependency>
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${springfox.swagger.version}</version>
</dependency>
<!--swagger-ui 这里是用了一个好看一点ui界面-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>${xiaoymin.swagger.version}</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>${spring-boot.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 当前项目依赖 -->
<dependencies>
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
</dependency>
<!--swagger-ui 这里是用了一个好看一点ui界面-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- 自动配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
- 创建SwaggerAutoConfiguration自动配置类,这部分的配置是与后面我们在微服务项目中基于yml文件进行配置的基础Swagger信息,由于依赖了SwaggerProperties,因此我们还需要自己封装一个SwaggerProperties的实体类。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
/**
* project name:<font size = "1"><b>swagger启动具体配置类</b></font><br>
* file name:<font size = "1"><b>SwaggerAutoConfiguration</b></font><br>
* description:<font size = "1"><b>swagger启动具体配置类</b></font><br>
* @version 1.0.0<br>
* @update [1] [2024/4/1 9:51] [CattyWhale] [新建] <br>
*/
@Configuration
public class SwaggerAutoConfiguration {
/* 引入当前SwaggerProperties参数配置 */
@Autowired(required = true)
private SwaggerProperties swaggerProperties;
/* 注入Docket对象 */
@Bean
public Docket docket() {
Set<String> set = new HashSet<>();
set.add("http");
set.add("https");
return new Docket(DocumentationType.SWAGGER_2).pathMapping("/")
.enable(true)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
.paths(PathSelectors.any())
.build()
.protocols(set);
}
/**
* title:<font size = "1"><b>apiInfo</b></font><br>
* description:<font size = "1"><b> 配置Swagger信息 = ApiInfo </b></font><br>
* @param null <br>
* @return <br>
* @update [1] [2024/4/1 14:58] [xuzihan] [新建] <br>
*/
private ApiInfo apiInfo() {
// 作者信息
Contact contact = new Contact(swaggerProperties.getAuthor().getName(),
swaggerProperties.getAuthor().getUrl(),
swaggerProperties.getAuthor().getEmail());
return new ApiInfo(swaggerProperties.getApiInfo().getTitle(),
swaggerProperties.getApiInfo().getDescription(),
swaggerProperties.getApiInfo().getVersion(),
swaggerProperties.getApiInfo().getTermsOfServiceUrl(),
contact,
swaggerProperties.getApiInfo().getLicense(),
swaggerProperties.getApiInfo().getLicenseUrl(),
new ArrayList<>());
}
}
4.封装SwaggerProperties的实体类
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* project name:<font size = "1"><b>Swagger参数配置信息类</b></font><br>
* file name:<font size = "1"><b>SwaggerProperties</b></font><br>
* description:<font size = "1"><b>Swagger参数配置信息类</b></font><br>
* @version 1.0.0<br>
* @update [1] [2024/4/1 9:51] [CattyWhale] [新建] <br>
*/
@Data
@ConfigurationProperties(prefix = SwaggerProperties.PREFIX)
@Component
@EnableConfigurationProperties
public class SwaggerProperties {
public static final String PREFIX = "spring.swagger";
// 包
private String basePackage;
// 作者相关信息
private Author author;
// API相关信息
private ApiInfo apiInfo;
@Data
public static class ApiInfo{
String title;
String description;
String version;
String termsOfServiceUrl;
String license;
String licenseUrl;
}
@Data
public static class Author{
private String name;
private String email;
private String url;
}
}
- 重点:基于Srping的自动配置原理,在当前项目的resorces目录下书写META-INF/spring.factories文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration = \
com.cattywhale.swagger.starter.config.SwaggerAutoConfiguration
以上就是我们的的自定义starter的过程,实现完上述步骤后,基于maven install打包即可
做完以上内容,我们的准备工作就结束了,开始搭建自己的微服务及网关
搭建微服务与网关的过程在这里就不予赘述啦,直接进入正题:如何在Gateway网关中聚合文档实现网关访问多个服务实例接口文档
- 网关导入依赖:
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
</dependency>
<!--swagger-ui 这里是用了一个好看一点ui界面-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
这里有一个坑,在Spring Cloud Nacos中,由于原版的nacos使用的是ribbon实现的负载均衡,所以在搭建网关进行服务发现时需要排除nacos中的ribbon组件
<!-- nacos 注册中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
- 书写SwaggerResourceProvider实现网关动态获取服务实例的定义接口
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Component
@Primary
public class GatewaySwaggerResourcesProvider implements SwaggerResourcesProvider {
/* 访问后缀名 */
private static final String SWAGGER2URL = "/v2/api-docs";
/* 网关路由 */
@Autowired
private RouteLocator routeLocator;
/* 网关应用名 */
@Value("${spring.application.name}")
private String self;
/* 让swagger可以找到其对应的服务 */
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
List<String> routeHosts = new ArrayList<>();
// 获取当前所有的可用host : serverID
routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null)
.filter(route -> !self.equals(route.getUri().getHost()))
.subscribe(route -> routeHosts.add(route.getUri().getHost()));
// 记录已经添加过的server
Set<String> alreadyAddServers = new HashSet<>();
routeHosts.forEach(instance -> {
String url = "/" + instance.toLowerCase() + SWAGGER2URL;
if (!alreadyAddServers.contains(url)){
alreadyAddServers.add(url);
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setUrl(url);
swaggerResource.setName(instance);
resources.add(swaggerResource);
}
});
return resources;
}
}
- 在具体的微服务中导入自定义starter,并书写接口及注解标记
- 书写具体微服务的配置文件:
# 配置服务名,nacos发现地址
spring:
application:
name: server-name
cloud:
nacos:
discovery:
namespace: configFile-namespace
server-addr: host : port
# 自定义starter会获取以下信息作为参数进行配置
swagger:
basePackage: 控制层接口所在的包路径
author:
name: CattyWhale
email: email
url: 访问url 域名
apiInfo:
title: Swagger测试服务
description: Swagger测试相关接口
version: 1.0
termOfServiceUrl: http://127.0.0.1:${server.port}/${spring.application.name}
license: license
licenseUrl: licenseUrl
# 声明服务端口
server:
port: 30001
- 书写Gateway网关配置
# 声明网关端口
server:
port: 10001
# 网关具体配置
spring:
cloud:
gateway:
discovery:
locator:
# 开启从注册中心动态创建路由的功能,利用微服务名进行路由
enabled: true
routes:
- id: server-name
# 匹配后提供服务路由地址
uri: lb://server-name
# 断言
filters:
- StripPrefix=1
predicates:
- Path=/swagger/**
- 启动Gateway及对应微服务测试
最终结果如果是上述结果就是正确的了! 这部分可能会出现503或者是404的报错,小伙伴可以自己尝试解决一下,如果有问题可以私信或是评论哦,我会努力解决的!
今天的Gateway集成Swagger实现基于网关访问接口文档就到此为止啦!
最后希望各位大佬或者是正在一起学习的小伙伴节节高升!技术突飞猛进!如果喜欢鲸鱼的文章可以伸伸小手点点关注,各位的关注就是鲸鱼持续更新的动力!!!!