一、管道存在意义
认为管道是连接Connector与Servlet的关键组件,我们可以把管道想象成一个流水线,每个容器都持有一个子流水线,整个调用流程如图:
可以看到,连接器处理好数据到调用Servlet的service,经过了哪些容器的管道,这些管道组装在一起,仿佛就是一个大管道直接连通connector与Servlet。
继续看看每个容器管道是怎么进来怎么出去的。
先看下管道接口的结构
public interface Pipeline {
public Valve getBasic();
public void setBasic(Valve valve);
public void addValve(Valve valve);
public Valve[] getValves();
public void removeValve(Valve valve);
public Valve getFirst();
}
这里面使用到一个组件阀Valve,我们来看看Valve
public interface Valve {
public String getInfo();
public Valve getNext();
public void setNext(Valve valve);
public void backgroundProcess();
public void invoke(Request request, Response response) throws IOException, ServletException;
public void event(Request request, Response response, CometEvent event) throws IOException, ServletException;
}
每个管道都有一个基础阀,看一下管道的调用方式和阀的使用方式
pipeline.getFirst().invoke(request,response);
void invoke(request, response){
getNext().invoke(request,response);
// 该阀需要处理的工作
}
我们可以大致知道,pipeline管道使用了责任链的模式,解耦了请求与处理逻辑,可灵活增加业务逻辑对现有代码没有侵入。
而pipeline就是管理着有着前后关系的Valve。
我们可以看下StandardPipeline类的addValve与getFirst()
public void addValve(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();
}
}
}
public Valve getFirst() {
if (first != null) {
return first;
} else {
return basic;
}
}
从上面代码我们可以看出,pipeline维持一个调用链,每个管道至少有一个基础阀。
使用了这种模式,我们可以做到每个阀的职责单一,可灵活添加业务。
至此我们对管道有了大概的认识
1、管道负责容器的串联
2、负责解耦容器的请求和调用