在 Netflix Zuul 1.x 中,错误过滤器专门用于捕获和处理在请求处理过程中出现的异常。无论是在其他过滤器(如前置、路由或后置过滤器)中抛出的异常,还是目标微服务返回的错误响应,错误过滤器都可以拦截并进行统一的处理。
首先,需要创建一个继承 com.netflix.zuul.ZuulFilter 抽象类的错误过滤器类。代码如下:
package com.hxstrive.hystrix_demo.filter;
import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
/**
* 错误处理过滤器
* @author hxstrive.com
*/
@Component
public class ErrorHandlingFilter extends ZuulFilter {
private static final Logger LOG = LoggerFactory.getLogger(ErrorHandlingFilter.class);
@Override
public String filterType() {
return "error";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
Throwable throwable = ctx.getThrowable();
if (throwable!= null) {
try {
LOG.error("An error occurred during request processing", throwable);
HttpServletResponse response = ctx.getResponse();
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.setContentType("application/json;charset=UTF-8");
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", 500);
jsonObject.put("message", "发生内部错误,请稍后再试。");
PrintWriter writer = response.getWriter();
writer.print(jsonObject.toJSONString());
writer.flush();
writer.close();
} catch (Exception e) {
LOG.error("Error writing response", e);
}
}
return null;
}
}在上述代码中,filterType 方法返回 error,表明这是一个错误过滤器。filterOrder 方法设置其执行顺序为 0,确保它能尽早地处理异常。shouldRun方法返回true,表示这个过滤器会执行。在 run 方法中,首先获取请求上下文(RequestContext)中的异常对象(Throwable),如果存在异常,就记录详细的错误日志,然后设置响应状态码为 500(表示内部服务器错误),设置自定义的响应内容和响应头。
修改 CustomFilter 过滤器的 run 方法,在该方法中添加“如果存在 error 参数,则抛出 RuntimeExcetion 异常”的逻辑,代码如下:
@Component
public class CustomFilter extends ZuulFilter {
//...
// 过滤器执行逻辑
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
// 在这里可以进行请求验证等前置操作
System.out.println("CustomPreFilter: " + request.getMethod() + " " + request.getRequestURL());
// 模拟异常,如果存在 error 参数且不为空,则跑出异常
String error = request.getParameter("error");
if(StringUtils.hasText(error)) {
throw new RuntimeException(error);
}
return null;
}
}启动 Zuul 示例应用,通过浏览器访问 http://localhost:9000/api/order/order/1?error=Error%20Message 地址,效果如下图:

通过上图可知,错误类型的过滤器生效了。
点击下载/查看本教程相关资料或者源代码。