一、GateWay概述
- Gateway是在spring生态系统之上构建的API网关服务,基于Spring5,SpringBoot2和Project Reactor等技术。Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能,例如:熔断、限流、重试等
- SpringCloud Gateway是SpringCloud的一个全新项目,基于Spring5.X+SpringBoot2.X和Project Reactor等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式。
- 为了提升网关的性能,SpringCloud Gatway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通讯框架Netty。
- SpringCloud Gateway的目标提供统一的路由方式且基于Filter链的方式提供了网关基本的功能,例如:安全、监控/指标、和限流。
二、三大核心组件
- 使用gateway引入以下坐标
xml
<!--网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 负载均衡组件 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
1、Route(路由)
路由是构建网关的基本模块,它由ID,目标URI,一系列的断言(匹配规则)和过滤器组成,如果断言为true则匹配该路由
2、 Predicate(断言)
参考的是java8的java.util.function.Predicate开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
入门使用,新建Geteway模块, 引入坐标,配置yml文件
yaml
server:
port: 网关的端口号 # 再访问服务就使用 网关的端口+url ,而不使用之前的服务的端口
spring:
application:
name: spzx-cloud-gateway # 启动后Nacos注册中心服务会显示这个名字
cloud:
nacos:
discovery:
server-addr: 你nacos服务器的ip:端口
gateway:
discovery:
locator:
enabled: true #网关和注册中心整合
# 配置route , id, target , predicate
routes:
- id: spring-cloud-user # 随意见名知意,唯一
uri: lb://spzx-cloud-user # nacos中注册中心,服务的id lb表示loadBalancer
# 配置路由
predicates:
- Path=/*/user/** # user 前面一个深度, user后面可以任意深度
# 访问网关最先匹配的就是断言规则, 这里写path就是看看路径匹配不匹配
#- #http://127.0.0.1:10100/api/user/selectByUserId/1
在这里插入图片描述

- 直接访问服务
- 通过网管访问服务
- 就举这个一个例子,更多在🔗官网predicates
3、 Filter(过滤)
Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改在gateway中要实现其他的功能:权限控制、流量监控、统一日志处理等。就需要使用到gateway中所提供的过滤器了。过滤器,可以对进入网关的请求和微服务返回的响应做处理:
pring gateway提供了31种不同的过滤器。、
官网地址:🔗直达链接
路由过滤器(内置, 单个)
举例
- AddRequestHeader给当前请求添加一个请求头
yml
routes:
- id: spring-cloud-user
uri: lb://spzx-cloud-user
predicates:
- Path=/*/user/**
filters:
#添加过滤器,
- AddRequestHeader= key,abcdefg# 增加一个请求头,和值

默认过滤器(内置,全局)
- 关键字 default-filters
yaml
routes:
- id: spring-cloud-user
uri: lb://spzx-cloud-user
predicates:
- Path=/*/user/**
filters:
- AddRequestHeader= key,abcdefg
# 和routes平级
default-filters: # 使用方法一样, 全局生效
- AddRequestHeader= key,chen
- 全局和局部都配置了, 并不会产生覆盖, 而是都要
全局过滤器GlobalFilter(用户自定义,全局)
-
概述
上述的过滤器是gateway中提供的默认的过滤器,每一个过滤器的功能都是固定的。但是如果我们希望拦截请求,做自己的业务逻辑,默认的过滤器就没办法实现。此时就需求使用全局过滤器,全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。区别在于GatewayFilter通过配置定义,处理逻辑是固定的;而GlobalFilter的逻辑需要自己写代码实现。
-
案例:定义全局过滤器,拦截请求,判断请求的参数是否满足下面条件:
请求参数中是否有username,如果同时满足则放行,否则拦截 -
步骤分析:
1、定义一个类实现GlobalFilter接口
2、重写filter方法
3、将该类纳入到spring容器中
4、实现Ordered接口定义该过滤器的顺序
java
@Component
public class AuthorizationFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String username = request.getQueryParams().getFirst("username");
//request.getQueryParams() 返回当前请求的查询参数(Query Parameters),
// 它是一个 MultiValueMap<String, String>,表示多个键值对,允许某个键有多个值。
//.getFirst("username") 表示从查询参数中获取第一个名为 "username" 的参数的值。
// getFirst 方法返回该参数的第一个值(如果存在),如果查询参数中没有该字段,则返回 null。
System.out.println(username);
if(StringUtils.isEmpty(username)){
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED); //HttpStatus 是Spring提供的 UNAUTHORIZED 401
return response.setComplete();
// setComplete() 返回一个 Mono<Void> 对象(Mono 是一种表示异步操作的类型),
// 它表示一个完成的异步操作。
}
//放行
return chain.filter(exchange);
}
/**
* 设置过滤器的优先级
* @return
*/
@Override
public int getOrder() {
return 1;
}
}
1.6.6 过滤器执行顺序
请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter
请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器:
排序的规则
1、按照order的值进行排序,order的值越小,优先级越高,执行顺序越靠前。
2、路由过滤器和默认过滤器会按照order的值进行排序,这个值由spring进行指定,默认是按照声明顺序从1递增
3、当过滤器的order值一样时,会按照 globalFilter > defaultFilter > 路由过滤器的顺序执行
