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進行相關處理。