当前位置: > > > API网关服务组件Spring Cloud Zuul使用详解10(过滤器详解2:异常处理)

API网关服务组件Spring Cloud Zuul使用详解10(过滤器详解2:异常处理)

十二、异常处理

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 处理。
  • Zuul 中有一个默认的处理异常的 filter,名为 SendErrorFilter,这个过滤器实际所做的工作只是将异常处理转发到了“/error”这个路径上。
  • 而在 Spring Boot 中,有一个默认的处理异常的 controller,名为 BasicErrorController,它映射到了“/error”这个路径,这个 controller 对异常的处理是这样的:对于非 rest 方式,返回一个错误页面;对于 rest 方式,返回一个 json
(2)如果想自定义返回的异常信息的 response body 的格式,最简单的方法是仿照 BasicErrorController 重写一下 /error 接口接口。
(1)默认情况下,如果通过 rest 方式访问一个路由,当发生异常时,会返回类似如下信息(以上面抛出 RuntimeException 异常为例):

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

(3)如需要自定义返回的异常信息,只需自定义 /errorController,实现 ErrorController,覆盖 Spring Boot 默认的处理异常的 controllerBasicErrorController)即可。
  • 下面自定义的异常处理 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