tomcat架构分析(valve机制)
2016-04-13 17:23
441 查看
出处:http://gearever.iteye.com
关于tomcat的内部逻辑单元的存储空间已经在相关容器类的blog里阐述了。在每个容器对象里面都有一个pipeline及valve模块。它们是容器类必须具有的模块。在容器对象生成时自动产生。Pipeline就像是每个容器的逻辑总线。在pipeline上按照配置的顺序,加载各个valve。通过pipeline完成各个valve之间的调用,各个valve实现具体的应用逻辑。
先看一下pipeline及valve的逻辑概念图。
这些valve就是在tomcat的server.xml中配置,只要满足一定条件,继承ValveBase基类
引用
org.apache.catalina.valves.ValveBase
就可以在不同的容器中配置,然后在消息流中被逐一调用。每个容器的valve的作用域不一样,在总体结构中已有说明。这里红色标记的是配置的自定义的valve,这样可以扩展成多个其他应用,例如cluster应用等。
Tomcat实现
Tomcat提供了Pipeline的标准实现:
引用
org.apache.catalina.core.StandardPipeline
四大容器类StandardEngine,StandardHost,StandardContext及StandardWrapper都有各自缺省的标准valve实现。它们分别是
Engine:org.apache.catalina.core.StandardEngineValve
Host: org.apache.catalina.core.StandardHostValve
Context:org.apache.catalina.core.StandardContextValve
Wrapper:org.apache.catalina.core.StandardWrapperValve
容器类生成对象时,都会生成一个pipeline对象,同时,生成一个缺省的valve实现,并将这个标准的valve对象绑定在其pipeline对象上。以StandardHost类为例:
Java代码
public class StandardHost extends ContainerBase implements Host {
protected Pipeline pipeline = new StandardPipeline(this);
public StandardHost() {
super();
pipeline.setBasic(new StandardHostValve());
}
}
Valve实现了具体业务逻辑单元。可以定制化valve(实现特定接口),然后配置在server.xml里。每层容器都可以配置相应的valve,当只在其作用域内有效。例如engine容器里的valve只对其包含的所有host里的应用有效。定制化的valve是可选的,但是每个容器有一个缺省的valve,例如engine的StandardEngineValve,是在StandardEngine里自带的,它主要实现了对其子host对象的StandardHostValve的调用,以此类推。
配置的例子有:
Xml代码
<Engine name="Catalina" defaultHost="localhost">
<Valve className="MyValve0"/>
<Valve className="MyValve1"/>
<Valve className="MyValve2"/>
……
<Host name="localhost" appBase="webapps">
</Host>
</Engine>
当在server.xml文件中配置了一个定制化valve时,会调用pipeline对象的addValve方法,将valve以链表方式组织起来,看一下代码;
Java代码
public class StandardPipeline implements Pipeline, Contained, Lifecycle{
protected Valve first = null;
public void addValve(Valve valve) {
// Validate that we can add this Valve
if (valve instanceof Contained)
((Contained) valve).setContainer(this.container);
// Start the new component if necessary
if (started) {
if (valve instanceof Lifecycle) {
try {
((Lifecycle) valve).start();
} catch (LifecycleException e) {
log.error("StandardPipeline.addValve: start: ", e);
}
}
// Register the newly added valve
registerValve(valve);
}
// 将配置的valve添加到链表中,并且每个容器的标准valve在链表的尾端
if (first == null) {
first = valve;
valve.setNext(basic);
} else {
Valve current = first;
while (current != null) {
if (current.getNext() == basic) {
current.setNext(valve);
valve.setNext(basic);
break;
}
current = current.getNext();
}
}
}
}
从上面可以清楚的看出,valve按照容器作用域的配置顺序来组织valve,每个valve都设置了指向下一个valve的next引用。同时,每个容器缺省的标准valve都存在于valve链表尾端,这就意味着,在每个pipeline中,缺省的标准valve都是按顺序,最后被调用。
消息流
先看一下四大容器的标准valve的调用逻辑图。从中可以梳理出标准valve的逻辑。注意此图只是在缺省配置下的状态,也就是说每个pipeline只包含一个标准valve的情况。
图中显示的是各个容器默认的valve之间的实际调用情况。从StandardEngineValve开始,一直到StandardWrapperValve,完成整个消息处理过程。注意每一个上层的valve都是在调用下一层的valve返回后再返回的,这样每个上层valve不仅具有request对象,同时还能拿到response对象,想象一下,这样是不是可以批量的做很多东西?
关于tomcat的内部逻辑单元的存储空间已经在相关容器类的blog里阐述了。在每个容器对象里面都有一个pipeline及valve模块。它们是容器类必须具有的模块。在容器对象生成时自动产生。Pipeline就像是每个容器的逻辑总线。在pipeline上按照配置的顺序,加载各个valve。通过pipeline完成各个valve之间的调用,各个valve实现具体的应用逻辑。
先看一下pipeline及valve的逻辑概念图。
这些valve就是在tomcat的server.xml中配置,只要满足一定条件,继承ValveBase基类
引用
org.apache.catalina.valves.ValveBase
就可以在不同的容器中配置,然后在消息流中被逐一调用。每个容器的valve的作用域不一样,在总体结构中已有说明。这里红色标记的是配置的自定义的valve,这样可以扩展成多个其他应用,例如cluster应用等。
Tomcat实现
Tomcat提供了Pipeline的标准实现:
引用
org.apache.catalina.core.StandardPipeline
四大容器类StandardEngine,StandardHost,StandardContext及StandardWrapper都有各自缺省的标准valve实现。它们分别是
Engine:org.apache.catalina.core.StandardEngineValve
Host: org.apache.catalina.core.StandardHostValve
Context:org.apache.catalina.core.StandardContextValve
Wrapper:org.apache.catalina.core.StandardWrapperValve
容器类生成对象时,都会生成一个pipeline对象,同时,生成一个缺省的valve实现,并将这个标准的valve对象绑定在其pipeline对象上。以StandardHost类为例:
Java代码
public class StandardHost extends ContainerBase implements Host {
protected Pipeline pipeline = new StandardPipeline(this);
public StandardHost() {
super();
pipeline.setBasic(new StandardHostValve());
}
}
Valve实现了具体业务逻辑单元。可以定制化valve(实现特定接口),然后配置在server.xml里。每层容器都可以配置相应的valve,当只在其作用域内有效。例如engine容器里的valve只对其包含的所有host里的应用有效。定制化的valve是可选的,但是每个容器有一个缺省的valve,例如engine的StandardEngineValve,是在StandardEngine里自带的,它主要实现了对其子host对象的StandardHostValve的调用,以此类推。
配置的例子有:
Xml代码
<Engine name="Catalina" defaultHost="localhost">
<Valve className="MyValve0"/>
<Valve className="MyValve1"/>
<Valve className="MyValve2"/>
……
<Host name="localhost" appBase="webapps">
</Host>
</Engine>
当在server.xml文件中配置了一个定制化valve时,会调用pipeline对象的addValve方法,将valve以链表方式组织起来,看一下代码;
Java代码
public class StandardPipeline implements Pipeline, Contained, Lifecycle{
protected Valve first = null;
public void addValve(Valve valve) {
// Validate that we can add this Valve
if (valve instanceof Contained)
((Contained) valve).setContainer(this.container);
// Start the new component if necessary
if (started) {
if (valve instanceof Lifecycle) {
try {
((Lifecycle) valve).start();
} catch (LifecycleException e) {
log.error("StandardPipeline.addValve: start: ", e);
}
}
// Register the newly added valve
registerValve(valve);
}
// 将配置的valve添加到链表中,并且每个容器的标准valve在链表的尾端
if (first == null) {
first = valve;
valve.setNext(basic);
} else {
Valve current = first;
while (current != null) {
if (current.getNext() == basic) {
current.setNext(valve);
valve.setNext(basic);
break;
}
current = current.getNext();
}
}
}
}
从上面可以清楚的看出,valve按照容器作用域的配置顺序来组织valve,每个valve都设置了指向下一个valve的next引用。同时,每个容器缺省的标准valve都存在于valve链表尾端,这就意味着,在每个pipeline中,缺省的标准valve都是按顺序,最后被调用。
消息流
先看一下四大容器的标准valve的调用逻辑图。从中可以梳理出标准valve的逻辑。注意此图只是在缺省配置下的状态,也就是说每个pipeline只包含一个标准valve的情况。
图中显示的是各个容器默认的valve之间的实际调用情况。从StandardEngineValve开始,一直到StandardWrapperValve,完成整个消息处理过程。注意每一个上层的valve都是在调用下一层的valve返回后再返回的,这样每个上层valve不仅具有request对象,同时还能拿到response对象,想象一下,这样是不是可以批量的做很多东西?
相关文章推荐
- tomcat部署项目的各种方式
- Ubuntu 配置 Tomcat
- 关于tomcat优化记录与思路
- maven project 部署到tomcat时项目部署不上去
- Servlet和Tomcat部署
- Mac 安装Tomcat
- 使用JMX监控Tomcat
- Tomcat重启负载高问题定位
- 启动Tomcat出现Using CATALINA_BASE
- Apache与Tomcat联系及区别
- maven tomcat1.7环境下构建javaweb 项目
- Tomcat7插件+overlays不能热部署调试如何解
- nginx + tomcat 配置,静态资源直接使用nginx
- 配置tomcat
- java.lang.UnsatisfiedLinkError: D:\Tomcat\apache-tomcat-7.0.37\bin\tcnative-1.dll: Can't load AMD 6
- cmd正常启动tomcat,而 从eclipse启动出现 404
- tomcat Server Locations 不可用 两种解决方式
- TOMCAT开放远程调试端口
- java.lang.IllegalArgumentException: Document base D:\apache-tomcat-7.0.61\webapps\xxxx does no
- tomcat和java历史版本下载