前言
SpringCloudGateway是Spring官方基于Spring 5.0,SpringBoot 2.0和ProjectReactor等技术开发的网关,SpringCloudGateway旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。在博客‘SpringCloudAlibaba微服务项目’中我们使用gateway实现了简单的网关转发服务,在本文中,我们来进一步学习gateway的其他功能。
简介
一、为什么需要网关服务
微服务架构中有多个服务,如果没有网关,客户端在调用接口时必须使用每个微服务的地址,当微服务数量很多时,这就是很大的工作量,还面临无法统一鉴权、跨域无法访问等问题。引入网关服务后,网关作为所有请求的唯一入口,这样一来,就简化了客户端工作,客户端只需要和网关交互,而不再需要关注项目中的各种微服务。
当然,这就又引入了一个问题,就是网关又成为了微服务体系中的瓶颈,如果网关宕机,那么整个微服务项目也就宕机了;解决这一问题的方案是将网关又分为流量网关和API网关,流量网关负责限制整体的流量控制等,而API网关负责与业务紧密结合的服务治理、身份认证、路由等。流量网关我们可以用nginx来担任,而在springcloud项目中,我们可以使用gateway来担任API网关。

二、Gateway三大核心

gateway服务转发示意图
三、Gateway工作流程
客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到Gateway Web Handler。Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(’pre’)或之后(’post’)执行业务逻辑。

