Tomcat设计模式-责任链模式(二)pipeline valve
在tomcat中责任链模式还有一个非常典型的应用:http消息在container之间的传递。具体过程在文章Tomcat源码分析HTTP消息处理(从connector到servlet)中已经详细分析过,本文着重分析容器间管道和阀门的实现。Tomcat源码分析HTTP消息处理(从connector到servlet)中提到,消息传递过程中每个容器内都会有这样一样代码:xxxx. getPi
在tomcat中责任链模式还有一个非常典型的应用:http消息在container之间的传递。
具体过程在文章Tomcat源码分析HTTP消息处理(从connector到servlet)中已经详细分析过,本文着重分析容器间管道和阀门的实现。
Tomcat源码分析HTTP消息处理(从connector到servlet)中提到,消息传递过程中每个容器内都会有这样一样代码:
xxxx. getPipeline().getFirst().invoke(request, response);
这里就是通过管道对阀的调用。下面分析阀是怎么加入到管道并连接起来的。这里举例分析Host容器,其他容器过程与Host相同。
1. 为容器加入管道
在容器的基类ContainerBase 中用成员变量
protected Pipeline pipeline =
CatalinaFactory.getFactory().createPipeline(this);
public class CatalinaFactory {
private static CatalinaFactory factory = new CatalinaFactory();
public static CatalinaFactory getFactory() {
return factory;
}
private CatalinaFactory() {
// Hide the default constructor
}
public String getDefaultPipelineClassName() {
return StandardPipeline.class.getName();
}
public Pipeline createPipeline(Container container) {
Pipeline pipeline = new StandardPipeline();
pipeline.setContainer(container);
return pipeline;
}
}
由此,每个容器都有一个StandardPipeline类型的pipeline。
2. 为pipeline设置基本的阀门
public StandardHost() {
super();
pipeline.setBasic(new StandardHostValve());
}
在basicValve的invoke中会调用下一个容器。
3. 增加阀门
getPipeline().addValve(valve);
在 StandardPipeline 中会保存 first 和 basic 两个阀门,新加阀门会增加到 basic 之前。 valve 本身是一个单向链表,会保存 next。
// Add this Valve to the set associated with this Pipeline
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();
}
}
通过2,3两步,pipeline中增加了一个从first到basic的valve列表。
4. 阀门的调用
在valve的基类ValveBase中有虚方法
publicabstractvoid invoke(Requestrequest, Response response)
throws IOException,ServletException;
每个子类都会实现这个方法,这里面完成需要的valve逻辑。这里作为basicValve在invoke中会调用下一个容器。其他容器都必须调用getNext().invoke(request,response);除非想特意让pipeline中断,转到你需要的容器中。
5. 加入第三方valve
可以通过继承ValveBase或者org.apache.catalina.valves中的类实现自己的valve。这里要特别注意,如果不想改变消息的传递方向的话,在实现invoke方法时一定要加入getNext().invoke(request,response)。
还需要在server.xml中给容器增加valve配置,如:
<Engine defaultHost="localhost" name="Catalina">
<Valve className="org.apache.catalina.valves.RequestDumperValve"/>
………
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true"
xmlNamespaceAware="false" xmlValidation="false">
<Valve className="org.apache.catalina.valves.FastCommonAccessLogValve"
directory="logs" prefix="localhost_access_log." suffix=".txt"
pattern="common" resolveHosts="false"/>
…………
</Host>
</Engine>
以上,pipeline-valve的原理和增加方法就分析完了。通过pipeline-valve,tomcat的使用者不仅可以完成消息过滤,还可以改变消息的流向。在不改变tomcat原来逻辑的情况下实现扩展tomcat。
更多推荐
所有评论(0)