文档章节

Tomcat8源码分析-启动流程-MapperListener启动

特拉仔
 特拉仔
发布于 2019/12/08 10:51
字数 868
阅读 205
收藏 0

上一篇:Tomcat8源码分析-启动流程-start方法

MapperListener启动主要完成了将资源(class目录、jar、servlet-mapping、welcome list)添加MappedHost下的ContextVersion的不同Wrappers数组当中,以及将自己设置为该Engine及其下面是所有容器的ContainerListener与LifeCycleListener

完成上面的功能有什么作用喃???可以说太重要了,看到“servlet-mapping”就应该想到肯定是与处理请求的时候相关的,没错,当Tomcat处理请求的时候就会根据path与上面处理形成的Wrappers数组进行匹配得到Servlet,并设置给StandardWrapperValve.StandardWrapper.servlet,最终才能调用到对应Servlet的方法。

看看源码

StandardService部分

   protected void startInternal() throws LifecycleException {

        。。。。。省略其他代码。。。。。

        /** 很重要
         * 会完成如下资源的解析与加载
         * 1.将Context下的Wrapper(自定义的Servlet\defaultServlet\jspServlet\jspxServlet)进行分析,并最终拆分为ContextVersion的四个Wrapper数组,
         *   exactWrappers\wildcardWrappers\extensionWrappers\defaultWrapper,他们在Tomcat接收请求时被用作与path匹配,最终得
         *   到想要的Servlet
         * 2.将Context中的WebResource(里面包含了比如class目录、jar包添加到ContextVersion
         * 3.将welcome list配置添加到ContextVersion
         *
         */

        mapperListener.start();

        。。。。。省略其他代码。。。。。
    }

调用start方法(按照前面讲的模板方法设计模式套路),紧接着会按照Mapper.registerHost-Mapper.registerContext-Mapper.addContextVersion-Mapper.addWrappers-Mapper.-Mapper.addWrapper这个顺序进入到下面的源代码,在这里面就完成了默认Servlet和自定义Sevlet的Mapping规则加载,等候被使用。

    protected void addWrapper(ContextVersion context, String path,
            Wrapper wrapper, boolean jspWildCard, boolean resourceOnly) {

        synchronized (context) {
            if (path.endsWith("/*")) {//以"/*"开始的path加入到通配符wrapper当中
                // Wildcard wrapper
                String name = path.substring(0, path.length() - 2);
                MappedWrapper newWrapper = new MappedWrapper(name, wrapper,
                        jspWildCard, resourceOnly);
                MappedWrapper[] oldWrappers = context.wildcardWrappers;
                MappedWrapper[] newWrappers = new MappedWrapper[oldWrappers.length + 1];
                if (insertMap(oldWrappers, newWrappers, newWrapper)) {
                    context.wildcardWrappers = newWrappers;
                    int slashCount = slashCount(newWrapper.name);
                    if (slashCount > context.nesting) {
                        context.nesting = slashCount;
                    }
                }
            } else if (path.startsWith("*.")) {//以"*."开始的path加入到后缀Wrapper当中
                // Extension wrapper
                String name = path.substring(2);
                MappedWrapper newWrapper = new MappedWrapper(name, wrapper,
                        jspWildCard, resourceOnly);
                MappedWrapper[] oldWrappers = context.extensionWrappers;
                MappedWrapper[] newWrappers =
                    new MappedWrapper[oldWrappers.length + 1];
                if (insertMap(oldWrappers, newWrappers, newWrapper)) {
                    context.extensionWrappers = newWrappers;
                }
            } else if (path.equals("/")) {//设置默认的DefaultMapper
                // Default wrapper
                MappedWrapper newWrapper = new MappedWrapper("", wrapper,
                        jspWildCard, resourceOnly);
                context.defaultWrapper = newWrapper;
            } else { //到这里都还没匹配到的就是精确Wrapper了
                // Exact wrapper
                final String name;
                if (path.length() == 0) {
                    // Special case for the Context Root mapping which is
                    // treated as an exact match
                    name = "/";
                } else {
                    name = path;
                }
                MappedWrapper newWrapper = new MappedWrapper(name, wrapper,
                        jspWildCard, resourceOnly);
                MappedWrapper[] oldWrappers = context.exactWrappers;
                MappedWrapper[] newWrappers = new MappedWrapper[oldWrappers.length + 1];
                if (insertMap(oldWrappers, newWrappers, newWrapper)) {
                    context.exactWrappers = newWrappers;
                }
            }
        }
    }