Gateway工作流程示意图
功能详解
一、路由功能
1. 自定义路由
我们在之前的demo中已经实现了一个路由,我们来看看其中的配置,这是我们配置在nacos中的gateway.yaml文件
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | server:port: 8088
 
 spring:
 cloud:
 
 gateway:
 
 routes:
 
 - id: order_route
 
 uri: lb://service-order
 
 predicates:
 
 - Path=/order/**
 
 
 | 
从配置文件中可以看到,配置的‘uri’指向‘service-order’服务,这一服务我们已经注册到了nacos中,nacos会自动帮我们解析地址并转发;而根据配置的断言‘predicates’,当请求路径中以‘/order’开头,则匹配成功,可以转发;我们来简单测试

自定义路由测试

自定义路由测试结果
可以看到我们访问gateway服务,它自动帮我们转发到了‘service-order’服务
2. 自动路由
gateway的自动路由功能,可以从服务注册中心(如 Eureka、Consul、Nacos 等)中的服务列表,为每个服务生成默认的路由规则;路由的 Path 为 /serviceId/**,其中 serviceId 是服务的名称(通常是小写形式);例如,如果注册中心有一个服务名为 user-service,Gateway 会自动生成一个路由规则,将 /user-service/** 的请求转发到 user-service 服务。
在gateway服务的配置文件中添加如下内容:
| 12
 3
 4
 5
 6
 7
 8
 
 | spring:
 cloud:
 gateway:
 
 discovery:
 locator:
 enabled: true
 
 | 
重新启动gateway服务以后我们来做简单测试

自动路由测试结果1

自动路由测试结果2
可以看到,虽然我们没有添加关于‘service-account’的路由设置,但是我们配置了自动路由,所以我们的请求被转发到了‘service-account’服务
3. 在代码中实现路由功能
我们除了在yaml文件中进行路由配置,也可以在代码中实现路由配置
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | @Configurationpublic class GatewayConfig {
 @Bean
 public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
 return routeLocatorBuilder.routes()
 
 .route("provider-route", r -> r.path("/provider/test/sendMessage")
 .uri("lb://service-provider"))
 .build();
 }
 }
 
 | 
二、断言功能
断言(Predicate)也翻译为谓词,是一个函数式接口,通常用于表示一个返回值为布尔值的函数(即返回 true 或 false 的函数)。它常用于条件判断、过滤、匹配等场景。
1. Path
这个谓词即通过请求路径匹配,可以使用正则表达式,多个请求路径可以使用逗号进行分隔;这个谓词我们在自定义路由中已经使用过了,这里就不赘述
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | spring:
 cloud:
 gateway:
 routes:
 - id: host_route
 uri: https://example.org
 predicates:
 
 - Path=/foo/{segment},/bar/{segment},/order/**,account/*
 
 | 
- 注:** 用于多层路径匹配,适合递归匹配整个目录树,* 用于单层路径匹配,适合匹配当前目录的文件或目录。
2. After
(1)谓词介绍
	该谓词匹配在指定日期时间之后发生的请求
(2)添加配置
	在‘gateway’的yaml文件中添加配置
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | spring:
 cloud:
 gateway:
 routes:
 
 - id: after-predicates-route
 uri: lb://service-account
 predicates:
 - Path=/gatewayTest/after
 
 - After=2025-02-22T23:59:59.255+08:00[Asia/Shanghai]
 
 | 
时间戳可以用下面的代码生成
| 12
 3
 4
 5
 6
 
 | public class ZonedDateTimeDemo {public static void main(String[] args) {
 ZonedDateTime zonedDateTime = ZonedDateTime.now();
 System.out.println(zonedDateTime);
 }
 }
 
 | 
(3)在‘service-account’中添加代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | @Slf4j@RestController
 @RequestMapping("/gatewayTest")
 public class GatewayTestController {
 
 
 
 
 
 @GetMapping("/after")
 public Result afterTest() {
 log.info("com.qiuli.account.controller.TestController.afterTest");
 return Result.ok().message("Predicates After Test");
 }
 }
 
 | 
(4)重启服务后进行测试


从测试结果我们可以看到我们是在23日进行的测试,而我们设置的指定日期是在22日23点59分59秒后,是符合条件的,所以成功转发;
我们可以设置一个还没有到的时间,比如就将日期延后一天

重启服务后再次测试

可以看到,因为设置的时间还没到,所以这次的转发是失败的
3. Before
(1)谓词介绍
	该谓词匹配在指定日期时间之前发生的请求
(2)添加配置
		在‘gateway’的yaml文件中添加配置
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | spring:
 cloud:
 gateway:
 routes:
 
 - id: after-predicates-route
 uri: lb://service-account
 predicates:
 - Path=/gatewayTest/before
 
 - After=2025-02-23T23:59:59.255+08:00[Asia/Shanghai]
 
 | 
(3)在‘service-account’中添加代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | 
 
 
 
 @GetMapping("/before")
 public Result beforeTest() {
 log.info("com.qiuli.account.controller.GatewayTestController.beforeTest");
 return Result.ok().message("Predicates Before Test");
 }
 
 | 
(4)重启服务后进行测试


可以看到,我们在23日测试,设置条件为23日23点59分59秒之前,所以请求成功转发 了;我们可以修改指定时间为22日23点59分59秒

再次进行测试

可以看到,因为已经超过了测试时间,所以这次的转发请求失败了
4. Between
(1)谓词介绍
	该谓词匹配在指定日期时间之间发生的请求
(2)添加配置
		在‘gateway’的yaml文件中添加配置
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | spring:
 cloud:
 gateway:
 routes:
 
 - id: between-predicates-route
 uri: lb://service-account
 predicates:
 - Path=/gatewayTest/between
 
 - Between=2025-02-22T23:59:59.255+08:00[Asia/Shanghai],2025-02-23T23:59:59.255+08:00[Asia/Shanghai]
 
 | 
(3)在‘service-account’中添加代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | 
 
 
 
 @GetMapping("/between")
 public Result betweenTest() {
 log.info("com.qiuli.account.controller.GatewayTestController.betweenTest");
 return Result.ok().message("Predicates Between Test");
 }
 
 | 
(4)重启服务后进行测试


我们的测试时间为23日,设置时间为22日23点59分59秒到23日23点59分59秒,所以请求成功转发;但如果我们设置时间到一天之前,21日23点59分59秒到22日23点59分59秒,那么现在的时间就不在范围内

我们再次测试

可以看到,这次请求没有成功转发
5. Cookie
(1)谓词介绍
cookie是一个键值对,而本谓词有两个参数,一个是 Cookie name , 一个是正则表达式;路由规则会通过获取对应的 Cookie 值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行
(2)添加配置
	在‘gateway’的yaml文件中添加配置
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | spring:
 cloud:
 gateway:
 routes:
 - id: cookie-predicates-route
 uri: lb://service-account
 predicates:
 - Path=/gatewayTest/cookie
 
 - Cookie=password,\d+
 
 | 
(3)在项目‘service-account’中添加代码
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | 
 
 
 @GetMapping("/cookie")
 public Result cookieTest() {
 log.info("com.qiuli.account.controller.GatewayTestController.cookieTest");
 return Result.ok().message("Predicates Cookie Test");
 }
 
 | 
(4)重启项目后进行测试
首先我们新建一个request,填写基本测试信息后点击‘save’旁的‘Cookies’按钮,来到Cookie管理页面;先添加目标域名(我们在本地测试,所以填localhost),再在目标域名下添加一个cookie,根据gateway中配置的路由,我们添加如下cookie
| 1
 | password=123; Path=/; Expires=Tue, 24 Feb 2026 01:26:38 GMT;
 | 
点击保存,然后再发送请求

请求中包含的cookie

测试结果1

测试结果2
可以看到,我们配置了符合路由规则的cookie后,请求已经正确转发了;如果我们将cookie的值改为字符,再次测试,请求将转发失败

将cookie的值改为字母

转发失败
(1)谓词介绍
	Header谓词和Cookie谓词一样,也是一个键值对,一个 header 中属性名称和一个正则表达式,这个属性值和正则表达式匹配则执行
(2)添加配置
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | spring:
 cloud:
 gateway:
 routes:
 - id: header-predicates-route
 uri: lb://service-account
 predicates:
 - Path=/gatewayTest/header
 
 - Header=Authorization,\d+
 
 | 
(3)在项目‘service-account’中添加代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | 
 
 
 
 @GetMapping("/header")
 public Result headerTest() {
 log.info("com.qiuli.account.controller.GatewayTestController.headerTest");
 return Result.ok().message("Predicates Header Test");
 }
 
 | 
(4)重启服务后进行测试
	我们在postman中新建一个request,填写基本信息后在Headers栏目中添加‘Authorization:123’,然后发送请求


可以看到,我们根据路由规则在header中配置了相应参数,请求成功转发;如果我们将header中的参数删除,再次发送请求,请求将转发失败

转发失败
7. Host
(1)谓词介绍
	Host谓词接收一组参数,一组匹配的域名列表,多个域名之间使用逗号分隔,它通过参数中的主机地址作为匹配规则
(2)添加配置
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | spring:
 cloud:
 gateway:
 routes:
 - id: host-predicates-route
 uri: lb://service-account
 predicates:
 - Path=/gatewayTest/host
 
 - Host=**.somehost.org,**.anotherhost.org
 
 | 
(3)在项目‘service-account’中添加代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | 
 
 
 
 @GetMapping("/host")
 public Result hostTest() {
 log.info("com.qiuli.account.controller.GatewayTestController.hostTest");
 return Result.ok().message("Predicates Host Test");
 }
 
 | 
(4)重启服务后进行测试
	在postman新建一个request,填写基本信息后在headers栏目添加参数‘Host:www.somehost.org',发送请求进行测试

添加Host参数后发送请求

成功收到转发请求
可以看到请求成功转发;我们再修改Host参数为’Host:www.baidu.com‘,再次发送请求

请求转发失败
可以看到,当Host参数与设置的值不匹配,请求转发失败
8. Method
(1)谓词介绍
	该谓词可以通过你请求的方式(GET、POST、PUT、DELETE、…)来进行匹配,只有指定方式的请求才可以匹配成功
(2)添加配置
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | spring:
 cloud:
 gateway:
 routes:
 - id: method-predicates-route
 uri: lb://service-account
 predicates:
 - Path=/gatewayTest/method
 
 - Method=GET,POST
 
 | 
(3)在项目’service-account‘中添加代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | 
 
 
 
 @GetMapping("/method")
 public Result methodTest1() {
 log.info("com.qiuli.account.controller.GatewayTestController.methodTest1");
 return Result.ok().message("Predicates Method Test1");
 }
 
 
 
 
 
 
 @PostMapping("/method")
 public Result methodTest2() {
 log.info("com.qiuli.account.controller.GatewayTestController.methodTest2");
 return Result.ok().message("Predicates Method Test2");
 }
 
 | 
(4)重启服务后进行测试
	我们在postman新建一个request,先用get请求类型测试
	
GET请求类型测试结果

成功接到转发请求
可以看到请求成功,然后再用POST请求类型测试

POST请求类型测试结果

成功接到转发请求
可以看到请求转发成功;我们再用PUT类型发送请求

PUT请求类型测试结果
可以看到,如果请求类型不匹配,请求转发失败
9. Query
(1)谓词介绍
	这个谓词是根据请求中的参数进行匹配,该谓词也支持传入两个值,一个是属性名一个是属性值,属性值可以是正则表达式
(2)添加配置
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | spring:
 cloud:
 gateway:
 routes:
 - id: query-predicates-route
 uri: lb://service-account
 predicates:
 - Path=/gatewayTest/query
 
 - Query=number,\d+
 
 | 
(3)在项目’service-account‘中添加代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | 
 
 
 
 
 @GetMapping("/query")
 public Result queryTest(@RequestParam Integer number) {
 log.info("com.qiuli.account.controller.GatewayTestController.queryTest");
 return Result.ok().message("Predicates Query Test");
 }
 
 | 
(4)重启服务后进行测试
	在postman中新建一个request,请求中添加参数number=123,然后进行测试

添加参数number进行测试

成功接收到转发的请求
可以看到,添加了符合设置的参数,请求转发成功;我们将参数改为字符串,再次测试

修改参数后进行测试
可以看到,我们传递的参数不符合设置的正则表达式,请求转发失败
10. RemoteAddr
(1)谓词介绍
| 1
 | 该谓词通过ip和子网掩码进行匹配,支持设置某个 ip 区间号段,支持单个 ip 地址,还支持接受 cidr 符号 (IPv4 或 IPv6) 字符串的列表(最小大小为 1),例如 192.168.0.1/16 (其中 192.168.0.1 是客户端发送请求的 ip 地址,16指二进制16位数字,即子网掩码(255.255.0.0),24位即子网掩码(255.255.255.0))
 | 
(2)添加配置
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | spring:
 cloud:
 gateway:
 routes:
 - id: remote-addr-predicates-route
 uri: lb://service-account
 predicates:
 - Path=/gatewayTest/remoteAddr
 
 
 - RemoteAddr=192.168.124.12/24
 
 | 
(3)在项目’service-account‘中添加代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | 
 
 
 
 @GetMapping("/remoteAddr")
 public Result remoteAddrTest() {
 log.info("com.qiuli.account.controller.GatewayTestController.remoteAddrTest");
 return Result.ok().message("Predicates Remote Addr Test");
 }
 
 | 
(4)重启服务后进行测试
	在postman新建一个request,设置请求url为’http://192.168.124.12:8088/gatewayTest/remoteAddr‘,进行测试
	
设置ip后进行测试

测试结果
可以看到,我们使用设置的ip发送请求,请求被成功转发;我们可以再修改ip发送请求

修改ip后的测试结果
可以看到,我们没有使用设置的ip发送(localhost是回环地址,即127.0.0.1),请求转发失败
11. Weight
(1)谓词介绍
| 12
 3
 4
 5
 6
 7
 8
 
 | 该谓词用于实现基于权重的路由分发。它允许你将流量按指定的权重比例分发到不同的服务实例或路由上。这对于实现灰度发布、A/B 测试或负载均衡的场景非常有用。
 谓词的配置需要两个参数:
 group:权重组的名称。同一组的路由会共享权重分配逻辑。
 weight:当前路由的权重值。权重值越高,分配到该路由的流量比例越大。
 # 示例
 - Weight=group, weight
 # 注:只有group名称相同(即在同一组中的路由),权重配置才会生效;
 
 | 
(2)添加配置
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | spring:
 cloud:
 gateway:
 routes:
 - id: weight-1-predicates-route
 uri: lb://service-account
 predicates:
 - Path=/gatewayTest/weight
 - Weight=group-test, 80
 - id: weight-2-predicates-route
 uri: lb://service-order
 predicates:
 - Path=/gatewayTest/weight
 - Weight=group-test, 20
 
 | 
	根据该配置,80%的请求会转发到服务service-account,20%的请求会转发到服务service-order
(3)在项目中添加代码
	在’service-account‘中添加代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | 
 
 
 
 @GetMapping("/weight")
 public Result weightTest() {
 log.info("com.qiuli.account.controller.GatewayTestController.weightTest");
 return Result.ok().message("Predicates Weight Test");
 }
 
 | 
	在’service-order‘中添加代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | 
 
 
 
 @GetMapping("/weight")
 public Result weightTest() {
 log.info("com.qiuli.order.controller.GatewayTestController.weightTest");
 return Result.ok().message("Predicates Weight Test");
 }
 
 | 
(4)在 pom.xml 中添加 Actuator 依赖
| 12
 3
 4
 
 | <dependency><groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-actuator</artifactId>
 </dependency>
 
 | 
(5)启用 Actuator 端点
	在 项目的yaml文件中配置 Actuator 端点
| 12
 3
 4
 5
 
 | management:endpoints:
 web:
 exposure:
 include: "*"
 
 | 
(6)重启服务后进行测试
	我们首先用postman测试接口是否正常

接口测试
可以看到接口是可以正常访问的;接下来我们使用JMeter发送批量请求,新建一个测试计划,添加线程组,设置10个线程,每个线程循环请求10次

测试计划1

测试计划2
然后我们用引入的Actuator组件来查看统计信息
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | # Actuator的使用方式# 访问 /actuator/metrics 查看所有指标。
 # 访问 /actuator/metrics/http.server.requests 查看 HTTP 请求的统计信息。
 # 使用 tag 参数过滤特定接口的流量
 # curl http://localhost:8080/actuator/metrics/http.server.requests?tag=uri:/api/test
 
 # 我们先查看’service-account‘服务的访问情况(端口号为8001),用浏览器访问如下链接
 http://localhost:8001/actuator/metrics/http.server.requests?tag=uri:/gatewayTest/weight
 # 查看’service-order‘服务的访问情况(端口号为8003),用浏览器访问如下链接
 http://localhost:8001/actuator/metrics/http.server.requests?tag=uri:/gatewayTest/weight
 
 | 

’service-account‘访问数据

’service-order‘访问数据
可以看到,服务’service-account‘有81次访问,服务’service-order‘有21次访问,符合我们在gateway配置文件中的设置
三、过滤功能
Gateway的过滤功能根据作用域划分为GatewayFilter(网关过滤器)和GlobalFilter(全局过滤器)两类,每类过滤器又分为系统内置的和自定义的两种。内置过滤器种类很多,这里不一一列举,仅举例说明,也不再测试。
1. 系统内置的全局过滤器
官方网址:https://docs.spring.io/spring-cloud-gateway/docs/2.2.6.RELEASE/reference/html/#global-filters

全局过滤器的种类
| 过滤器名称 | 默认顺序 | 作用 | 
| NettyWriteResponseFilter | -1 | 将后端服务的响应写回客户端。 | 
| RouteToRequestUrlFilter | 10000 | 将路由的 URI 转换为实际请求的 URL。 | 
| LoadBalancerClientFilter | 10100 | 使用负载均衡器选择后端服务实例。 | 
| ForwardRoutingFilter | 50000 | 将请求转发到指定的 URI。 | 
| NettyRoutingFilter | 2147483647 | 使用 Netty 客户端将请求转发到后端服务。 | 
全局过滤器的执行顺序由默认顺序决定,值越小,优先级越高。
官方说明:
| 12
 
 | GlobalFilter:全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,它为请求业务以及路由的URI转换为真实业务服务请求地址的核心过滤器,不需要配置系统初始化时加载,并作用在每个路由上。- 也就是说全局过滤器是默认生效的。
 
 | 
2. 自定义的全局过滤器
	自定义网关过滤器需要实现两个接口:GlobalFilter、Ordered
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 
 | @Slf4j@Component
 public class MyGlobalFilter implements GlobalFilter, Ordered {
 
 
 
 
 
 
 
 
 @Override
 public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
 
 ServerHttpRequest request = exchange.getRequest();
 
 
 log.info("Request Path: " + request.getPath());
 
 
 ServerHttpRequest modifiedRequest = request.mutate()
 .header("X-Custom-Header", "CustomValue")
 .build();
 
 
 return chain.filter(exchange.mutate().request(modifiedRequest).build());
 }
 
 
 
 
 
 
 @Override
 public int getOrder() {
 return 0;
 }
 }
 
 | 
3. 系统内置的网关过滤器
官方网址:https://docs.spring.io/spring-cloud-gateway/docs/2.2.6.RELEASE/reference/html/#gatewayfilter-factories
(1)RewritePath
	作用:重写请求路径,将客户端请求的路径重写为后端服务所需的路径,从而实现路径映射或路径转换的功能。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | filters:- RewritePath=<正则表达式>, <替换后的路径>
 
 
 spring:
 cloud:
 gateway:
 routes:
 - id: RewritePath-predicates-route
 uri: lb://service
 predicates:
 - Path=/api/**
 - RewritePath=/api/(?<segment>/?.*), /$\{segment}
 
 | 
	/api/(?<segment>.*) 表示匹配 /api/ 开头的路径,并将剩余部分捕获到 segment 组中,例如:/api/user会被重写为/user
(2)StripPrefix
	作用:去除请求路径中的指定数量的前缀部分,将剩余部分作为新的路径转发给后端服务
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | filters:- StripPrefix=<要去除的前缀部分数量>
 
 
 spring:
 cloud:
 gateway:
 routes:
 - id: StripPrefix-predicates-route
 uri: lb://service
 predicates:
 - Path=/api/**
 filters:
 - StripPrefix=1
 
 | 
	客户端请求 /api/user 会被去掉 /api 前缀(去除1级前缀),最终转发给后端服务的路径是 /user
(3)PrefixPath
	作用:在客户端请求的路径前添加指定的前缀,将新的路径转发给后端服务
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | filters:- PrefixPath=<要添加的前缀>
 
 
 spring:
 cloud:
 gateway:
 routes:
 - id: PrefixPath-predicates-route
 uri: lb://service
 predicates:
 - Path=/**
 filters:
 - PrefixPath=/api
 
 | 
	在所有请求前面加上/api再转发给后端服务,如/user变为/api/user
(4)SetPath
	作用:将客户端请求的路径替换为指定的路径,将新的路径转发给后端服务
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | filters:- SetPath=<替换后的路径>
 
 
 spring:
 cloud:
 gateway:
 routes:
 - id: SetPath-predicates-route
 uri: lb://service
 predicates:
 - Path=/user
 filters:
 - SetPath=/order
 
 | 
	将/user替换为/order
(5)SetStatus
	作用:设置 HTTP 响应的状态码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | filters:- SetStatus=<状态码>
 
 
 spring:
 cloud:
 gateway:
 routes:
 - id: SetPath-predicates-route
 uri: lb://service
 predicates:
 - Path=/user
 filters:
 - SetStatus=403
 
 | 
	访问/user的请求返回状态码403
(6)AddRequestParameter
	作用:向请求中添加指定的查询参数,将修改后的请求转发给后端服务
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | filters:- AddRequestParameter=<键>,<值>
 
 
 spring:
 cloud:
 gateway:
 routes:
 - id: AddRequestParameter-predicates-route
 uri: lb://service
 predicates:
 - Path=/user/{id}
 filters:
 - AddRequestParameter=userId,{id}
 
 | 
	为/user请求添加参数’userId={id}‘
	作用:向请求中添加指定的请求头,将修改后的请求转发给后端服务
	使用场景:
- 认证信息传递:当后端服务需要认证信息(如 JWT Token)时,可以使用 - AddRequestHeader添加这些信息。
 
- 自定义请求头:当后端服务需要某些自定义请求头时,可以使用 - AddRequestHeader添加这些请求头。
 
- 动态请求头生成:结合模板变量(如 - {segment}),可以根据请求动态生成请求头。
 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | 
 filters:
 - AddRequestHeader=<键>,<值>
 
 
 spring:
 cloud:
 gateway:
 routes:
 - id: AddRequestHeader-predicates-route
 uri: lb://service
 predicates:
 - Path=/user/{id}
 filters:
 - AddRequestHeader=X-user-id,{id}
 - AddRequestHeader=X-Version,v1
 
 | 
	向请求头中添加键值对’[X-user-id:{id}, X-Version:version ]‘
	作用:向响应中添加指定的响应头
	使用场景:
- 跨域支持:添加 `Access-Control-Allow-Origin` 等响应头以支持跨域请求
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | filters:- AddResponseHeader=<键>,<值>
 
 
 spring:
 cloud:
 gateway:
 routes:
 - id: AddRequestHeader-predicates-route
 uri: lb://service
 predicates:
 - Path=/user/{id}
 filters:
 - AddResponseHeader=X-user-id,{id}
 - AddResponseHeader=X-Version,version
 
 | 
	向响应头中添加键值对’[X-user-id:{id}, X-Version:version ]‘
4. 自定义的网关过滤器
(1)创建一个类并实现 GatewayFilterFactory 接口,重写 apply 方法,编写自定义逻辑
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 
 | @Slf4jpublic class MyGatewayFilter extends AbstractGatewayFilterFactory<MyGatewayFilter.Config> {
 @Override
 public GatewayFilter apply(Config config) {
 return (exchange, chain) -> {
 
 log.info("Custom Config Value: " + config.getValue());
 
 
 ServerHttpRequest modifiedRequest = exchange.getRequest().mutate()
 .header("X-Route-Filter", "Applied")
 .build();
 
 
 return chain.filter(exchange.mutate().request(modifiedRequest).build());
 };
 }
 
 public static class Config {
 private String value;
 
 public String getValue() {
 return value;
 }
 
 public void setValue(String value) {
 this.value = value;
 }
 }
 }
 
 | 
(2)在配置文件中为特定路由配置该过滤器
| 12
 3
 4
 5
 6
 7
 8
 
 | spring:cloud:
 gateway:
 routes:
 - id: custom_route
 uri: http://example.com
 filters:
 - CustomRouteFilter=CustomValue
 
 | 
四、处理跨域问题
	gateway中可以处理跨域问题,在yaml文件中添加配置
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | spring:cloud:
 gateway:
 globalcors:
 cors-configurations:
 '[/**]':
 
 allowed-origins: "*"
 
 allowed-methods: GET, POST, PUT, DELETE
 
 allowed-headers: "*"
 
 max-age: 3600
 
 | 
五、整合sentinel实现限流及降级
由于篇幅问题,这部分内容我放在别的文章中。
六、实现统一鉴权
关于网关访问时必须要统一验证请求是否有效时,有很多种办法,我这里给出SpringBoot+Spring Security+JWT实现单点登录的解决思路来实现网关统一验证。由于篇幅问题,这部分内容我放在别的文章中。