文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring Cloud Zuul中异常处理细节有哪些

2023-06-19 12:09

关注

本篇内容主要讲解“Spring Cloud Zuul中异常处理细节有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring Cloud Zuul中异常处理细节有哪些”吧!

首先我们来看一张官方给出的Zuul请求的生命周期图,如下:

Spring Cloud Zuul中异常处理细节有哪些  

关于这张图我说如下几点:

正常情况下所有的请求都是按照pre、route、post的顺序来执行,然后由post返回response
2.在pre阶段,如果有自定义的过滤器则执行自定义的过滤器
3.pre、routing、post的任意一个阶段如果抛异常了,则执行error过滤器,然后再执行post给出响应

这是这张图给我们的信息,我们再来看看源码com.netflix.zuul.http.ZuulServlet类中的service方法,这是整个调用过程的核心,如下:

try {    init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);    // Marks this request as having passed through the "Zuul engine", as opposed to servlets    // explicitly bound in web.xml, for which requests will not have the same data attached    RequestContext context = RequestContext.getCurrentContext();    context.setZuulEngineRan();    try {        preRoute();    } catch (ZuulException e) {        error(e);        postRoute();        return;    }    try {        route();    } catch (ZuulException e) {        error(e);        postRoute();        return;    }    try {        postRoute();    } catch (ZuulException e) {        error(e);        return;    }} catch (Throwable e) {    error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));} finally {    RequestContext.getCurrentContext().unset();}

我们看到这里有一个大的try…catch,大的try…catch里边有三个小的try…catch,小的try…catch只负责捕获ZuulException异常,其他的异常交给大的try…catch来捕获。pre和route执行出错之后都会先执行error再执行post,而post执行出错之后就只执行error而不会再执行post。

ZuulFilter最终会在com.netflix.zuul.FilterProcessor的processZuulFilter方法中被调用,在该方法中会判断runFilter是否执行成功,如果执行失败,则将异常信息提取出来,然后抛出异常,抛出的异常如果是ZuulException的实例,则抛出一个ZuulException类型的异常,如果不是ZuulException的实例,则抛出一个状态码为500的ZuulException类型的异常,所以无论如何,我们最终看到的都是ZuulException类型的异常,下面我贴出processZuulFilter方法的一部分核心代码,如下:

public Object processZuulFilter(ZuulFilter filter) throws ZuulException {    try {        ZuulFilterResult result = filter.runFilter();        ExecutionStatus s = result.getStatus();        execTime = System.currentTimeMillis() - ltime;        switch (s) {            case FAILED:                t = result.getException();                ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);                break;            case SUCCESS:                break;            default:                break;        }        if (t != null) throw t;        usageNotifier.notify(filter, s);        return o;    } catch (Throwable e) {        usageNotifier.notify(filter, ExecutionStatus.FAILED);        if (e instanceof ZuulException) {            throw (ZuulException) e;        } else {            ZuulException ex = new ZuulException(e, "Filter threw Exception", 500, filter.filterType() + ":" + filterName);            ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);            throw ex;        }    }}

在Zuul中,所有的错误问题的最终都是被SendErrorFilter类来处理,该类在早期的版本是一个post类型的filter,post类型的filter有一个缺陷就是不能处理post中抛出的异常,需要我们手动去完善,而我目前使用的这个版本(Dalston.SR3)已经修复了这个问题,SendErrorFilter现在是一个error类型的filter,而且只要RequestContext中有异常就会进入到SendErrorFilter中,错误信息也都从exception对象中提取出来,核心代码如下:

@Overridepublic boolean shouldFilter() {    RequestContext ctx = RequestContext.getCurrentContext();    // only forward to errorPath if it hasn't been forwarded to already    return ctx.getThrowable() != null            && !ctx.getBoolean(SEND_ERROR_FILTER_RAN, false);}@Overridepublic Object run() {    try {        RequestContext ctx = RequestContext.getCurrentContext();        ZuulException exception = findZuulException(ctx.getThrowable());        HttpServletRequest request = ctx.getRequest();        request.setAttribute("javax.servlet.error.status_code", exception.nStatusCode);        log.warn("Error during filtering", exception);        request.setAttribute("javax.servlet.error.exception", exception);        if (StringUtils.hasText(exception.errorCause)) {            request.setAttribute("javax.servlet.error.message", exception.errorCause);        }        RequestDispatcher dispatcher = request.getRequestDispatcher(                this.errorPath);        if (dispatcher != null) {            ctx.set(SEND_ERROR_FILTER_RAN, true);            if (!ctx.getResponse().isCommitted()) {                dispatcher.forward(request, ctx.getResponse());            }        }    }    catch (Exception ex) {        ReflectionUtils.rethrowRuntimeException(ex);    }    return null;}

如果我们想要自定义异常信息也很方便,如下:

@Componentpublic class MyErrorAttribute extends DefaultErrorAttributes {    @Override    public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {        Map<String, Object> result = super.getErrorAttributes(requestAttributes, includeStackTrace);        result.put("status", 222);        result.put("error", "error");        result.put("exception", "exception");        result.put("message", "message");        return result;    }}

到此,相信大家对“Spring Cloud Zuul中异常处理细节有哪些”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