Context实例表示一个具体的web应用程序,其中包含一个或者多个Wrapper实例,每个Wrapper表示一个具体的servlet定义。StandardContext类是Context接口的标准实现。

一、相关类 UML图:

1、StandardContext是一个相当复杂的容器类,他实现了Context接口,类的很多功能是依赖于其他对象完成的,因此在start启动Context时会启动所有的这些依赖对象,Available变量表示StandardContext对象是否可用,如果启动都正常且配置文件读取正常,则Available变量为True,如果启动失败则为False;启动时会给Context的所有监听器发送START_EVENT事件,ContextConfig对象也是其中一个监听器,他会读取web.xml文件并初始化配置,如果成功则设置Configured变量为True,否则设置为False;

2、每个容器对象都有name属性,StandardContext对象也不例外,也有name属性;DocBase表示该web应用的路径,该应用下的所有servlet都是该路径加上servlet的路径组合而来;welcomeFiles存储了默认首页的名称列表;

3、每个Context应用都有若干个servlet,children变量是一个hashMap类型的,存储了所有servlet实例Wrapper对象,存储时是以Wrapper.Name和Wrapper对象为键值对存储的;

4、servletMappings是一个HashMap类型的变量,存储了servletPath和servletName的键值对关系,addServletMapping函数实现了将servletPath和servletName添加为一个映射的功能;

5、客户端的请求Request到达StandardContextValve.invoke方法时会调用Context.map方法查找到处理该请求的servlet对象,而这个map方法就是依赖StandardContextMapper对象完成的,StandardContextMapper.map方法会首先从Request请求中解析出relativeURI,然后拿这个路径到servletMappings去查找映射,根据映射关系中的servletName可以查找到对应的Wrapper对象;

6、WebAppLoader实现了Context的加载器,NamingContextListener实现了对StandardContext的监听,完成在Context启动和关闭时绑定对象到JDNI和从JDNI上解除绑定;

7、ProxyDirContext对象实现了DirContext接口,代理了对WARDirContext或者FileDirContext对象的访问,同时提供了缓存机制,其意义表示对web应用程序的war文件或者目录资源的访问控制和属性的访问控制;

8、StandardManager对象实现了Context中的session管理机制;charsetMapper对象实现了字符集映射器;Logger对象实现了Context的日志管理功能;Cluster对象实现了集群管理功能;realm对象实现了安全管理功能;resources对象实现了资源管理功能;pipeline对象实现了Context的管道功能,对Context.invoke调用都会转为对pipeline.invoke调用;

9、ContextConfig对象也是作为Context的一个监听器之一,代码如下:

因此在他的lifecycleEvent中的START_EVENT事件时会读取tomcat目录下Conf/web.xml文件和web应用目录下的WEB-INF/web.xml文件:

同时判断当前链接如果是安全链接https,则会添加许可阀到管道对象中:

此外还会安装一个验证器阀到管道对象中(根据配置文件中指定的web应用的验证方式(Basic, Form, Degister, Client-cert)来安装不同的验证器阀):

最后start方法如果成功读取和初始化配置文件并且成功的安装了相关阀门到管道对象,则设置Context的Configured变量为True,否则设置为False;

二、启动流程:

三、客户端请求处理流程:

1、客户端的请求通过在Connect里面生成Request和Response对象后,调用容器(Context)的invoke方法并传入request和response参数;

2、Context的invoke方法调用管道对象PipeLine的invoke方法,PipeLine.invoke又通过ValveContext调用到StandardContextValve.invoke方法,然后这个invoke方法通过协议方式(http)在Context里面查找到对应的Mapper对象,调用mapper.map方法来返回对应的Wrapper对象;

3、在StandardContextMapper.map方法里面,首先从request里面解析出requestURI和relativeURI,根据relativeURI在Context的servletMappings里面查找到对应的servetName(servletMappings里面存储了servletName和路径的映射关系),然后再拿servletName在children里面查找对应的servlet对象Wrapper(children是一个存储了servletName和Wrapper对象映射关系的HashMap);

4、在StandardContextMapper.map返回了对应的Wrapper对象后,最后调用Wrapper对象的invoke方法完成对servlet的调用;

那么Context中的servletName和servletPath是如何建立映射关系的了:

1、首先我们在应用程序的web.xml文件中配置了映射关系:

2、在webRuleSet.java文件中读取servlet-mapping的内容并调用Context. addServletMapping方法:

3、在Context.addServletMapping方法中将servletName和servletPath添加到servletMappings的hashMap变量中:

四、reLoad机制:

Context的reLoad机制是通过WebAppLoader类来实现的;

1、在WebAppLoader.setContainer里面调用setReloadable来设置WebAppLoader的reloadable变量,通过根据reloadable变量值为true或者false来开启或者停止线程;

2、由于WebAppLoader类实现了Runnable接口,因此可以启动一个线程来执行WebAppLoader.run方法;

3、WebAppLoader.run方法会调用classLoader.modified()来检查web应用下的文件有无变更,如果有则重新开启一个线程来执行Context.Reload方法;

4、Context.reload方法与start方法先将Context相关联的对象和子容器对象停止(stop),然后再开启(start);

五、JNDI配置:

1、配置:

在Context.xml文件中配置如下:

<Context>

<Resource name=”jdbc/xx” auth=”container” type=”javax.sql.DataSource”
password=”mysql” driverClassName=”com.mysql.jdbc.Driver” username=”root” url=”jdbc://mysql://127.0.0.1/xx”
/>

</Context>

那么在java代码中可以这样访问上面的服务:

InitialContext ctx = new InitialContext();

DataSource ds = (DataSource)ctx.lookup(“java:comp/env/jdbc/xx”);

2、那么Jdbc/xx 服务是如何绑定到JNDI上面的了:

  • 首先StandardContext.start方法会创建NamingContextListener对象,这个对象是一个绑定到StandardContext的监听器对象;
  • 然后StandardContext会发出START_EVENT事件消息,NamingContextListener接收到该事件后就创建NamingContext对象,并将此对象绑定在容器中:

  • 接着在createNamingContext函数中创建子上下文:

  • 一旦创建了子上下文,就会被已经由degister解析出来的ContextResource对象加载到上下文中

对于上面的配置信息,这里会依次创建jdbc子上下文和xx子上下文;

tomcat源码阅读之StandardContext的更多相关文章

  1. Tomcat源码阅读(二)初始化

    近来,我开始阅读tomcat的源码,感觉还挺清晰易懂:为了方便理解,我参考了网上的一些文章,把tomcat的组成归纳一下:整个tomcat的组成如下图所示: Tomcat在接收到用户请求时,将会通过以 ...

  2. tomcat源码阅读之载入器(Loader)

    一.Java类的载入器: 双亲委派模型: 1.JVM提供了三种类型的类加载器:引导类载入器(bootstrap class loader).扩展类载入器(extension class loader) ...

  3. tomcat源码阅读

    1      工具准备 需要SVN.Maven.JDK.Eclipse.Eclipse M2插件 2      下载源码及发布包 源码在这里:http://svn.apache.org/repos/a ...

  4. tomcat源码阅读之过滤器

    一.Servlet过滤器: 1.介绍: Servlet过滤器本身并不生成请求和响应对象,它只提供过滤作用. Servlet过滤器能够在Servlet被调用之前检查Request对象,修改Request ...

  5. tomcat源码阅读之SingleThreadModel

    一.接口简介: 实现了SingleThreadModel接口的servlet类只能保证在同一时刻,只有一个线程执行该servlet实例的service方法,在tomcat实现中会创建多个servlet ...

  6. tomcat源码阅读之安全机制

    一.领域(Realm): 1.Principal接口代表角色信息,包含了三个成员:用户名.密码.role列表(以逗号分隔),对应了tomcat-users.xml文件中一行user信息: Generi ...

  7. tomcat源码阅读之BackupManager

    一. 配置: <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOpti ...

  8. tomcat源码阅读之部署器

    我们知道web应用是用Context实例表示的,而Context是部署到Host实例中的,因此tomcat的部署器是关联的Host实例.Context实例可以用WAR文件部署,也可以把整个web应用的 ...

  9. tomcat源码阅读之集群

    一. 配置: 在tomcat目录下的conf/Server.xml配置文件中增加如下配置: <!-- Cluster(集群,族) 节点,如果你要配置tomcat集群,则需要使用此节点. clas ...

随机推荐

  1. UVA-10026 Shoemaker's Problem (贪心)

    题目大意:一个鞋匠,有n只鞋要修,修某只鞋的时间ti已知,某只鞋晚修一天要交的罚款fi也已知.现在让找个修鞋顺序使得罚款最少. 题目分析:本来想水一下这道题,没想到真的AC啦.后来又查的题解,找的解释 ...

  2. 规格化设计-----JSF(第三次博客作业)

    从20世纪60年代开始,就存在着许多不同的形式规格说明语言和软件开发方法.在形式规格说明领域一些最主要的发展过程列举如下: 1969-1972 C.A.R Hoare撰写了"计算机编程的公理 ...

  3. PL/SQL Developer 使用中文条件查询时无数据的解决方法(转)

    原文地址: PL/SQL Developer 使用中文条件查询时无数据的解决方法 PL/SQL Developer 使用中文条件查询时无数据,这是由于字符集的不一致导致的. 执行以下sql命令:sel ...

  4. Import Data from *.xlsx file to DB Table through OAF page(转)

    Use  Poi.jar Import Data from *.xlsx file to DB Table through OAF page Use Jxl.jar Import Data from ...

  5. 简话Angular 06 Angular自定义指令

    一句话: 直接return link函数可以解决大多数问题,无须死扣用法 1. 上源码 (dom操作,事件,css,mode操作全包括了) <h3>Custom directive, wi ...

  6. JS之Fetch

    细节叙述见以下链接:https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch 1 基本概念:  WindowOrWo ...

  7. Delphi IDE 版本

    产品 compiler Version version bds 2007-WIN32 VER 180 185 11 5.0 2009 VER 200 13 6.0 XE VER 220 15 8.0 ...

  8. 如何在ubuntu16上安装docker

    自从用了docker,就一直无法忘怀,省去了很多部署成本.特别是可以统一开发环境和部署环境,在实际开发中有很大的实用价值. 作为一个伪全栈,我是力推大家学习docker技术的.这种共享linux内核的 ...

  9. JavaScript世界的一等公民 - 函数

    简介 在很多传统语言(C/C++/Java/C#等)中,函数都是作为一个二等公民存在,你只能用语言的关键字声明一个函数然后调用它,如果需要把函数作为参数传给另一个函数,或是赋值给一个本地变量,又或是作 ...

  10. C++虚析构函数的作用

    注:本文内容来源于zhice163博文,感谢作者的整理. 1.为什么基类的析构函数是虚函数? 在实现多态时,当用基类操作派生类,在析构时防止只析构基类而不析构派生类的状况发生. 下面转自网络:源地址  ...