再来看看ContextVersion实例化的时候传的参数有哪些,这些参数就说明了它包含了那些资源

        //将新生成的Context添加到Host的contextList当中。在这里也验证了一个Host可以有多个Context(一个应用)
        mapper.addContextVersion(host.getName(), host, contextPath,
                context.getWebappVersion(), context, welcomeFiles, resources,
                wrappers);

其中的resources就是WebResource,里面就是之前已经解析完成的目录与jar资源

 

再来看看ContextVersion在Debug时构造完成后几个关键属性中的值

这张图看清楚了Tomcat启动之后有哪些Wrapper(也就是Servlet可以使用)

这张图再点进去看可以看到目录与jar相关信息

 

总结

MapperListener真的很重要,完成了非常核心的servlet-mapping的分析与加载,让处理请求的阶段可以找到对照表(4中Wrappers数组)进行匹配,从而能够正确的进行业务逻辑处理。

© 著作权归作者所有

特拉仔
粉丝 62
博文 279
码字总数 286943
作品 0
渝中
架构师
私信 提问
加载中

评论(0)

Tomcat8源码分析-启动流程-start方法

上一篇:Tomcat8源码分析-启动流程-load方法 前面讲了启动流程中的Catalina.load,进一步调用绝大部分组建的init操作,主要完成对server.xml解析,并根据解析的结果结合设置的Rule(规则)构造...

特拉仔
2019/12/08
48
0
Tomcat7.0源码分析——请求原理分析(上)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/beliefer/article/details/51645799 前言   谈起Tomcat的诞生,最早可以追溯到1995年。近20年来,Tomcat始终...

泰山不老生
2016/06/30
0
0
Tomcat学习之Connector

目录(?)[-] protocol Service mapperListener 初始化与启动 如下图所示,Tomcat服务器主要有两大核心模块组成:连接器和容器,本节只分析连接器的实现。 连接器主要是接收用户的请求,然后封...

wangxuwei
2016/09/26
32
0
Tomcat8源码分析-请求处理过程(含源码中新建web应用一起调试)

上一篇:Tomcat8源码分析-启动流程-start方法 此篇主要将Tomcat8从接收请求到处理请求的时序图画出来,并用文字描述一下主要流程 时序图 图片有点大,需要点开了放大看 说明 文字描述流程之前...

特拉仔
2019/12/11
41
0
谈谈 Tomcat 架构及启动过程 [ 含部署 ]

(点击上方公众号,可快速关注) 来源:Rainstorm, github.com/c-rainstorm/blog/blob/master/tomcat/谈谈%20Tomcat%20架构及启动过程%5B含部署%5D.md 这个题目命的其实是很大的,写的时候还...

ImportNew
2018/01/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

PHP一致性hash代码

[TOC] PHP实现一致性hash bash命令 因为下面PHP代码的模拟用户用的是随机数,所以统计结果达不到绝对的均衡. php ./hash.php | sort | uniq -c | sort PHP代码 这是之前学的时候留下来的测试...

我爱吃炒鸡
今天
78
0
OSChina 周六乱弹 —— 现在看动弹的人都是什么状态

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @薛定谔的兄弟 :分享洛神有语创建的歌单「我喜欢的音乐」: 《夏日、教室与望着窗外的我》- Candy_Wind 手机党少年们想听歌,请使劲儿戳(这里...

小小编辑
今天
174
4
wamp环境安装redis扩展

1.查看phpinfo信息根据配置信息下载对应的扩展 关键信息:VC14,TS,x86 2.下载php_redis和php_igbinary扩展 php_redis扩展下载地址: https://windows.php.net/downloads/pecl/snaps/redis...

点滴课程
今天
36
0
开源商城开发笔记1-创建MyBatis示例

一、修改pom.xml,引入MyBatis,JUnit,Log4j <dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.4</version>......

土龙
今天
56
0
The Best Way To Learn English in 2020 (In my humble opinion.)

✅Here is the plan: THINGS YOU WILL NEED: - 1 hour per day (30 minutes will work as well). - a notebook and a pen to write down new vocabulary each day. - an English song. - an ......

FalconChen
昨天
85
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部