一 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"zuul") (prefix =
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);
}