tomcat源码阅读之容器(Container)

一、 实现容器的接口是Container接口,Tomcat中共有四种类型的容器:

1、Engine:表示整个Catalina Servlet引擎;

2、Host:表示含有一个或者多个Context容器的虚拟主机,通常一个Engine下含有一个Host;

3、Context:表示一个web应用程序;

4、Wrapper :表示一个独立的Servlet;

二、Container接口的UML图:

三、Container接口:

1、容器管理相关:addChild, removeChild, findChild等等;

Container是有层级关系的,Engine下有一个或者多个Host ,一个Host下有一个或者多个Context,一个Context下有一个或者多个Wrapper;这些都可以通过容器管理相关方法来管理,Wrapper是最底层的容器,无法再包含自容器了;

2、支持的其他一些组件:Loader, Logger, Manager, Cluster,Realm, ParentClassLoader, DirContext, Mapper等,支持这些的方法更像是一个实体类,提供了对应的Get和 Set方法;

3、Container接口提供了一个最重要的方法invoke,Container接口示例会传递给Connector连接器,连接器处理用户请求并解析生成Request和Response对象后,会调用Container容器的invoke方法;

四、Container.Invoke的调用流程:

1、这里的Container接口实现使用的是Context,Connect.invoke方法调用就传递给Context.invoke;

2、Context.invoke传递给pipeline.invoke,然后pipeline.invoke方法会借助ValveContext来循环调用Valves数组中的Valve,Valves数组调用完成后就会调用BasicValve(这种循环调用是用过InvokeNext方法实现的),不管是Valves数组还是BasicValve都是valve接口的实现;

3、Valve的Invoke方法会调用Context.map方法,map方法中先根据request请求字符串调用findMapper方法返回对应协议的mapper,然后调用对应mapper.map方法;

4、Mapper的map方法实现首先从Context中根据request请求字符串查找到对应的Wrapper(也即对应的servlet实例),然后由对应的Wrapper去处理用户请求;

请求转到每个Servlet对应的Wrapper后,其调用流程如下:

每个Container的实现都含有一个PipeLine对象,于是Container的invoke实现就传递给PipeLine的invoke方法,pipeLine对象含有一个BasicValve和Valves列表,PipeLine会首先循环调用valves列表中的valve,最后再调用Basic Valve;在Basic Valve的invoke方法中传递进了Request和Response对象,然后调用对应Servlet;

在BasicValve.invoke方法中,首先会根据servletClass生成servlet实例并初始化,然后调用其service方法来完成servlet方法的调用;

五、UML 图:

1、Wrapper接口的实现类StandardWrapper继承自ContainerBase类,也就是实现了Container接口,StandardWrapper类是Container接口的最小实现单位。StandardWrapper类继承了ContainwrBase类的两个重要方法invoke和map,Connector的invoke方法会调用此处的invoke,map方法会根据请求URL(Request对象)查找映射器,然后由映射器将请求传给对应的子容器处理;

2、StandardWrapper类的allocate调用LoadServlet加载Servlet,unload会卸载servlet,也即调用servlet.Destroy方法;同时StandardWrapper作为Container接口的实现,也包含了pipeLine接口的实现类StandardPipeLine;

3、PipeLine包含了多个Valve和一个BasicValve,StandardWrapperValve作为BasicValve,其invoke方法调用时首先加载servlet并调用,然后根据配置文件中给该servlet配置的过滤器链创建ApplicationFilterChain,最后调用过滤器链中的过滤器;

4、FilterDef对应了一个配置文件中配置的一个过滤器,包含了filterName, DisplayName, Description, parameters, SmallIcon等信息,ApplicationFilterConfig对应了一个过滤器,他能根据filterClass加载出对应的过滤器Filter并初始化。ApplicationFilterChain根据filterMaps数组中的配置加载出过滤器链表;

5、Mapper定义了映射器接口,StandardContextMapper、StandardEngineMapper、StandardHostMapper类实现了Mapper(Wrapper是最小的Container单位,对应一个具体的servlet,因此其不需要映射器实现类),map方法实现了根据Request查找到对应处理这个请求的子容器对象;

6、Context对应一个web应用;

其中管理子容器的变量是一个hash表:

在addChild方式时,会将child.getName作为Key,child对象作为value存入hash表:

servletMappings变量存储了servletName和请求路径的映射关系,也是一个hash表:

其中的数据存储是以servletName和请求路径为映射关系存储的:

这样方便根据请求地址能很快查找到servletName,然后根据servletName能很快查找到对应的Wrapper(Context的map方法就是这样实现的);

