1. 序言

基本上gateway自带的过滤器都能满足我们的使用,除了使用自带的,我们也可以自定义过滤器实现自己的逻辑

2. 工程搭建

基本步骤不变,只是在配置环节有不一样

3. 全局过滤器

全局过滤器只需要实现GlobalFilter即可,所有的请求都会走此过滤器,用于做全局的事件处理,如权限验证、日志记录、租户校验等……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

@Component
public class LogGlobalFilter implements GlobalFilter {
private static final Logger logger = LoggerFactory.getLogger(RuntimeException.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
StopWatch watch = new StopWatch();
watch.start();
try {
return chain.filter(exchange);
} catch (RuntimeException e) {
logger.error("过滤器中发生异常:"+e.getMessage(),e);
throw e;
} finally {
watch.stop();
logger.info("任务执行时间:"+watch.prettyPrint());
}
}
}

只要LogGlobalFilter加入容器扫描到即可,框架会自行扫描GlobalFilter对应的类,然后加入全局过滤器中

4. 局部过滤器

局部过滤器在局部请求中使用,因此需要有创建和配置两个过程

4.1. 创建

创建一个过滤器继承AbstractGatewayFilterFactory,也可以实现GatewayFilterFactory,但一般通过继承AbstractGatewayFilterFactory来处理会方便很多。

1
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
34
35
36
37
38
39
40
41
42
@Component
@Slf4j
public class ProviderServiceGatewayFilterFactory extends AbstractGatewayFilterFactory<ProviderServiceGatewayFilterFactory.ProviderConfig> {
/**
* 构造器中将泛型的class传入,泛型即为配置类
*/
public ProviderServiceGatewayFilterFactory() {
super(ProviderConfig.class);
}
@Override
public GatewayFilter apply(ProviderConfig config) {

log.info("ProviderServiceGatewayFilterFactory apply");

if (config.postLogger){
log.info("postLogger enable");
}
if (config.preLogger){
log.info("preLogger enable");
}
//这里如果有配置的话要保证每次创建的不一样,因为每个路径配置此传参都可能不一样
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("ProviderServiceGatewayFilterFactory inner filter");
return chain.filter(exchange);
}
};
}
/**
* 配置类,在配置文件配置的时候会参照对应并填入值
* 如: filters:
* - ProviderService=message1,true,true
* 其中,参数位置就对应属性的位置
*/
@Data
public static class ProviderConfig {
private String message;
private boolean preLogger;
private boolean postLogger;
}
}

注意,过滤器工厂命名的时候一定要以GatewayFilterFactory结尾命名,这是约定大于配置的体现,实现了此则才能使用filters中的如下配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
routes:
- id: header_route # 按照请求头正则匹配
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
filters:
- ProviderService=message1,true,true
# 或者全写形式
- name: ProviderService
args:
message: message1
preLogger: true
postLogger: true