《看透springMVC源码》之Container分析

来源:互联网 发布:免费的主题软件 编辑:程序博客网 时间:2024/06/05 10:26

ContainerBase的结构

Container是Tomcat中容器的接口,通常使用的Servlet就封装在其子接口Wrapper中。Container一共有4个子接口Engine、Host、Context、Wrapper和一个默认实现类ContainerBase,每个子接口都是一个容器,这4个容器都有一个对应的StandardXXX实现类,并且这些实现类都继承ContainerBase类。另外Container还继承Lifecycle接口,而且ContainerBase间接继承LifecycleBase,所以Engine、Hose、Context、Wrapper 4个子容器都符合前面讲过的tomcat生命周期管理模式。

这里写图片描述

Container的4个子容器

Container的子容器Engine、Host、Context、Wrapper是逐层包含的关系,其中Engine是最顶层,每个service最多只能有一个Engine,Engine里面可以有多个Host,每个Host下可以有多个Context,每个Conext下可以有多个Wrapper:
这里写图片描述

4个容器的作用分别是:

  • Engine:引擎,用来管理多个站点,一个Service最多只能有一个Engine。
  • Host:代表一个站点,也可以叫虚拟主机,通过配置Host就可以添加站点、
  • Context:代表一个应用程序,对应着平时开发的一套程序,或者一个WEN-INF目录以及下面的web.xml文件。
  • Wrapper:每个Wrapper封装着一个Servlet。

Context和host的区别是Context表示一个应用,比如,默认配置下webapps下的每个目录都是一个应用,其中ROOT目录中存放着主应用,其他目录存放这别的子应用,而整个webapps是一个站点。假如www.excelib.com域名对应着webapps目录所代表的站点,其中的ROOT目录里的应用就是主应用,访问时直接使用域名访问就可以,而webapps/test目录存放的是test子应用,访问时需要用www.excelib.com/test,每一个应用对应一个Context,所有webapps下的应用都属于www.excelib.com站点,而blog.excelib.com则是另外一个站点,属于另外一个Host。

4种容器的配置方法

这里写图片描述

这里首先定义了一个Server,在8005端口监听关闭命令“SHUTDOWN”;Server里定义了一个名为Catalina的Service;Service里定义了两个Connector,一个是HTTP协议,一个是AJP协议,AJP主要用于集成(如与Apache集成);Service里还定义了一个名为Catalina的Engine;Engine里定义了一个名为localhost的Host。
Engine在定义的时候有个defaultHost属性,它表示接收到请求的域名如果在所有的Host的name和Alias中都找不到时使用的默认Host。

Context有三种配置方法:
1. 通过文件配置;
2. 将WAR应用直接放到Host目录下,Tomcat会自动查找并添加到Host中;
3. 将应用的文件放到Host目录下,tomcat也会自动查找并添加到Host中。

Context通过文件配置的方式一共有5个位置可以配置:

  • conf/server.xml文件中的Context标签。
  • conf/[enginename]/[hostname]/目录下以应用命名的xml文件。
  • 应用自己的/META-INF/context.xml文件。
  • conf/context.xml文件。
  • conf/[enginename]/[hostname]/context.xml.default文件。

其中前三个位置用于配置单独的应用,后两个配置的Context是共享的,conf/context.xml文件中配置的内容在整个Tomcat中共享,第五种的内容在对应的站点(Host)中共享。另外,因为conf/servver.xml文件只有在Tomcat重启的时候才会重新加载,所以第一种配置方法不推荐使用。
Wrapper的配置就是我们在wen.xml中配置的Servlet,一个Servlet对一个Wrapper。另外也可以在conf/web.xml文件中配置全局的Wrapper,处理Jsp的JspServlet就配置在这里,所以不需要自己配置Jsp就可以处理Jsp请求了。
同一个Service下的所有站点由于是共享Connector,所以监听的端口都一样。如果想要监听不同端口的站点,可以通过不同的Service来配置,Service也是在conf/server.xml文件中配置的。

Container的启动

Container的启动是通过init和start方法来完成的,在前面分析过这两个方法会在Tomcat启动时被Service调用。Contianer也是按照Tomcat的生命周期来管理的,init和start方法也会调用initInternal和startInternal方法来具体处理,不过Container和前面讲的Tomcat整体结构启动的过程稍微有点不一样,主要有三点区别:
1. Container的4个子容器有一个共同的父类ContainerBase,这里定义了Container容器的initInternal和startInternal方法通用处理内容,具体容器还可以添加自己的内容;
2. 除了最顶层容器的init是被Service调用的,子容器的init方法并不是在容器中逐层循环调用的,而是在执行start方法的时候通过状态判断还没有初始化才会调用;
3. start方法除了在父容器的startInternal方法中调用,还会在父容器的添加子容器的addStart方法中调用,这主要是因为Context和Wrapper是动态添加的,我们在站点目录下放一个应用的文件夹或者war包就可以添加一个Context,在web.xml文件中配置一个Servlet就可以添加一Wrapper,所以Context和Wrapper在容器启动的过程中才动态查找出添加到相应的父容器中的。

Pipeline-Value管道

Container处理请求是使用Pipeline-Value管道来处理的。
Pipeline-Value是责任链模式,责任链模式是指在一个请求处理的过程中有多个处理者依次对请求进行处理,每个处理者负责做自己相应的处理,处理完成后将处理后的请求返回,再让下一个处理者继续处理。
不过Pipeline-Value的管道模型和普通的责任链模式稍微有点不同,区别主要有两点:
1. 每个Pipeline都有特定的Value,而且是在管道的最后一个执行,这个Value叫BaseValue,BaseValue是不可删除的;
2. 在上层容器的管道的BaseValue中会调用下层容器的管道。

这里写图片描述

阅读全文
0 0
原创粉丝点击