Zuul 处理 Http 请求都是基于 SpringMVC 上的,细心的你必定注意到了,当你搭建了一个zuul后配置后端隐射请求 /apps/** 到你的后端服务时,不管 /apps/**** 仍是 /zuul/apps/**** 都能到达你的后端服务。java
那么这到达是如何实现的呢?web
Zuul 有一个自制的 Servlet -- ZuulServlet, 它包含了 Zuul 全部的处理流程的主干支,这里不详细介绍,之后会篇章会详细介绍 Zuul 的处理流程。后端
SpringBoot 有个 ServletRegistrationBean 是专门用来注册自定义 Servlet 的。api
public ServletRegistrationBean zuulServlet() { ServletRegistrationBean servlet = new ServletRegistrationBean(new ZuulServlet(), this.zuulProperties.getServletPattern()); servlet.addInitParameter("buffer-requests", "false"); return servlet; }
这里还有一个定义路基path 的使用,默认是 /zuul,你能够经过配置文件定义成其余,以下就改为 /api 了app
zuul.servletPath=/api
若是没有使用 SpringBoot 的话,那么其实老办法只要将 ZuulServlet 配置在 web.xml 中便可,路径也是 web.xml 中配置。ide
来看下这个是哪门哪派的。this
RequestMappingHandlerMapping 不会陌生,SpringMVC默认使用的就是这个,它会捕捉全部 @Controller 和 @RequetMapping 注解的方法来处理不一样的URL。spa
SpringMVC3.1以前其实不是使用上面这个类,而是使用 AbstractUrlHandlerMapping 的派系 -- DefaultAnnotationHandlerMapping,这个类但是 ZuulHandlerMapping 一个派系的,都是根据 URL 来选择使用使用什么来处理。.net
那到底用什么来处理呢?ZuulHandlerMapping 中 registerHandlers 方法回答了这个问题code
private void registerHandlers() { Collection<Route> routes = this.routeLocator.getRoutes(); if (routes.isEmpty()) { this.logger.warn("No routes found from RouteLocator"); } else { for (Route route : routes) { registerHandler(route.getFullPath(), this.zuul); } } }
this.zuul 是什么? ZuulController
public class ZuulController extends ServletWrappingController
原来是 Servlet 包装成 Controller, 其实仍是 ZuulServlet
public class ZuulController extends ServletWrappingController { public ZuulController() { setServletClass(ZuulServlet.class); // <<======= See Here! setServletName("zuul"); setSupportedMethods((String[]) null); // Allow all } @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { try { return super.handleRequestInternal(request, response); } finally { RequestContext.getCurrentContext().unset(); } } }
Zuul 的 Request 怎么进来的到这已经清楚了,下面分析进来之后发生了什么。
详细代码解析见 SpringCloud 之 Zuul 源代码详细笔记