API网关服务组件Spring Cloud Zuul使用详解10(过滤器详解2:异常处理)
作者:hangge | 2020-10-23 08:10
十二、异常处理
1,自定义 Error 过滤器
(1)Zuul 过滤器(链)生命周期的任何部分发生异常,都会执行 Error 过滤器。下面我们自定义一个简单的 Error 过滤器:
@Component
public class ErrorFilter extends ZuulFilter {
private Logger logger = LoggerFactory.getLogger(ErrorFilter.class);
@Override
public String filterType() {
return FilterConstants.ERROR_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.SEND_ERROR_FILTER_ORDER + 100;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
Throwable throwable = ctx.getThrowable();
logger.error("Filter Error:{}",throwable.getCause().getMessage());
return null;
}
}
(2)接着定义一个 pre 类型的过滤器测试一下,我们在该过滤器的 run 方法中抛出一个异常。
@Component
public class AccessFilter extends ZuulFilter {
private static Logger log = LoggerFactory.getLogger(AccessFilter.class);
@Override
public String filterType() {
// 前置过滤器
return "pre";
}
@Override
public int filterOrder() {
// 优先级,数字越大,优先级越低
return 0;
}
@Override
public boolean shouldFilter() {
//是否执行该过滤器,true代表需要过滤
return true;
}
@Override
public Object run() {
doSomething();
return null;
}
private void doSomething() {
throw new RuntimeException("一个未知的错误...");
}
}
(3)启动网关,随便访问一个路由接口都会显示错误,同时查看控制台可以看到这个 error 过滤器也成功调用了:

2,自定义 error 错误页面、错误信息
(1)Zuul 默认的异常处理是:Zuul 自己不处理,交给 Spring Boot 处理。
(1)默认情况下,如果通过 rest 方式访问一个路由,当发生异常时,会返回类似如下信息(以上面抛出 RuntimeException 异常为例):- Zuul 中有一个默认的处理异常的 filter,名为 SendErrorFilter,这个过滤器实际所做的工作只是将异常处理转发到了“/error”这个路径上。
- 而在 Spring Boot 中,有一个默认的处理异常的 controller,名为 BasicErrorController,它映射到了“/error”这个路径,这个 controller 对异常的处理是这样的:对于非 rest 方式,返回一个错误页面;对于 rest 方式,返回一个 json。

(2)而如果通过非 rest 方式访问一个路由,当发生异常时,则会显示如下页面内容:

(3)如需要自定义返回的异常信息,只需自定义 /error 的 Controller,实现 ErrorController,覆盖 Spring Boot 默认的处理异常的 controller(BasicErrorController)即可。
- 下面自定义的异常处理 Controller 作用是:无论是 rest 方式、还是非 rest 方式请求路由,当发生异常时,都是返回 JSON 数据。
当然我们继承 BasicErrorController 来创建一个自定义的 ErrorController 也是可以的,具体参考我之前写的文章:
@RestController
public class ErrorHandlerController implements ErrorController {
/**
* 出异常后进入该方法,交由下面的方法处理
*/
@Override
public String getErrorPath() {
return "/error";
}
@RequestMapping("/error")
public ResponseEntity<Map<String, Object>> error(){
// 获取Zuul异常
RequestContext ctx = RequestContext.getCurrentContext();
ZuulException exception = (ZuulException)ctx.getThrowable();
// 获取状态码
HttpStatus status = HttpStatus.resolve(exception.nStatusCode);
// 设置返回的消息体
Map<String, Object> body = new HashMap<>();
body.put("custom", "出错啦------");
body.put("code", status.value());
body.put("error", exception.getMessage());
body.put("message", exception.errorCause);
body.put("cause", exception.getCause().getMessage());
return new ResponseEntity<>(body, status);
}
}
(4)无论是 rest 方式、还是非 rest 方式请求路由,当发生异常时,都是返回 JSON 数据:
全部评论(0)