Spring Cloud Gateway聚合Swagger文档
前言
2020年7月份Springfox 3.0.0发布了,增加了对Webflux、OpenApi 3的支持,适应Gateway,微服务中为方便管理各微服务的接口文档,特此来摸索一下Spring Cloud Gateway集成管理,整个过程没什么代码,简单易用
1、环境及工具介绍
1、gradle,一个基于 JVM 的富有突破性构建工具,简化maven的xml繁琐配置
2、nacos,阿里开发的动态服务发现、配置和服务管理平台,appllo不喜欢用就它了
3、knife4j,Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui(swagger2用的好好的为啥要用这玩意???原皮看厌倦了换上新鲜的感觉)
4、Spring Cloud版本用的是Hoxton.RELEASE,SpringBoot版本2.2.1.RELEASE
以上gradle、nacos环境自行百度搭建,比较简单,不做赘述了
2、微服务端
2.1、先写两个简单的微服务,这里起个很随便的名字(example、cart-service)
端口分别设置为8081和8082
server:
port: 8081
build.gradle:
plugins {
id 'org.springframework.boot' version '2.2.1.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}
group 'com.asan.cart'
version '1.0.0-SNAPSHOT'
sourceCompatibility = 1.8
ext {
set('springBootVersion', "2.2.1.RELEASE")
set('springCloudVersion', "Hoxton.RELEASE")
set('alibabaCloudVersion', "2.2.1.RELEASE")
}
repositories {
mavenLocal()
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
}
configurations {
compile.exclude module: 'tomcat-embed-el'
compile.exclude module: 'spring-boot-starter-tomcat'
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile (
/** 微服务api文档,不需要引入前端ui包 */
'com.github.xiaoymin:knife4j-micro-spring-boot-starter:3.0.2',
/** nacos配置中心 */
'com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-config',
/** nacos注册与发现中心 */
'com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery',
'org.springframework.boot:spring-boot-starter-web',
'org.springframework.boot:spring-boot-starter-undertow'
)
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springBootVersion}"
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
mavenBom "com.alibaba.cloud:spring-cloud-alibaba-dependencies:${alibabaCloudVersion}"
}
}
这里主要就是启动微服务集成knife4j文档,因为tomcat老报错,容器就用的undertow,web默认用的tomcat,如果需要需要使用undertow,增加如下内容排除tomcat依赖:
configurations {
compile.exclude module: 'tomcat-embed-el'
compile.exclude module: 'spring-boot-starter-tomcat'
}
两个微服务客户端增加一个配置类:
package com.asan.example.config;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
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;
@Configuration
@EnableSwagger2WebMvc
public class Swagger2Config {
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.asan.example.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
Contact contact = new Contact("阿三", "http://www.asan.com", "asan@163.com");
return new ApiInfoBuilder()
.title("example服务文档")
.description("example服务API文档")
.contact(contact)
.version("1.0")
.build();
}
}
增加启动类ExampleApplication
package com.asan.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}
接着来一个Controller做文档展示:
Controller这里自己随便写吧,能看到就行,这里也贴一下吧显得不那么空
package com.asan.example.controller;
import com.alibaba.fastjson.JSON;
import com.asan.example.entity.Cat;
import com.asan.example.pojo.dto.CatDto;
import com.asan.example.pojo.vo.PageResult;
import com.asan.example.pojo.vo.ResultVO;
import com.asan.example.service.impl.CatServiceImpl;
import com.asan.example.util.BeanCopierUtil;
import com.asan.example.util.RedisClient;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import tk.mybatis.mapper.entity.Example;
@RestController
@RequestMapping("/v1/example/cat")
@Slf4j
public class CatController {
@Autowired
private CatServiceImpl catService;
@Autowired
private RedisClient redisClient;
@ApiOperation("获取信息")
@GetMapping
public ResultVO<String> getCat(@ApiParam("主键") @RequestHeader("cid") Integer cid) {
Cat cat = catService.selectById(cid);
if (cat != null) {
// 测试缓存
redisClient.setForTimeMIN("SOA:TEXMPLE:CAT:"+cid.toString(), JSON.toJSONString(cat), 30);
}
return new ResultVO(cat);
}
@ApiOperation("新增信息")
@PostMapping
public ResultVO<String> addCat(@RequestBody CatDto catDto) {
Cat cat = new Cat();
BeanCopierUtil.copy(catDto, cat);
catService.insert(cat);
return new ResultVO(Constants.RESULT_SUCCESS);
}
@ApiOperation("修改信息")
@PutMapping
public ResultVO<String> updateCat(@RequestBody CatDto catDto) {
Cat cat = new Cat();
BeanCopierUtil.copy(catDto, cat);
catService.updateById(cat);
return new ResultVO(Constants.RESULT_SUCCESS);
}
@ApiOperation("删除信息")
@DeleteMapping
public ResultVO<String> deleteCat(@ApiParam("主键") @RequestHeader("cid") Integer cid) {
catService.deleteById(cid);
return new ResultVO(Constants.RESULT_SUCCESS);
}
}
然后复制项目更改名称为cart-service,settings-gradle记得也改下
controller里仅修改了路径和类名CartController
3、gateway集成微服务端
启动类一样复制一个过来,改名GatewayApplication
build.gradle文件增加依赖
compile (
/** api文档,包含前端ui包 */
'com.github.xiaoymin:knife4j-spring-boot-starter:3.0.2',
/** nacos配置中心 */
'com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-config',
/** nacos注册与发现中心 */
'com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery',
'javax.servlet:javax.servlet-api:3.1.0',
'org.springframework.cloud:spring-cloud-starter-gateway'
)
下面增加一个配置类
package com.asan.gateway.config;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebFlux;
import java.util.ArrayList;
import java.util.List;
/**
* @author Jaakko
*/
@Configuration
@Primary
@EnableSwagger2WebFlux
public class SwaggerResourceConfig implements SwaggerResourcesProvider {
public static final String API_URI = "v2/api-docs";
private final RouteLocator routeLocator;
private final GatewayProperties gatewayProperties;
public SwaggerResourceConfig(RouteLocator routeLocator, GatewayProperties gatewayProperties) {
this.routeLocator = routeLocator;
this.gatewayProperties = gatewayProperties;
}
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
List<String> routes = new ArrayList<>();
//获取所有路由的ID
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
//过滤出配置文件中定义的路由->过滤出Path Route Predicate->根据路径拼接成api-docs路径->生成SwaggerResource
gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())).forEach(route ->
route.getPredicates().stream()
.filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
.forEach(predicateDefinition -> resources.add(swaggerResource(route.getId(),
predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
.replace("**", API_URI)))));
return resources;
}
private SwaggerResource swaggerResource(String name, String location) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setLocation(location);
swaggerResource.setSwaggerVersion("2.0");
return swaggerResource;
}
}
gateway nacos配置
server:
port: 9200
spring:
cloud:
gateway:
#配置路由路径
routes:
- id: example
uri: lb://example
predicates:
- Path=/example/**
filters:
- StripPrefix=1
- id: cart-service
uri: lb://cart-service
predicates:
- Path=/cart-service/**
filters:
- StripPrefix=1
discovery:
locator:
#开启从注册中心动态创建路由的功能
enabled: true
#使用小写服务名,默认是大写
lower-case-service-id: true
启动两个微服务端,再启动gateway服务
浏览器访问:localhost:9200/doc.html
这里某些依赖手动加进去的,并未实际验证!!!(你可能觉得坑,但八九不离十),可能存在兼容问题,大致应该可以,有问题可以留言讨论!!!
效果图这里就不截了,自行玩耍
公共redis工具类提取
踮脚被吹跑阅读 1.2k
Postcat 如何生成接口文档,2 分钟学会
圆圆大姐头赞 2阅读 370
SpringCloud Gateway 通过 Nacos 配置动态路由 (代码片段)
毛宇鹏阅读 3.9k
装上这个插件,你就能一键生成接口文档!
气势凌人的柿子赞 2阅读 247
除了 Swagger,这个开源 API 工具生成文档更高效!
圆圆大姐头赞 2阅读 207
国产 API 工具天花板,用来搞项目真的不错
气势凌人的柿子赞 2阅读 126评论 1
Swagger URL 插件上线,同步生成文档更简单!
Postcat赞 1阅读 373评论 1
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。