对于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 免费下载
在有个过滤器,那我们是不是应该想想容器的生命周期啦。。。。