在 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 地址,效果如下图:
通过上图可知,错误类型的过滤器生效了。
点击下载/查看本教程相关资料或者源代码。