对于tomcat的过滤器,大家应该都不陌生,每当一个http请求到达的时候,都会经过过滤器,我们知道过滤器会优先于servlet执行,而我们使用的时候只是在web.xml文件中配置了一个filter标签,那他到底在tomcat中是个什么东西呢。今天不妨就来了解一下
最后附上源码,供大家参考:
(1)bootstrap类的启动设置:
<span style="white-space:pre"> </span>HttpConnector connector = new HttpConnector();
<span style="background-color: rgb(102, 255, 255);">Wrapper wrapper = new SimpleWrapper();</span>
wrapper.setServletClass("ModernServlet");
Loader loader = new SimpleLoader();
Valve valve1 = new HeaderLoggerValve(); ---这就相当于一个过滤器
Valve valve2 = new ClientIPLoggerValve();
wrapper.setLoader(loader);
((Pipeline) wrapper).addValve(valve1);
((Pipeline) wrapper).addValve(valve2);
connector.setContainer(wrapper);
(2)addValue()方法,最后是将value添加在了Value的对象数组里。具体的代码参考如下
这是在bootstrap中的SimpleWrapper 中的,见下:
<span style="white-space:pre"> </span>public synchronized void addValve(Valve valve) {
pipeline.addValve(valve);
<span style="white-space:pre"> </span>}
是通过调用pipeline的addValue()方法实现的添加。接下来我们在仔细看看pipline这个类SimplePipeline:
import java.io.IOException;
import javax.servlet.ServletException;
import org.apache.catalina.Contained;
import org.apache.catalina.Container;
import org.apache.catalina.Pipeline;
import org.apache.catalina.Request;
import org.apache.catalina.Response;
import org.apache.catalina.Valve;
import org.apache.catalina.ValveContext;
public class SimplePipeline implements Pipeline {
public SimplePipeline(Container container) {
setContainer(container);
}
// The basic Valve (if any) associated with this Pipeline.
protected Valve basic = null;
// The Container with which this Pipeline is associated.
protected Container container = null;
// the array of Valves
protected Valve valves[] = new Valve[0];
public void setContainer(Container container) {
this.container = container;
}
public Valve getBasic() {
return basic;
}
public void setBasic(Valve valve) {
this.basic = valve;
((Contained) valve).setContainer(container);
}
public void addValve(Valve valve) {
if (valve instanceof Contained)
((Contained) valve).setContainer(this.container);
synchronized (valves) {
Valve results[] = new Valve[valves.length + 1];
System.arraycopy(valves, 0, results, 0, valves.length);
results[valves.length] = valve;
valves = results;
}
}
public Valve[] getValves() {
return valves;
}
public void invoke(Request request, Response response) throws IOException,
ServletException {
// Invoke the first Valve in this pipeline for this request
(new SimplePipelineValveContext()).invokeNext(request, response);
}
public void removeValve(Valve valve) {
}
// this class is copied from org.apache.catalina.core.StandardPipeline
// class's
// StandardPipelineValveContext inner class.
protected class SimplePipelineValveContext implements ValveContext {
protected int stage = 0;
public String getInfo() {
return null;
}
public void invokeNext(Request request, Response response)
throws IOException, ServletException {
int subscript = stage;
stage = stage + 1;
// Invoke the requested Valve for the current request thread
if (subscript < valves.length) {
valves[subscript].invoke(request, response, this);
} else if ((subscript == valves.length) && (basic != null)) {
basic.invoke(request, response, this);
} else {
throw new ServletException("No valve");
}
}
} // end of inner class
}
过滤的链就是在这个类中形成的哦
在SimplePipeline中,addValue()方法是将前面提到的filter添加到了Value的对象数组中,在其内部类中SimplepipelineContext中,invokeNext()则实现了过滤链的迭代调用,当然了,这个迭代调用是从创建HttpProcessor中开始的:
connector.getContainer().invoke(request, response);
因为在bootstrap中已经设置了
connector.setContainer(wrapper);
所以在就是调用的SimpleWrapper中的invoke()方法:
注意:过滤链可以实现对数据的有序修改—-》》》这次的request和response对象都会传入到下一个invoke方法中,但是如果某个过滤器发生异常,那么过滤链就无法完成,最后到各什么err页面什么的。struts2的什么拦截器也是这么个事,在struts中他通过一个/×的过滤器,拦截所有请求,然后自由发挥对数据进行处理
public void invoke(Request request, Response response) throws IOException,
ServletException {
pipeline.invoke(request, response);
}
在pipline中还是调用的:
public void invoke(Request request, Response response) throws IOException,
ServletException {
// Invoke the first Valve in this pipeline for this request
(new SimplePipelineValveContext()).invokeNext(request, response);
}
因为在SimplePipeline中已经存在了所有过滤链的过滤器(value数组),所以在invokeNext中,是通过游标的方式来实现一次调用的。
连接:
http://download.csdn.net/detail/hao707822882/7484611
免费下载
在有个过滤器,那我们是不是应该想想容器的生命周期啦。。。。