这里省略各种tomcat的初始化和启动过程,简略说下,就是Bootstrap中,初始化HttpConnector类,初始化父容器StandardContext,子容器StandartWapper,以及一些生命周期,然后各种关联赋值,最后调用连接器的初始化方法,然后调用start方法,单一启动模式开启。这里,连接器有serverSocket等待接受请求,同时存在HttpProcess类,和前面一样,线程之间等待,交互,Process得到socet,assign(socket),socket给了处理器,处理器的run方法执行此行 process(socket);处理socket对象,HttpProcessor处理器对象拥有request和response全局变量,在处理器这里,解析了socket之后初始化了request和response对象。然后再处理器的process方法中调用 connector.getContainer().invoke(request, response);父容器启动,一直启动到子容器。这里说下容器关系,父容器是StandadContext,子容器是StandartWapper,它们都继承自ContainerBase类,实现了Context接口,都拥有自己的PipeLine对象,pipeLine对象都拥有自己的处理阀,父容器的基础阀是StandartContextValve,子容器的基础阀是StandardWapperValve等。先说下pipeline的启动,StandartContext继承自ContainerBase类,此类拥有pipeline对象和basic阀和一个Valve阀数组,首先父容器启动,然后调用pipeline的invoke方法,管道启动后,会调用各个阀进行servlet的处理,首先调用Valve数组,若此阀数组为空,则调用basic阀,若basic阀也为空则抛出异常,这里有一个细节就是,Valve阀会按数组下标++顺序执行,执行完后就不在执行Valve阀数组,转而执行basic阀。StandardContext的invoke( )方法调用super.invoke(request, response);即ContainerBase的invoke()方法, ContainerBase中的invoke方法调用管道的invoke( )方法pipeline.invoke(request, response);看下pipeline的启动invok()方法,在管道的invoke方法中初始化了StandardPipeLine的一个内部类 (new StandardPipelineValveContext()).invokeNext(request, response);看下invokeNext方法,内容如下:
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
(sm.getString("standardPipeline.noValve"));
}
}
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
(sm.getString("standardPipeline.noValve"));
}
}
注:一个wrapper每次对应一个servlet,wrapper的pipeline每次只会执行一个阀,阀数组下标每次+1
filterChain.doFilter(sreq, sres);
} 调用filterChain.doFilter(sreq, sres);
if( System.getSecurityManager() != null ) {
final ServletRequest req = request;
final ServletResponse res = response;
try {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction()
{
public Object run() throws ServletException, IOException {
internalDoFilter(req,res);
return null;
}
}
);
}
(ApplicationFilterConfig) iterator.next();
Filter filter = null;
try {
filter = filterConfig.getFilter();
support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
filter, request, response);
filter.doFilter(request, response, this);
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response);
1.接口
2.实现例子
这里的basic阀就是StandardContextValve,在这个阀里面,获取子容器wapper,调用 wrapper.invoke(request, response);在wrapper的invoke里,原理和父容器一样,只不过basic阀是StandardWrapperValve类,在基础阀的invoke( )方法中,调用了容器wrapper的allocate方法 servlet = wrapper.allocate();获取servlet实例,然后执行 ApplicationFilterChain filterChain =
createFilterChain(request, servlet);这里就到了本文要谈的过滤器的实现。在没有发生异常的前提下,在向请求段发送了ack确认后,就会初始化对象 ApplicationFilterChain filterChain = createFilterChain(request, servlet);简略说下过滤器的一些实现类,ApplicationFilterChain 代表的是一个过滤器链,FilterDef类代表了一个为web应用定义的过滤器实体,此类并没有太多逻辑方法,只包含一些属性如description描述,displayName和filterClass、filterName,filterClass是过滤器类的全限定名,以及这些属性的get 、set方法。所以说FilterDef并不包含过滤器要实现的逻辑,从某种意义上来说,它只是对开发者展示了一个过滤器定义(包含名字、描述等)。这里还有一个ApplicationFilterConfig类,此类可以理解为过滤器的控制类,包含FilterDef过滤器定义类, ApplicationFilterConfig的getFilter方法返回一个过滤器,方法内部通过类加载器加载FilterDef中的类全限定名。所加载的才是真正的过滤器实现类Filter类。在StandardWrapperValve的invoke( )方法中; if ((servlet != null) && (filterChain != null)) {
filterChain.doFilter(sreq, sres);
} 调用filterChain.doFilter(sreq, sres);
看下doFilter方法 public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if( System.getSecurityManager() != null ) {
final ServletRequest req = request;
final ServletResponse res = response;
try {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction()
{
public Object run() throws ServletException, IOException {
internalDoFilter(req,res);
return null;
}
}
);
}
这里 java.security.AccessController.doPrivileged以及内部类是让internalDoFilter(req,res)跳过权限检查直接执行!
private void internalDoFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
// Construct an iterator the first time this method is called
if (this.iterator == null)
this.iterator = filters.iterator();
// Call the next filter if there is one
if (this.iterator.hasNext()) {
ApplicationFilterConfig filterConfig =
(ApplicationFilterConfig) iterator.next();
Filter filter = null;
try {
filter = filterConfig.getFilter();
support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
filter, request, response);
filter.doFilter(request, response, this);
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response);
} catch (IOException e) {
if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw e;
} catch (ServletException e) {
if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw e;
} catch (RuntimeException e) {
if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw e;
} catch (Throwable e) {
if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw new ServletException
(sm.getString("filterChain.filter"), e);
}
return;
}
// We fell off the end of the chain -- call the servlet instance
try {
support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
servlet, request, response);
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse)) {
servlet.service((HttpServletRequest) request,
(HttpServletResponse) response);
} else {
servlet.service(request, response);
}
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response);
} catch (IOException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw e;
} catch (ServletException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw e;
} catch (RuntimeException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw e;
} catch (Throwable e) {
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw new ServletException
(sm.getString("filterChain.servlet"), e);
}
}
throws IOException, ServletException {
// Construct an iterator the first time this method is called
if (this.iterator == null)
this.iterator = filters.iterator();
// Call the next filter if there is one
if (this.iterator.hasNext()) {
ApplicationFilterConfig filterConfig =
(ApplicationFilterConfig) iterator.next();
Filter filter = null;
try {
filter = filterConfig.getFilter();
support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
filter, request, response);
filter.doFilter(request, response, this);
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response);
} catch (IOException e) {
if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw e;
} catch (ServletException e) {
if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw e;
} catch (RuntimeException e) {
if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw e;
} catch (Throwable e) {
if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw new ServletException
(sm.getString("filterChain.filter"), e);
}
return;
}
// We fell off the end of the chain -- call the servlet instance
try {
support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
servlet, request, response);
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse)) {
servlet.service((HttpServletRequest) request,
(HttpServletResponse) response);
} else {
servlet.service(request, response);
}
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response);
} catch (IOException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw e;
} catch (ServletException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw e;
} catch (RuntimeException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw e;
} catch (Throwable e) {
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw new ServletException
(sm.getString("filterChain.servlet"), e);
}
}
这里过滤器数组存放的是ApplicationFilterConfig类,iterator = filters.iterator();、
if (this.iterator.hasNext()) {
ApplicationFilterConfig filterConfig =
(ApplicationFilterConfig) iterator.next();
Filter filter = null;
try {
filter = filterConfig.getFilter();
support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
filter, request, response);
filter.doFilter(request, response, this);
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response);
执行了doFilter方法时,触发监听器事件,调用然后调用servlet的service方法传入request和response。
这里有个疑问就是,为什么过滤器没有循环调用,而只是next( )了一次?为了解决这个疑问,查了下百度,下面是参考博客:
Tomcat的过滤器主要由Filter、FilterChain组成,FilterChain包含一个Filter数组.当Wrapper执行FilterChain的doFilter(request,response)方法时,FilterChain首先调用第一个Filter的doFilter(request,response,filterchain)方法,当第一个filter做完过滤操作后,它又会调用filterchain的doFilter方法,此时filterchain的当前filter已变为第二个filter,第二个filter又执行dofilter方法,依此类推,直至所有过滤器都执行完毕
1.接口
- public interface Filter {
- .....
- //执行过滤
- public void doFilter ( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException;
- }
- public interface FilterChain {
- public void doFilter ( ServletRequest request, ServletResponse response ) throws IOException, ServletException;
- }
2.实现例子
- class ApplicationFilterChain implements FilterChain {
- //pos为当前filter的所在位置,n为filters数组的长度
- if (pos < n) {
- //pos++执行后,把filterchain的当前filter指向下一个
- ApplicationFilterConfig filterConfig = filters[pos++];
- Filter filter = null;
- try {
- filter = filterConfig.getFilter();
- //filter执行过滤操作
- filter.doFilter(request, response, this);
- }
- ...
- }
- }
- class SampleFilter implements Filter {
- ........
- public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain)
- throws IOException, ServletException {
- //do something
- .....
- //request, response传递给下一个过滤器进行过滤
- chain.doFilter(request, response);
- }
- }