MapperListener主要是观察者模式,其负责监听Tomcat后端容器组件的各种事件的变化,当一旦有风吹草动的时候,就会将这些变化同步到Mapper路由缓存中;
MapperListener主要的持有Mapper,其中Mapper可以理解为整个Tomcat的“路由表”;
本文,我们主要关注的就是这个Mapper的数据结构,并且通过源码的分析看看其是怎么从一个contextPath的进入,最终执行Wrapper进行路由的;
1.关键属性
Mapper类有三个比较关键的属性:

MapperHost:是Mapper数据结构的起始位置,其关联的是最终“路由表”数据结构,这个在下面会详述;
defaultHost:Engine属性可以配置一个defaultHost的属性,但无论你配不配置,都需要有一个defaultHost在路由映射的时候进行路由;
contextObjectContextVersionMap:是Context(StandardContext)和ContextVersion(路由表内部对象)之间的映射,其主要是为了方便Tomcat内部对象查询用的;
上述三个属性中,其中MapperHost代表着路由表。
2."路由表"数据结构

MapperHost:
一个Tomcat中有n个Host,而这个MapperHost就是Host的路由表的抽象;
值得注意的一点是,MapperHost自己和自己还是1:n的关系,这个是为什么呢?

每一个MappedHost中是可以有别名的,而且可以起n个别名,而这n个别名其实都是MappedHost类型,这就是aliases的1:n的由来;
<Host name="www.mycompany.com" ...> ... <Alias>mycompany.com</Alias> ... </Host>
如上面所示,Alias可以有n个;
对于原有的Host,是realHost;
ContextList:
一个Host中有n个Context,这个ContextList抽象的就是这n个Context;
MappedContext:
每一个Context在路由表中抽象为MappedContext;
但这个MappedContext并不是最终的结局,因为Tomcat中的应用可以有多版本一说,所以MappedContext需要持有n个版本信息:

ContextVersion:

ContextVersion实际代表着一个应用,即使这个应用没有任何的版本,它其中含有的Wrapper信息是主要的路由来源,除此之外,WebResourceRoot是当前应用除了动态Wrapper之外的静态页面等资源信息,还包括welcomeResources的欢迎页面等等;
对于Mapper的一些方法,主要以addXXX为主,也就是当MapperListener触发事件或者是初始化加入应用路由信息的时候,都会调用这些addXX方法:

而实际上的路由的过程,是Tomcat前端CoyoteAdaptor的postParseRequest中需要组装Request,而缺少Mapping信息的,这个时候,就会中调用map方法进行匹配:

基于上述的路由数据结构,Tomcat是怎么通过Mapper进行在“路由表”中进行查询的呢?
下一篇文章再进行分解!