时间: 2024-10-07 15:00:55

tomcat源码阅读之容器(Container)的相关文章

Tomcat源码阅读(二)初始化

近来,我开始阅读tomcat的源码,感觉还挺清晰易懂:为了方便理解,我参考了网上的一些文章,把tomcat的组成归纳一下:整个tomcat的组成如下图所示: Tomcat在接收到用户请求时,将会通过以上组件的协作来给最终用户产生响应.首先是最外层的Server和Service来提供整个运行环境的基础设施,而Connector通过指定的协议和接口来监听用户的请求,在对请求进行必要的处理和解析后将请求的内容传递给对应的容器,经过容器一层层的处理后,生成最终的响应信息,返回给客户端. Tomcat的容

Tomcat源码分析之—容器整体结构

Tomcat有多个容器组成,而Container也就是容器与Connecter连接器是Tomcat最核心的两个模块,Connecter连接器接收客户端的请求,并根据客户端的请求传递给Container处理并作出相应. Tomcat中有多个层次的容器对象:Engine.Host.Context.Wrapper,这些容器是有层级关系的. Engine:代表整个Tomcat的Servlet引擎,可以包含一个或多个子容器 Host:    表示一个虚拟主机,包含多个Context Context :表示

tomcat源码解读(2)–容器责任链模式的实现

责任链模式:责任链模式可以用在这样的场景,当一个request过来的时候,需要对这个request做一系列的加工,使用责任链模式可以使每个加工组件化,减少耦合.也可以使用在当一个request过来的时候,需要找到合适的加工方式.当一个加工方式不适合这个request的时候,传递到下一个加工方法,该加工方式再尝试对request加工. 在tomcat中容器之间的调用使用的就是责任链的设计模式,当一个请求过来的时候首先是engine容器接受请求,然后engine容器会把请求传到host容器,host

Tomcat源码阅读#1:classloader初始化

Bootstrap 通过Tomcat的启动脚本可以看到启动的入口是在Bootstrap,来看下Bootstrap的main方法, /** * Main method and entry point when starting Tomcat via the provided * scripts. * * @param args Command line arguments to be processed */ public static void main(String args[]) { if

tomcat源码阅读之生命周期(LifeCycle)

一.事件机制流程: 1.     当外部事件源发生事件(比如点击了按钮,数据发生改变更新等)时,事件源将事件封装成事件对象Event: 2.     将事件对象交由对应的事件派发器Dispatcher进行派发(将Event对象传递给事件派发器.事件派发器中存储了一个事件监听器列表,需要提前将监听器注册到派发器的),事件派发器会循环遍历监听器列表,将事件对象派发给监听器: 3.     监听器接收到派发器派发过来的事件对象Event后,从Event中取出事件信息并进行响应: 二.相关接口: 1.L

tomcat源码阅读之日志记录器(Logger)

UML图: 1.Logger接口中定义了日志的级别:FATAL.ERROR.WARNING.INFORMATION.DEBUG,通过接口函数getVerbosity获取日志级别,setVerbosity设置日志级别: 2.接口中提供一组重载的log方法来记录日志,在LoggerBase实现类中除了log(String msg)方法没有实现外,其他重载的log方法均实现为调用这个方法来实现日志的记录: 3.在LoggerBase类中,默认的日志级别是ERROR:带日志级别参数的log方法在记录日志

如何阅读Java源码 阅读java的真实体会

刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 说到技术基础,我打个比方吧,如果你从来没有学过Java,或是任何一门编程语言如C++,一开始去啃<Core Java>,你是很难从中吸收到营养的,特别是<深入Java虚拟机>这类书,别人觉得好,未必适合现在的你. 虽然Tomcat的源码很漂亮,但我绝不建议你一开始就读它.我文中会专门谈到这个,暂时不展开. 强烈

Java源码阅读的真实体会

原文:http://zwchen.iteye.com/blog/1154193 刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 说到技术基础,我打个比方吧,如果你从来没有学过Java,或是任何一门编程语言如C++,一开始去啃<Core Java>,你是很难从中吸收到营养的,特别是<深入Java虚拟机>这类书,别人觉得好,未必适合现在的你. 虽然Tomcat的

[收藏] Java源码阅读的真实体会

收藏自http://www.iteye.com/topic/1113732 刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 说到技术基础,我打个比方吧,如果你从来没有学过Java,或是任何一门编程语言如C++,一开始去啃<Core Java>,你是很难从中吸收到营养的,特别是<深入Java虚拟机>这类书,别人觉得好,未必适合现在的你. 虽然Tomcat的源码