ZuulServlet是HttpServlet。Servlet的生命周期包括init(仅第一次)、service、destroy。ZuulServlet的init在Zuul- 启动提过了,就是创建一个ZuulRunner对象。所以我们主要看service方法

ZuulServlet#service

这个方法就是获取一个RequestContext,如果没有则创建,是ThreadLocal类。获取后就开始调用preRoute、route、postRoute、error方法。由于这几个方法调用方式是一致的,所以下面就只讲preRoute,这个方法实际就是调用ZuulRunner#preRoute方法。

@Override
public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException {
    try {
        // 给RequestContext赋值request和HttpResponse
        init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);
        // 获取RequestContext
        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();
    }
}

ZuulRunner#preRoute

preRoute是单例。然后调用runFilters。在runFilters中,先从FilterLoader获取ZuulFilter集合,然后遍历处理ZuulFilter。

public void preRoute() throws ZuulException {
    runFilters("pre");
    //其他略
}

public Object runFilters(String sType) throws Throwable {
    
    boolean bResult = false;
    // 从FilterLoader获取ZuulFilter集合
    List<ZuulFilter> list = FilterLoader.getInstance().getFiltersByType(sType);
    if (list != null) {
        for (int i = 0; i < list.size(); i++) {
            ZuulFilter zuulFilter = list.get(i);
            // 处理每个ZuulFilter
            Object result = processZuulFilter(zuulFilter);
            if (result != null && result instanceof Boolean) {
                bResult |= ((Boolean) result);
            }
        }
    }
    return bResult;
}

FilterLoader#getFiltersByType

FilterLoader也是单例。主要就是ConcurrentHashMap类型的hashFiltersByType取值,没有的话从filterRegistry获取,然后排序返回。

public List<ZuulFilter> getFiltersByType(String filterType) {
    // 从ConcurrentHashMap类型的hashFiltersByType,通过filterType取ZuulFilter集合
    List<ZuulFilter> list = hashFiltersByType.get(filterType);
    // 如果有了,直接返回
    if (list != null) return list;

    list = new ArrayList<ZuulFilter>();
    //没有从filterRegistry获取,并根据filterType拿到对应的ZuulFilter
    Collection<ZuulFilter> filters = filterRegistry.getAllFilters();
    for (Iterator<ZuulFilter> iterator = filters.iterator(); iterator.hasNext(); ) {
        ZuulFilter filter = iterator.next();
        if (filter.filterType().equals(filterType)) {
            list.add(filter);
        }
    }
    // 排序
    Collections.sort(list); // sort by priority

    hashFiltersByType.putIfAbsent(filterType, list);
    return list;
}

FilterProcessor#processZuulFilter

拿到ZuulFilter集合后,对每个ZuulFilter处理。主要的调用ZuulFilter的runFilter方法。

public Object processZuulFilter(ZuulFilter filter) throws ZuulException {
    // 其他略    
    ZuulFilterResult result = filter.runFilter();
    // 其他略    
}

ZuulFilter#runFilter

public ZuulFilterResult runFilter() {
    ZuulFilterResult zr = new ZuulFilterResult();
    // 是否配置禁用,"zuul." + this.getClass().getSimpleName() + "." + filterType() + ".disable"
    // 比如zuul.PreDecorationFilter.pre.disable=false
    if (!isFilterDisabled()) {
        // 这个是我们需要写的,是否过滤
        if (shouldFilter()) {
            Tracer t = TracerFactory.instance().startMicroTracer("ZUUL::" + this.getClass().getSimpleName());
            try {
                // 这个是我们需要写的run方法
                Object res = run();
                zr = new ZuulFilterResult(res, ExecutionStatus.SUCCESS);
            } catch (Throwable e) {
                t.setName("ZUUL::" + this.getClass().getSimpleName() + " failed");
                zr = new ZuulFilterResult(ExecutionStatus.FAILED);
                zr.setException(e);
            } finally {
                t.stopAndLog();
            }
        } else {
            zr = new ZuulFilterResult(ExecutionStatus.SKIPPED);
        }
    }
    return zr;
}

总结

ZuulServlet#service中,通过各个ZuulServlet进行相关处理。
image


大军
847 声望183 粉丝

学而不思则罔,思而不学则殆


« 上一篇
Zuul- 启动
下一篇 »
Zuul- 路由加载