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. hdu多校2C

    题意:找多条路径覆盖所有的边,求最小路径数,要求输出路径 题解:新建一个点n+1,所有奇点向它连边,然后跑欧拉回路,最后把新加的边删去,一段连续的边就是一条路径 = =但是由于太久没写欧拉回路以及之前 ...

  2. ps -ef |grep xxx 输出的具体含义

    ps:将某个进程显示出来 -A 显示所有程序. -e 此参数的效果和指定"A"参数相同. -f 显示UID,PPIP,C与STIME栏位. grep命令是查找 中间的|是管道命令 ...

  3. iOS开发-开发文档安装

    iOS开发肯定离不开开发文档,苹果有在线帮助文档,xCode其实可以下载模拟器文档和iOS8.1文档的,不过下载的速度实在不敢恭维,而且比较头疼的是不显示下载进度条的,苹果的开发文档都是放在)/应用程 ...

  4. spark streaming 入门例子

    spark streaming 入门例子: spark shell import org.apache.spark._ import org.apache.spark.streaming._ sc.g ...

  5. chrome 扩展插件提示

    --force-fieldtrials=ExtensionDeveloperModeWarning/None/ ogfahjpoemnbbnlignjbfinfnahmfdlk ahjaciijnoi ...

  6. BZOJ1342 [Baltic2007]Sound静音问题

    越来越水了... 这道题是简单的单调队列,同时维护最大值和最小值即可. 另解:multiset大法求区间最大最小,但是复杂度会上升... /****************************** ...

  7. 获取URL的数据

    <!doctype html><html><head><meta charset="utf-8"><meta name=&qu ...

  8. js弹窗那些事

    <!doctype html> <html> <head> <meta charset="utf-8"> <meta name ...

  9. Hive时间函数笔记

    unix_timestamp()函数: 返回值: bigint说明: 获得当前时区的UNIX时间戳 举例: hive> select unix_timestamp() from dual; 14 ...

  10. pymysql 单独获取表的栏位名称

    有时需要获取表的栏位+数值,请参考 https://www.cnblogs.com/xibuhaohao/p/9996571.html 有时只需要栏位名称,那么可以使用 col=self.cursor ...