现在的位置: 首页 > 综合 > 正文

tomcat原理及实现—–tomcat的过滤器(第三篇)

2019年05月23日 ⁄ 综合 ⁄ 共 3853字 ⁄ 字号 评论关闭

对于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  免费下载

在有个过滤器,那我们是不是应该想想容器的生命周期啦。。。。

抱歉!评论已关闭.