文章目录
前言
前面已经介绍了很多关于网关的博客了,当前的形势前后端分离已经是大势所趋,我们需要为前端提供后端接口的服务,面对众多的后端微服务程序我们如果一个应用一份文档,这是复杂且难以维护的,那没有没一款框架能帮我们帮各个微服务程序的文档聚合到一个程序呢?有,它就是:Knife4j,接下来我们学习怎么使用和整合文档到网关服务中。
注意我这里使用的注册中心是nacos和eureka略有区别
一、组件特点
- ✅ 使用简单(最低4行配置搞定聚合),学习成本低
- ✅ 解耦Spring Cloud Gateway网关组件,聚焦文档聚合功能,职责单一
- ✅ 提供手动配置、微服务自动发现两种灵活配置方式聚合子服务文档
- ✅ 可以同时聚合Swagger2、OpenAPI3两种不同的规范
- ✅ 灵活配置聚合规则,自定义排除规则支持
- ✅ 微服务场景下支持服务的上线、下线场景,文档状态与子服务保持一致,无需重启服务
二、深入了解
1. 使用简单
按照官方的说法,你只需要配置这四行配置,你的网关服务和文档服务就整合到一块了,是不是画大饼呢?我们接着往下看
knife4j:
gateway:
# ① 第一个配置,开启gateway聚合组件
enabled: true
# ② 第二行配置,设置聚合模式采用discover服务发现的模式
strategy: discover
discover:
# ③ 第三行配置,开启discover模式
enabled: true
# ④ 第四行配置,聚合子服务全部为Swagger2规范的文档
version: swagger2
2. 场景描述
使用场景主要分为手动聚合和自动聚合
手动聚合
手动聚合适用于Swagger2/OpenAPI3两种规范同时使用,且子服务不多的情况
自动聚合
自动聚合依赖于注册中心,我们的子服务规范实现需要统一,要么全部用Swagger2规范,或者OpenAPI3规范
下面我们以自动聚合的介绍为主 \color{#0000FF}{下面我们以自动聚合的介绍为主} 下面我们以自动聚合的介绍为主
三、服务接口(提供者provider&消费者consumer)
我们前面开发的提供者服务和消费者服务作为对外服务的两个应用程序,我们需要提供相应的接口文档。
1. 确认版本
项目使用JDK17+Sring Boot 3.0,所以这里使用红框内容
2. 引入依赖
<!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-openapi3-jakarta-spring-boot-starter -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.5.0</version>
</dependency>
3. swagger配置
package org.example.nacos.provider.config;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
/**
* Create by zjg on 2024/8/4
*/
@Configuration
public class Knife4jConfiguration {
@Value("${server.port}")
private int port;
/**
* 根据@Tag 上的排序,写入x-order
*
* @return the global open api customizer
*/
@Bean
public GlobalOpenApiCustomizer orderGlobalOpenApiCustomizer() {
return openApi -> {
if (openApi.getTags()!=null){
openApi.getTags().forEach(tag -> {
Map<String,Object> map=new HashMap<>();
map.put("x-order", new Random().nextInt(0,100));
tag.setExtensions(map);
});
}
if(openApi.getPaths()!=null){
openApi.addExtension("x-test123","333");
openApi.getPaths().addExtension("x-abb",new Random().nextInt(1,100));
}
};
}
@Bean
public OpenAPI customOpenAPI() {
Info info = new Info();
Contact contact = new Contact();
contact.setName("zhangjg");
contact.setUrl("http://localhost:"+port);
contact.setEmail("zhangjg@gmail.com");
info.setContact(contact);
return new OpenAPI()
.info(info
.title("提供者应用程序接口文档")
.version("1.0")
.description( "提供者服务")
.termsOfService("http://doc.xiaominfo.com")
.license(new License().name("Apache 2.0")
.url("http://doc.xiaominfo.com")));
}
}
4. 新增控制器
package org.example.nacos.consumer.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* Create by zjg on 2024/8/4
*/
@Tag(name = "首页模块")
@RestController
public class IndexController {
@Operation(summary = "向客人问好")
@GetMapping("/sayHi")
public ResponseEntity<String> sayHi(@RequestParam(value = "name")String name){
return ResponseEntity.ok("Hi:"+name);
}
}
消费者程序类似,不再演示,到这里我们的微服务文档就准备好了
三、文档聚合(gateway)
1. 引入依赖
提供基于Spring Cloud Gateway网关简单聚合的starter组件包
<!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-gateway-spring-boot-starter -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-gateway-spring-boot-starter</artifactId>
<version>4.5.0</version>
</dependency>
2. 新建扩展配置
网关启用扩展文件
server:
port: 8888
spring:
application:
name: gateway-service
cloud:
nacos:
config:
file-extension: yaml
server-addr: ${NACOS_SERVER_ADDR}
namespace: ${NACOS_NAMESPACE}
username: ${NACOS_USERNAME}
password: ${NACOS_PASSWORD}
shared-configs[0]:
data-id: base-discovery.yaml
group: DEFAULT_GROUP
refresh: true
extension-configs[0]:
# 配置支持共享的 Data Id
data-id: ext-knife4j-gateway.yaml
# 配置 Data Id 所在分组,缺省默认 DEFAULT_GROUP
group: DEFAULT_GROUP
# 配置Data Id 在配置变更时,是否动态刷新,缺省默认 false
refresh: true
四、文档展示
左边菜单栏文档管理下面的各种模块就是我们的文档,对应一个控制器,其内容是根据Tag注解的name所得
http://{gateway.host}:{gateway.port}/doc.html
大家要注意应用程序中的过滤器和拦截器,会对我们获取文档数据造成影响,可以根据路径/v3/api-docs
添加白名单
总结
建议大家避免使用
@RequestMapping
,尽量使用@GetMapping
和@PostMapping
等Rest
风格的注解