3:控制器
Http请求被控制器拦截后交给ZuulServlet处理。
@Bean public ZuulController zuulController() { return new ZuulController(); }
执行顺序越小会越先执行,所有pre过滤器执行完成,才会执行route过滤器,同样所有的post过滤器都会再route过滤器之后执行。(zuulFileter的compareTo方法会比较Order大小,执行过程中,从注册的过滤器列表中获取到相关类型的过滤器,根据优先级从小到大排序。)
大概整理了下zuul自带的一些过滤器
过滤器类型 | 名称 | 执行顺序 | 功能 |
pre | ServletDetectionFilter | -3 | 判断请求头来源是zuulServlet还是DispatcherServlet,决定后续的处理机制 |
pre | FormBodyWrapperFilter | -1 | 解析表单数据重新包装,提供给下游服务使用 |
pre | DebugFilter | 1 | 是否开启调试标志 |
pre | Servlet30WrapperFilter | -2 | 包装为符合servlet3.0规范的请求体 |
pre | PreDecorationFilter | 5 | 路由转发前基本信息配置 |
post | SendResponseFilter | 1000 | 处理正常的请求响应 |
error | SendErrorFilter | 0 | 错误请求响应,早起版本是post的一种,新版本单独列为一种 |
post | LocationRewriteFilter | 900 | 重写位置头信息为zuul url |
route | SendForwardFilter | 500 | 处理内部转发 |
route | RibbonRoutingFilter | 10 | 使用Ribbon, Hystrix转发请求 |
route | SimpleHostRoutingFilter | 100 | 普通请求转发 |
二、ZuulServlet执行过程
前面说过ZuulServlet是Http请求的处理入口,类似用SpringMVC的请求转发器DispatcherServlet,当有Http请求到来时,会先交给ZuulServlet。
ZuulServlet继承HttpServlet,所以大概过程也是初始化-调用service()-销毁。
从service方法可以看出,按pre过滤器-route过滤器-postRoute顺序执行,如果出现错误会调用filterType为error的过滤器处理。
前置过滤器出现错误,会调用error过滤器处理后再交给post过滤器处理。
route过滤器出现错误,也是会先调用error过滤器处理再交给post过滤器处理。
而当post过滤器出现错误,直接调用error过滤器处理,结束流程。
public class ZuulServlet extends HttpServlet { private static final long serialVersionUID = -3374242278843351500L; private ZuulRunner zuulRunner; @Override public void init(ServletConfig config) throws ServletException { super.init(config); String bufferReqsStr = config.getInitParameter("buffer-requests"); boolean bufferReqs = bufferReqsStr != null && bufferReqsStr.equals("true") ? true : false; zuulRunner = new ZuulRunner(bufferReqs); } @Override public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException { 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(); } } ... }
所有过滤器的执行都是通过FilterProcessor来完成,这是过滤器执行的核心类,FilterProcessor是一个单例对象,会根据传入的过滤器类型,获取相关过滤器,根据order排序后依次执行。