Zuul 过滤器:请求生命周期的全方位管控
Zuul 的核心能力源于其灵活的过滤器机制,通过在请求处理的不同阶段插入自定义逻辑,实现对请求的路由、校验、监控等全方位管控。Zuul 将过滤器分为四类,分别对应请求生命周期的不同阶段,共同构成了网关的核心扩展点。
Zuul 过滤器的四种类型
Zuul 过滤器按执行时机可分为pre、route、post、error四类,覆盖了请求从进入网关到返回响应的全流程:
| 过滤器类型 |
执行阶段 |
典型应用场景 |
| pre |
请求被路由到微服务之前执行 |
身份认证(如 Token 校验)、参数校验、限流、请求转发、设置上下文变量等。 |
| route |
请求被路由到微服务过程中执行 |
处理请求转发逻辑(如选择具体服务实例、修改请求参数 / 头信息、适配不同协议)。 |
| post |
请求被微服务处理之后执行 |
统一添加响应头、收集监控指标(如响应时间)、日志记录、结果二次处理等。 |
| error |
上述任一阶段发生异常时执行 |
统一错误处理(如转换异常为标准响应格式)、记录错误日志、触发降级等。 |
过滤器的执行流程
Zuul 过滤器的执行顺序由filterOrder()(数值越小越先执行)和类型共同决定,核心流程如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public void doFilter(...) { try { preRouting(); if (sendZuulResponse) { routing(); } postRouting(); } catch (ZuulException e) { error(e); } }
|
- 异常处理:无论 pre、route、post 阶段抛出异常,都会触发 error 过滤器,执行后若未解决异常,最终仍会进入 post 阶段(确保响应正常返回)。
自定义 Zuul 过滤器
自定义过滤器需继承ZuulFilter抽象类,实现四个核心方法。以下通过实例说明不同类型过滤器的实现。
1. 自定义 pre 过滤器(身份认证)
功能:请求路由前校验 Token,无 Token 或 Token 无效则拦截请求。
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 43
| @Component public class AuthPreFilter extends ZuulFilter {
@Override public String filterType() { return "pre"; }
@Override public int filterOrder() { return 1; }
@Override public boolean shouldFilter() { return true; }
@Override public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest();
String token = request.getHeader("Authorization"); if (token == null || !token.startsWith("Bearer ")) { ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value()); ctx.setResponseBody("Missing or invalid token"); ctx.getResponse().setContentType("application/json"); } return null; } }
|
2. 自定义 post 过滤器(响应处理)
功能:微服务返回响应后,统一添加响应头(如X-Gateway-Version)。
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
| @Component public class ResponsePostFilter extends ZuulFilter {
@Override public String filterType() { return "post"; }
@Override public int filterOrder() { return 1; }
@Override public boolean shouldFilter() { return true; }
@Override public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletResponse response = ctx.getResponse(); response.addHeader("X-Gateway-Version", "1.0.0"); return null; } }
|
3. 自定义 error 过滤器(统一错误处理)
功能:捕获异常并返回标准化错误响应。
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
| @Component public class ErrorFilter extends ZuulFilter {
@Override public String filterType() { return "error"; }
@Override public int filterOrder() { return 1; }
@Override public boolean shouldFilter() { return RequestContext.getCurrentContext().containsKey("error.exception"); }
@Override public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); Throwable exception = (Throwable) ctx.get("error.exception");
String errorMsg = exception.getMessage() != null ? exception.getMessage() : "Unknown error"; int statusCode = HttpStatus.INTERNAL_SERVER_ERROR.value();
if (exception instanceof BusinessException) { statusCode = ((BusinessException) exception).getCode(); }
ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(statusCode); ctx.setResponseBody("{\"code\":" + statusCode + ",\"message\":\"" + errorMsg + "\"}"); ctx.getResponse().setContentType("application/json"); return null; } }
|
过滤器的核心组件:RequestContext
RequestContext是 Zuul 过滤器间传递数据的核心容器,本质是一个ThreadLocal变量,存储了请求 / 响应的上下文信息,主要方法包括:
| 方法 |
作用 |
setSendZuulResponse(boolean) |
设置是否转发请求到微服务(false表示拦截)。 |
setResponseStatusCode(int) |
设置响应状态码(如 401、500)。 |
setResponseBody(String) |
设置响应体内容。 |
getResponse() |
获取HttpServletResponse对象,用于操作响应头、编码等。 |
getRequest() |
获取HttpServletRequest对象,用于获取请求参数、头信息等。 |
put(String key, Object value) |
存储自定义变量(供其他过滤器使用)。 |
禁用默认过滤器
Zuul 默认启用了一些内置过滤器(如ServletDetectionFilter、FormBodyWrapperFilter),若需禁用某过滤器,可在配置文件中设置:
1 2 3 4 5 6 7 8
| zuul: ServletDetectionFilter: pre: disable: true FormBodyWrapperFilter: pre: disable: true
|
- 内置过滤器类名可在
org.springframework.cloud.netflix.zuul.filters包中查看。
过滤器的注意事项
- 线程安全:
RequestContext基于ThreadLocal,过滤器逻辑需保证线程安全;
- 性能影响:过滤器执行时间会累加在请求响应时间中,避免复杂逻辑(如耗时数据库操作);
- 执行顺序:通过
filterOrder()控制同一类型过滤器的执行顺序,建议按功能分组(如认证过滤器 order=1,限流过滤器 order=2);
- 异常处理:
run()方法抛出的异常会触发 error 过滤器,需确保异常信息可被正确解析。
总结
Zuul 过滤器通过 pre、route、post、error 四种类型,实现了对请求全生命周期的干预,是网关实现身份认证、限流、监控等功能的核心机制。自定义过滤器时,需明确其类型和执行顺序,通过RequestContext传递上下文信息,并注意性能和线程安全
v1.3.10