从专栏的第二十四篇博客可以知道,请求被路由到微服务之前以及微服务响应请求回网关之前,都会经过一连串的过滤器。
过滤器的主要作用就是在请求的传递过程中,对请求和响应做一些手脚。
在Gateway中, Filter的生命周期只有两个,PRE 和 POST,PRE这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。 POST这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
过滤器分为局部过滤器(GatewayFilter) 和全局过滤器(GlobalFilter) ,GatewayFilter主要是应用到单个路由或者一个分组的路由上,而GlobalFilter则是应用到所有的路由上 。
在SpringCloud Gateway中也内置了很多不同类型的网关路由过滤器,一般情况下,内置的网关路由过滤器基本能够满足开发需求,不过如果想要自定义网关路由过滤器,也是可以的。和上篇博客思路一样,找到一个内置的网关路由过滤器,如RewritePathGatewayFilterFactory,查看它的源码,然后可以得出自定义网关路由过滤器,需要满足的2个前提条件,一是自定义网关路由过滤器的名字必须是配置+GatewayFilterFactory,二是自定义网关路由过滤器类必须继承AbstractGatewayFilterFactory<配置类>。接下来要实现一个能够根据配置,来选择开启缓存日志或者是控制台日志的过滤器。
新建一个过滤器类LogGatewayFilterFactory,信息如下:
package com.example.apigateway.filters;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
//自定义局部过滤器
@Component
public class LogGatewayFilterFactory
extends AbstractGatewayFilterFactory<LogGatewayFilterFactory.Config> {
//构造函数
public LogGatewayFilterFactory() {
super(Config.class);
}
/**
* 读取配置文件中的参数,赋值到配置类中
* @return
*/
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("consoleLog", "cacheLog");
}
/**
* 过滤器逻辑
* @param config
* @return
*/
@Override
public GatewayFilter apply(Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (config.isConsoleLog()) {
System.out.println("consoleLog已经开启了....");
}
if (config.isCacheLog()) {
System.out.println("cacheLog已经开启了....");
}
return chain.filter(exchange);
}
};
}
/**
* 配置类,接收配置参数
*/
public static class Config {
private boolean consoleLog;
private boolean cacheLog;
public boolean isConsoleLog() {
return consoleLog;
}
public void setConsoleLog(boolean consoleLog) {
this.consoleLog = consoleLog;
}
public boolean isCacheLog() {
return cacheLog;
}
public void setCacheLog(boolean cacheLog) {
this.cacheLog = cacheLog;
}
}
}
在order_route路由加上log的网关过滤器配置,如下:
表示开启consoleLog,不开启cacheLog。浏览器访问http://localhost:8888/api/order/message1,结果如下:
说明局部过滤器定义成功,接下里就是尝试定义全局过滤器了。