Zuul如何继承SpringmMvc
-
ZuulHandlerMapping此类实现了 springmvc AbstractUrlHandlerMapping 重写了
lookupHandler方法并在此方法中 完成了 路由信息的 注册 -
ZuulHandlerMapping 源码分析
该类主要作用完成了 zuul 路由的注册 多个 path配置对应一个 ZuulController
比如 application.yml 配置了 2个route 的path 对应过来的就是
/test01/** --->ZuulController
/test02/** ---->ZuulController
zuul:
ignored-patterns: /test/**
routes:
myroute:
url: http://localhost:8085/
path: /test01/**
id: test
myroute1:
url: http://localhost:8080/
path: /test02/**
id: test-1
public class ZuulHandlerMapping extends AbstractUrlHandlerMapping {
private final RouteLocator routeLocator;
private final ZuulController zuul;
private ErrorController errorController;
private PathMatcher pathMatcher = new AntPathMatcher();
private volatile boolean dirty = true;
public ZuulHandlerMapping(RouteLocator routeLocator, ZuulController zuul) {
this.routeLocator = routeLocator;
this.zuul = zuul;
//设置handlerMapper的顺序为-200 也就是最前
//很重要在DispatcherServlet中 doDispatch中 getHandler会体现出来
setOrder(-200);
}
//跨越相关 重写了父类方法判断CorsConfiguration是否为空
@Override
protected HandlerExecutionChain getCorsHandlerExecutionChain(
HttpServletRequest request, HandlerExecutionChain chain,
CorsConfiguration config) {
if (config == null) {
return chain;
}
return super.getCorsHandlerExecutionChain(request, chain, config);
}
public void setErrorController(ErrorController errorController) {
this.errorController = errorController;
}
//设置路由注册标志 为true需要注册
public void setDirty(boolean dirty) {
this.dirty = dirty;
if (this.routeLocator instanceof RefreshableRouteLocator) {
((RefreshableRouteLocator) this.routeLocator).refresh();
}
}
//重写的父类的 查询 handler方法
/* 1,判断是否为 error的url如果是并且errorController存在 返回null
* 2,判断 zuul.ignored-patterns配置 如果匹配到直接返回null
* 3,判断是否为重定向 如果为重定向 返回null
*/
@Override
protected Object lookupHandler(String urlPath, HttpServletRequest request)
throws Exception {
if (this.errorController != null
&& urlPath.equals(this.errorController.getErrorPath())) {
return null;
}
if (isIgnoredPath(urlPath, this.routeLocator.getIgnoredPaths())) {
return null;
}
RequestContext ctx = RequestContext.getCurrentContext();
if (ctx.containsKey("forward.to")) {
return null;
}
//判断路由是注册过
if (this.dirty) {
synchronized (this) {
if (this.dirty) {
//注册handler
registerHandlers();
this.dirty = false;
}
}
}
return super.lookupHandler(urlPath, request);
}
//处理zuul.ignored-patterns配置的url是否匹配
private boolean isIgnoredPath(String urlPath, Collection<String> ignored) {
if (ignored != null) {
for (String ignoredPath : ignored) {
if (this.pathMatcher.match(ignoredPath, urlPath)) {
return true;
}
}
}
return false;
}
//注册handler
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) {
//key 为route的 path
//value为 ZuulController
registerHandler(route.getFullPath(), this.zuul);
}
}
}
}
- ZuulController 核心类分析 上面分析 得知所有的 url 都对应一个 controller 那就是 ZuulController
类图:
实现了ServletWrappingController类 见名知意 其实就是一个 Servlet 持有器的 Controller 实现了 Controller接口
public class ZuulController extends ServletWrappingController {
public ZuulController() {
//调用夫类方法 设置servlet的class父类通过反射创建对象
setServletClass(ZuulServlet.class);
//设置servlet名称
setServletName("zuul");
setSupportedMethods((String[]) null);
}
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
try {
//调用夫类方法 处理请求
return super.handleRequestInternal(request, response);
}
finally {
//因为zuul中RequestContext 使用 threadLocal存储请求结束后 需要remove 释放 防止内存泄露
RequestContext.getCurrentContext().unset();
}
}
}
父类 ServletWrappingController 的handleRequestInternal() 方法
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
//servlet非空判断
Assert.state(this.servletInstance != null, "No Servlet instance");
//直接调用servlet service方法 也就是 ZuulServlet 的service方法
this.servletInstance.service(request, response);
return null;
}
- ZuulSevlet 继承 HttpServlet
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 {
//请求进来之后 zuulRunner初始化 主要是创建RequestContext对象
init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);
RequestContext context = RequestContext.getCurrentContext();
//设置zuulEngineRan 属性为true
context.setZuulEngineRan();
try {
//执行 pre 过滤器
preRoute();
} catch (ZuulException e) {
//出现异常 执行error后 再执行 postRoute
error(e);
postRoute();
return;
}
try {
//执行route
route();
} catch (ZuulException e) {
error(e);
postRoute();
return;
}
try {
//执行postRoute
postRoute();
} catch (ZuulException e) {
error(e);
return;
}
} catch (Throwable e) {
//出现异常调用error过滤器
error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));
} finally {
//释放内存
RequestContext.getCurrentContext().unset();
}
}
/**
* 执行 "post" 过滤器
*/
void postRoute() throws ZuulException {
zuulRunner.postRoute();
}
/**
* 执行 "route" 类型过滤器
*/
void route() throws ZuulException {
zuulRunner.route();
}
/**
* 执行 "pre" 类型过滤器
*/
void preRoute() throws ZuulException {
zuulRunner.preRoute();
}
//初始化 zuulRunner 创建 RequestContext对象并把请求对象和返回对象进行设置
void init(HttpServletRequest servletRequest, HttpServletResponse servletResponse) {
zuulRunner.init(servletRequest, servletResponse);
}
//发生错误
void error(ZuulException e) {
RequestContext.getCurrentContext().setThrowable(e);
zuulRunner.error();
}
}