zoukankan      html  css  js  c++  java
  • tomcat源码阅读之StandardContext

    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子上下文;

  • 相关阅读:
    Python_装饰器复习_30
    Python_每日习题_0002_个税计算
    linux-文件流4种读取方式
    Max Sum Plus Plus
    棋盘问题
    noip数学
    P3384 【模板】树链剖分
    P2419 [USACO08JAN]牛大赛Cow Contest
    poj3159 Candies(差分约束)
    小K的农场(差分约束)
  • 原文地址:https://www.cnblogs.com/laoxia/p/8056749.html
Copyright © 2011-2022 走看看