关于Zuul的基础使用可以参考 SpringCloud全家桶—Zuul网关
拦截入口
首先看一下Zuul网关的入口类ZuulServlet,继承了HttpServlet,通过service方法拦截所有的get/post请求。
@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();
}
}
四种过滤器执行顺序
首先通过这部分源码可以得出一个在Zuul中四种过滤器的执行顺序。
最终无论是哪种过滤器都会执行到这个部分,然后通过type来区分
zuul中每种类型自带的过滤器
pre类型的
route类型的
post类型的
自定义过滤器重写shouldFliter和run两个方法的调用
runFilters的主要作用就是根据不同类型的过滤器,遍历并挨个执行。
主要处理业务逻辑的方法。
requestContext.setSendZuulResponse(false)控制是否路由
sendZuulResponse用来判断是否需要进行路由,这个值一般在自定义路由的时候会进行设置。
SimpleHostRoutingFilter、RibbonRoutingFilter在执行时都会对这个属性进行判断,确认是否需要对其进行路由。
SimpleHostRoutingFilter,配置文件中配置的是:指定url方式。
@Override
public boolean shouldFilter() {
return RequestContext.getCurrentContext().getRouteHost() != null
&& RequestContext.getCurrentContext().sendZuulResponse();
}
RibbonRoutingFilter,配置文件中配置的是:指定服务名方式,从eureka拉取服务列表,通过ribbon负载均衡调用
@Override
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
return (ctx.getRouteHost() == null && ctx.get(SERVICE_ID_KEY) != null
&& ctx.sendZuulResponse());
}