一 Zuul过滤器了解
首先,我们需要了解Zuul的过滤器分类,之后才能判断我们需要为业务需要定制的过滤器选定对应的类型,Zuul过滤器主要分为以下几类:
pre过滤器:ServletDetectionFilter:检测请求是否通过Spring Dispatcher。使用FilterConstants.IS_DISPATCHER_SERVLET_REQUEST_KEY的键设置布尔值。FormBodyWrapperFilter:解析表单数据并为下游请求重新编码。DebugFilter:如果设置了debug请求参数,则将RequestContext.setDebugRouting()和RequestContext.setDebugReques()设置为true。PreDecorationFilter:根据提供的RouteLocator确定需要路由到哪里。它还为下游请求设置了各种与代理相关的标头。(@EnableZuulProxy专属会初始化的spring bean)
post过滤器:SendResponseFilter:将代理请求的响应写入当前响应。
route过滤器:SendForwardFilter:使用Servlet RequestDispatcher转发请求。转发位置存储在RequestContext属性FilterConstants.FORWARD_TO_KEY中。这对于转发到当前应用程序中的端点很有用。
error过滤器:SendErrorFilter:如果RequestContext.getThrowable()不为null,则转发到/error(默认情况下)。您可以通过设置error.path属性来更改默认转发路径(/error)。RibbonRoutingFilter:使用Ribbon,Hystrix和可插拔HTTP客户端发送请求。服务ID在RequestContext属性FilterConstants.SERVICE_ID_KEY中找到。此过滤器可以使用不同的HTTP客户端。(@EnableZuulProxy专属会初始化的spring bean)- Apache HttpClient:默认客户端。
- Squareup OkHttpClient v3:通过在类路径上具有
com.squareup.okhttp3:okhttp库并设置ribbon.okhttp.enabled=true来启用。 - Netflix Ribbon HTTP客户端:通过设置
ribbon.restclient.enabled=true启用。该客户端具有局限性,包括不支持PATCH方法,但是还具有内置的重试功能。
SimpleHostRoutingFilter:通过Apache HttpClient将请求发送到预定的URL。 URL可在RequestContext.getRouteHost()中找到。(@EnableZuulProxy专属会初始化的spring bean)
二 如何自定义过滤器
通过对系统已有的过滤器及其分类的了解,下面我们看看如何自定义过滤器。
我们需要继承
ZuulFilter抽象类,并重写以下四个方法: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/**
* 指定过滤器类型
*/
public String filterType() {
return FilterConstants.ROUTE_TYPE;
}
/**
* 指定过滤器次序
*/
public int filterOrder() {
// after PreDecorationFilter
return FilterConstants.PRE_DECORATION_FILTER_ORDER;
}
/**
* 用于判断过滤器是否需要执行
*/
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
// TODO 根据ctx 获取的信息去判断 或者 通过 ProxyRequestHelper 来判断 如下
// proxyRequestHelper 通过@Autowired注入 或者 构造传入
if (proxyRequestHelper.isIncludedHeader("XXXHeader")) {
// 判断有 XXXHeader 请求头
}
}
public Object run() {
// TODO 具体过滤器需要执行的逻辑
}如果zuul网关自定义的过滤器仅想对某些路由生效,如果去配置?
可以在zuul网关下扩展多一个属性,如下:
1
2
3
4
5
6
7
8zuul:
routes:
business-api:
path: /business/** # 路由路径
customSensitiveHeaders: true # 是否去除敏感头 true为去除
sensitiveHeaders: Cookie,Set-Cookie # 需要去除的敏感头 去除了 即不会往下游转发
url: http://localhost:9999/api # 需要转发的url
customerParam: true # 用户自定义的扩展属性再通过扩展ZuulProperties读取到该属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17(prefix = "zuul")
public class CustomZuulProperties {
private Map<String, CustomZuulRoute> routes = new LinkedHashMap<>();
public static class CustomZuulRoute extends ZuulProperties.ZuulRoute {
private Boolean customerParam;
}
}再通过重写
shouldFilter()方法判断是否使用该过滤器1
2
3
4
5
6
7
8public boolean shouldFilter() {
Route route = routeLocator.getMatchingRoute(
RequestContext.getCurrentContext()
.getRequest()
.getRequestURI());
Boolean customerFlag = customZuulProperties.getRoutes().get(route.getId()).getCustomerParam();
return BooleanUtils.isTrue(customerFlag);
}
