網關Zuul——url請求流轉路徑
在springcloud的網關組件zuul中,網關本身能夠接收url請求,那么請求在網關zuul組件中是怎么流轉的呢?
從前面的文章可以看出,當外部請求傳遞到網關(Zuul)時,請求會傳遞到ZuulController類中
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView var3; try { var3 = super.handleRequestInternal(request, response); } finally { RequestContext.getCurrentContext().unset(); } return var3; }
這里可以看出,外部請求會進入ZuulController類中,交由handleRequest方法處理,而該方法實際調用其父類的handleRequestInternal方法
查看ZuulController的父類ServletWrappingController
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { Assert.state(this.servletInstance != null, "No Servlet instance"); this.servletInstance.service(request, response); return null; }
在ServletWrappingController類的handleRequestInternal方法中,請求是由ZuulServlet的service方法處理
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { try { this.init((HttpServletRequest)servletRequest, (HttpServletResponse)servletResponse); RequestContext context = RequestContext.getCurrentContext(); context.setZuulEngineRan(); try { this.preRoute(); } catch (ZuulException var12) { this.error(var12); this.postRoute(); return; } try { this.route(); } catch (ZuulException var13) { this.error(var13); this.postRoute(); return; } try { this.postRoute(); } catch (ZuulException var11) { this.error(var11); } } catch (Throwable var14) { this.error(new ZuulException(var14, 500, "UNHANDLED_EXCEPTION_" + var14.getClass().getName())); } finally { RequestContext.getCurrentContext().unset(); } } //處理http請求 void init(HttpServletRequest servletRequest, HttpServletResponse servletResponse) { this.zuulRunner.init(servletRequest, servletResponse); }
從上述代碼可以看出,http請求會傳遞到ZuulRunner類中進行處理
查看ZuulRunner中的處理方式
public void init(HttpServletRequest servletRequest, HttpServletResponse servletResponse) { RequestContext ctx = RequestContext.getCurrentContext(); if (this.bufferRequests) { ctx.setRequest(new HttpServletRequestWrapper(servletRequest)); } else { ctx.setRequest(servletRequest); } ctx.setResponse(new HttpServletResponseWrapper(servletResponse)); }
查看上述代碼,可以看出請求最后被存放在RequestContext類中,而RequestContext是一個靜態單例的,所以在程序的任何位置都可以通過獲取RequestContext的實例來獲取到http請求信息。而這也就是過濾器用以進行請求過濾的基礎。
總結:
http請求的流轉路徑:
ZuulController的handleRequest方法——>ServletWrappingController的handleRequestInternal方法——>ZuulServlet的service方法——>ZuulServlet的init方法——>
ZuulRunner的init方法——>RequestContext的實例中