1.责任链模式
- 请求被Connector组件接收,创建Request和Response对象。
- Connector将Request和Response交给Container,先通过Engine的 pipeline组件流经内部的每个Valve。
- 请求流转到Host的pipeline组件中,并且经过内部Valve的过滤。
- 请求流转到Context的pipeline组件中,并且经过内部的Valve的过滤。
- 请求流转到Wrapper的pipeline组件中,并且经过内部的Valve的过滤。
- Wrapper内部的WrapperValve创建FilterChain实例,调用指定的 Servlet实例处理请求。
- 返回
2.pipeline valve机制
这整个层层递进的调用过程使用的是Pipeline-Value管道。
- 责任链模式
- 在请求处理过程中有很多处理者依次对请求进行处理,每个处理着负责做自己的相应的处理,然后一个个传递给下一个处理者
2.1 Valve
Valve:阀门,可以把它理解成请求拦截器,在 tomcat 接收到网络请求与触发 Servlet 之间执行;生产线(pipeline)可以配置阀门的位置。一个pipeline包含多个Valve,这些阀共分为两类
- 基础阀(通过getBasic、setBasic方法调用)
- StandardEngineValve:StandardEngine中的唯一阀门,主要用于从request中选择其host映射的Host容器StandardHost。
- StandardHostValve:StandardHost中最后的阀门,主要用于从request中选择其context映射的Context容器StandardContext以及访问request中的Session以更新会话的最后访问时间。
- StandardContextValve:StandardContext中的唯一阀门,主要作用是禁止任何对WEB-INF或META-INF目录下资源的重定向访问,对应用程序热部署功能的实现,从request中获得StandardWrapper
- StandardWrapperValve:StandardWrapper中的唯一阀门,主要作用包括调用StandardWrapper的loadServlet方法生成Servlet实例和调用ApplicationFilterFactory生成Filter链。
- 普通阀(通过addValve、removeValve调用)
- AccessLogValve:记录请求日志,默认会开启
- RemoteAddrValve:可以做访问控制,比如限制IP黑白名单
- RemoteIpValve:主要用于处理 X-Forwarded-For 请求头,用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段
public interface Valve {
// 类似链表结构
public Valve getNext();
public void setNext(Valve valve);
// 重点,Request、Response分别是HttpServletRequest、HttpServletResponse的实现类
public void invoke(Request request, Response response)
// 是否支持异步
public boolean isAsyncSupported();
}
2.2 Pipeline
Pipeline:管道,每个Container都包含一个Pipeline;接口标准实现:org.apache.catalina.core.StandardPipeline
-
管道都是包含在容器中,所以有getContainer和setContainer方法。
-
Pipelin中维护了Valve的链表,整个调用链的执行是被valve来完成的,一个管道一般有一个基础阀(通过setBasic添加),可以有0到多个普通阀(通过addValve添加);valve完成自己的处理以后,就会调用getNext.invoke来触发下一个Valve调用
-
不同的容器的pipeline之间的触发,上一层的最后一个valve负责调用下一层的第一个valve
-
Wrapper容器的最后一个Valve会创建一个Filter链,并调用doFilter方法,最终会调用Servlet的service方法。
Valve和Filter
- valve是tomcat的私有机制
- Filter是在servlet级别的,是公有标准
- valve工作在web容器级别,拦截所有应用的请求
- Servlet Filter工作在应用级别,只能拦截某个Web应用的所有请求。
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();
public boolean isAsyncSupported();
public Container getContainer();
public void setContainer(Container container);
public void findNonAsyncValves(Set<String> result);
}
文章的最后附一个参考链接…