一,过滤器
Spring Cloud Gateway除了具备请求路由功能之外,也支持对请求的过滤。与Zuul网关类似,也是通过过滤器的形式来实现的。那么接下来我们一起来研究一下Gateway中的过滤器
1.1 过滤器基础
1.1.1 过滤器的生命周期
Spring Cloud Gateway 的 Filter 的生命周期不像 Zuul 的那么丰富,它只有两个:“pre” 和 “post”。
- PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择 请求的微服务、记录调试信息等。
- POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
1.1.2 过滤器类型
Spring Cloud Gateway 的 Filter 从作用范围可分为另外两种GatewayFilter 与 GlobalFilter。
- GatewayFilter:应用到单个路由或者一个分组的路由上。
- GlobalFilter:应用到所有的路由上。
1.2 局部过滤器
局部过滤器(GatewayFilter),是针对单个路由的过滤器。可以对访问的URL过滤,进行切面处理。在 Spring Cloud Gateway中通过GatewayFilter的形式内置了很多不同类型的局部过滤器。这里简单将 Spring Cloud Gateway内置的所有过滤器工厂整理成了一张表格,虽然不是很详细,但能作为速览使 用。如下:
每个过滤器工厂都对应一个实现类,并且这些类的名称必须以 GatewayFilterFactory 结尾,这是 Spring Cloud Gateway的一个约定,如果想看这些过滤器的源码,例如 AddRequestHeader 对应的实现类为 AddRequestHeaderGatewayFilterFactory 。可以直接在idea 上面搜索AddRequestHeaderGatewayFilterFactory ,对于这些过滤器的使用方式可以参考官方文档
就可以看到过滤器的源码。
1.3 全局过滤器
全局过滤器(GlobalFilter)作用于所有路由,Spring Cloud Gateway 定义了GlobalFilter接口,用户 可以自定义实现自己的Global Filter。通过全局过滤器可以实现对权限的统一校验,安全性验证等功 能,并且全局过滤器也是程序员使用比较多的过滤器。
.Spring Cloud Gateway内部也是通过一系列的内置全局过滤器对整个路由转发进行处理如下:
我们要定义一个全局过滤器只需要实现GlobalFilter 这个接口
下面我们做个例子
1.3.1 创建一个类,实现GlobalFilter 接口
public class LoginFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("触发了全局过滤器!");
return null;
}
@Override
public int getOrder() {
return 0;
}
}
并实现GlobalFilter接口里的方法。然后随便在filter 方法里写一个打印,然后我们请求网关服务,只要在日志里看到这个打印,说明全局过滤器就定义成功!
定义的这个全局过滤器一定要配置@Component
1.3.2 重启网关服务,并请求网关路径
触发了我们自定义的全局过滤器,但是报了一个空指针。因为实现的这个filter 方法返回值是null ,
1.3.3 定义filter 方法的返回值
/**
* 自定义一个全局过滤器
* 实现globalfilter,ordered接口
*/
@Component
public class LoginFilter implements GlobalFilter, Ordered {
/**
* 执行过滤器中的过滤逻辑
* @param exchange
* @param chain
* @return
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("触发了全局过滤器!");
return chain.filter(exchange);
}
/**
* 指定过滤器执行顺序,返回值越小,执行优先级越高
* @return
*/
@Override
public int getOrder() {
return 0;
}
}
重启网关服务, 就不报错了