GateWay之Filter相关
# GateWay之Filter相关
# 过滤器概念与相关资料
# 概念
SpringMVC里面的的拦截器Interceptor,Servlet的过滤器
“pre”和 “post” 分别会在请求被执行前调用和被执行后调用,用来修改请求和响应信息
# 作用
Spring Cloud Gateway 中的过滤器(Filter)是其核心功能之一,用于在请求转发前后对请求和响应进行处理。过滤器可以用来实现各种功能,如请求头和响应头的修改、请求日志记录、限流、熔断、重试等。
它的作用是对进入网关的请求和微服务返回的响应做处理。注意了,它不仅仅会对请求,还会对微服务返回的响应做处理。
# 请求过程
我们已经知道的是,请求进入网关一定要先做路由,我们会有一个断言工厂,它可以基于我们配置的规则完成请求路由,去判断一下到底应该去哪个微服务。
但是路由之后是不是立即就可以向微服务发出请求了呢?
不是这样子的,因为在网关里面我们还可以给我们的路由配置各种各样的过滤器
,这个过滤器会形成一个过滤器链,你的请求一定要经过这些过滤器链,然后才能到达微服务。
# 资料
Spring Cloud Gateway-filter (opens new window)
- https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories
GateWay-单一过滤器使用讲解-官网 (opens new window)
- https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories
# 快速上手
# 过滤器类型
GateWay提供了三种不同类型的过滤器:
全局过滤器:gateway出厂默认已有的,直接用即可,主要作用于所有的路由
不需要在配置文件中配置,作用在所有的路由上,实现GlobalFilter接口即可
单一过滤器:也可以称为网关过滤器,这种过滤器主要是作用于单一路由或者某个路由分组
自定义过滤器:就是单一过滤器提供的功能无法满足你,开发者自行实现的过滤器
下面主要介绍的就是单一过滤器。但因为单一过滤器有很多,因此主要介绍其中几个,其余的还请各位开发者朋友们,到官网自行查阅文档。
- https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories
# 单一过滤器示例
# AddRequestHeader
对应配置如下:
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
filters:
- AddRequestHeader=X-Request-red, blue
2
3
4
5
6
7
8
9
这样一来,对应请求一来,请求头中就会带上X-Request-red, 且值为blue。
This listing adds
X-Request-red:blue
header to the downstream request’s headers for all matching requests.
AddRequestHeader
is aware of the URI variables used to match a path or host. URI variables may be used in the value and are expanded at runtime.
# RemoveRequestHeader
作用:删除请求头中的信息
- id: pay_routh3 #pay_routh3
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/pay/gateway/filter/** # 断言,路径相匹配的进行路由
filters:
- AddRequestHeader=X-Request-atguigu1,atguiguValue1 # 请求头kv,若一头含有多参则重写一行设置
- RemoveRequestHeader=sec-fetch-site # 删除请求头sec-fetch-sit
2
3
4
5
6
7
# SetRequestHeader
当然,还有修改请求头,SetRequestHeader
filters:
- AddRequestHeader=X-Request-atguigu1,atguiguValue1 # 请求头kv,若一头含有多参则重写一行设置
- AddRequestHeader=X-Request-atguigu2,atguiguValue2
- RemoveRequestHeader=sec-fetch-site # 删除请求头sec-fetch-site
- SetRequestHeader=sec-fetch-mode, Blue-updatebyzzyy # 将请求头sec-fetch-mode对应的值修改为Blue-updatebyzzyy
2
3
4
5
# Other
除了有Request的,还有相应的,比如:ResponseHeader
filters:
- AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
- RemoveRequestParameter=customerName # 删除url请求参数customerName,你传递过来也是null
- AddResponseHeader=X-Response-atguigu, BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
2
3
4
5
上述是添加影响的。
还有设置响应的:
- AddResponseHeader=X-Response-atguigu, BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
- SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
2
RemoveResponseHeader GatewayFilter Factory
- RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除
还有增加前缀的,PrefixPath GatewayFilter Factory
predicates:
#- Path=/pay/gateway/filter/** # 被分拆为: PrefixPath + Path
- Path=/gateway/filter/** # 断言,为配合PrefixPath测试过滤,暂时注释掉/pay
filters:
- AddRequestHeader=X-Request-atguigu1,atguiguValue1 #请求头kv,若一头含有多参则重写一行设置
- PrefixPath=/pay # http://localhost:9527/pay/gateway/filter
2
3
4
5
6
7
8
这样后,它映射的地址就是 path+prefixPath
也就是:/pay/gateway/filter/**
....还有很多,请到官网查看
# 全局过滤器-配置文件
default-filters
假设你有多个服务,并希望通过网关对它们进行访问,同时希望对所有请求和响应都添加一些公共的头部信息。你的 application.yml
可能看起来像这样:
spring:
cloud:
gateway:
routes:
- id: service1_route
uri: http://localhost:8081
predicates:
- Path=/service1/**
- id: service2_route
uri: http://localhost:8082
predicates:
- Path=/service2/**
default-filters:
- AddRequestHeader=Global-Request-Header, Global-Request-Value
- AddResponseHeader=Global-Response-Header, Global-Response-Value
2
3
4
5
6
7
8
9
10
11
12
13
14
15
在此配置下,任何发送到 /service1/**
或 /service2/**
的请求都将自动包含 Global-Request-Header: Global-Request-Value
请求头,并且所有从这些服务返回的响应都将包含 Global-Response-Header: Global-Response-Value
响应头。
注意事项
- 优先级:
default-filters
是应用于所有路由的过滤器集合,但如果你在特定路由中定义了相同的过滤器,那么特定路由中的配置将覆盖default-filters
中的配置。 - 灵活性:虽然
default-filters
提供了一种快速简便的方式来为所有路由添加过滤器,但在处理更复杂的需求时,可能还需要结合自定义全局过滤器或针对具体路由的过滤器配置。
# 自定义全局过滤器
已经有了default-filters
,为什么还需要全局过滤器,因为前置无法处理复杂的逻辑。当然全局过滤器,GateWay也有一些内置的,这里就不展开介绍了。
除了使用内置的全局过滤器外,你还可以创建自己的全局过滤器来满足特定需求。要创建自定义的全局过滤器,你需要实现org.springframework.cloud.gateway.filter.GlobalFilter
接口,并且通常还需要实现org.springframework.core.Ordered
接口来指定过滤器的执行顺序。
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class AuthorizationGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 获取请求中的参数
String authParam = exchange.getRequest().getQueryParams().getFirst("authorization");
// 判断参数是否存在以及是否等于'demand'
if ("demand".equals(authParam)) {
// 放行请求
return chain.filter(exchange);
} else {
// 拦截请求并返回403 Forbidden状态码
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
return exchange.getResponse().setComplete();
}
}
@Override
public int getOrder() {
// 设置过滤器执行顺序,数值越小优先级越高
return 0;
}
}
2
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
以下是对该接口的介绍:
# GlobalFilter
GlobalFilter
接口。这个接口中只有一个方法就叫filter,顾名思义过滤。
而这个方法当中有两个参数,一个参数叫exchange,代表的是请求上下文。这个上下文指的是从你请求进入网关开始,一直到结束为止,整个流程中都可以共享exchange对象。那这个对象里边,你可以拿到请求相关的信息,响应相关的信息,甚至于你也可以往里边存个东西,取个东西都没问题。
第二个参数chain就是过滤器链。这个链条上除了你这个过滤器以外,还有别的过滤器,那它的作用就是放行,什么意思呢?你调用这个过滤器链让它往后走,等于你这里逻辑就处理完了,交给别人处理了。
因此这两个参数,第一个参数的作用是来让我们编写整个过滤器的业务逻辑的,你需要的信息这里面都有。而第二个参数是让我们放行来用的,交给下一个过滤器去处理好。
那处理完了以后,它有一个返回值。这个返回值大家比较陌生,它叫mono,是我们web flux里边的一个API。这个东西你没有见过不要紧
通过实现 GlobalFilter
和 Ordered
接口,并使用 @Component
注解将该类声明为Spring管理的组件,你的自定义过滤器将会自动被Spring Cloud Gateway应用到所有的路由上。
# 过滤器执行顺序
排序先看order值,值越小优先级越高值
一样是defauts优先,然后是局部的路由过滤器,最后是全局的global filter过滤器
配置类中的值,按照从上往下,值从1开始,依次累加
# 跨域问题解决
你也可以直接在配置类中配置 CORS,这种方式更加简洁且易于管理:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
// 设置允许的源、方法和头部信息
config.setAllowCredentials(true);
config.addAllowedOrigin("http://localhost:8080"); // 根据需要调整为具体的前端地址
config.addAllowedHeader("*");
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config); // 应用于所有路径
return new CorsWebFilter(source);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25