9.1 Filter API
9.1 Filter API
接下来几节主要介绍Filter
相关的接口,包含Filter
、FilterConfg
、FilterChain
。
Filter生命周期方法
Filter
的实现必须继承javax.servlet.Filter
接口。这个接口包含了Filter
的**3个生命周期方法:init
、doFilter
、destroy
**。
init方法
Servlet
容器初始化Filter
时,会触发Filter
的init
方法,一般来说是在应用开始时。也就是说,init
方法并不是在该Filter
相关的资源使用到的时候才初始化的,而且这个方法只调用一次,用于初始化Filter
。init
方法的定义如下:
1 | void init(FilterConfig filterConfig) |
注意FilterConfig
实例是由Servlet
容器传入init
方法中的。FilterConfig
将在后面的章节中讲解。
doFilter方法
当Servlet
容器每次处理Filter
相关的资源时,都会调用该Filter
实例的doFilter
方法。Filter
的doFilter
方法包含ServletRequest
、ServletResponse
、FilterChain
这3个参数。doFilter
的定义如下:
1 | void doFilter(ServletRequest request, ServletResponse response, |
接下来,说明一下doFilter
的实现中访问ServletRequet
、ServletResponse
。这也就意味着允许给ServletRequest
增加属性或者增加Header
。当然也可以修饰ServletRequest
或者ServletRespone
来改变它们的行为。在第10章中,“修饰Requests
及Responses
”中将会有详细的说明。
在Filter
的doFilter
的实现中,最后一行需要调用FilterChain
中的doChain
方法。注意Filter
的doFilter
方法里的第3个参数,就是filterChain
的实例:
1 | filterChain.doFilter(request, response) |
一个资源可能需要被多个Filter
关联到(更专业一点来说,这应该叫作Filter
链条),这时Filter.doFilter()
的方法将触发Filter
链条中下一个Filter
。只有在Filter
链条中最后一个Filter
里调用的FilterChain.doFilter()
,才会触发处理资源的方法。
如果在Filter.doFilter
()的实现中,没有在结尾处调用FilterChain.doFilter
()的方法,那么该Request
请求中止,后面的处理就会中断。
注意:FilterChaing
接口中,唯一的方法就是doFilter
。该方法与Filter
中的doFilter
的定义是不一致的:在FilterChaing
中,doFilter
方法只有两个参数,但在Filter
中,doFilter
方法有三个参数。
destroy方法
Filter
接口中,最后一个方法是destroy
,它的定义如下:
1 | void destroy() |
该方法在Servlet
容器要销毁Filter
时触发,一般在应用停止的时候进行调用。
除非Filter
在部署描述中被多次定义到,否则**Servlet
容器只会为每个Filter
创建单一实例**。由于Serlvet/JSP
的应用通常要处理用户并发请求,此时Filter
实例需要同时被多个线程所关联到,因此需要非常小心地处理多线程问题。关于如何处理线程安全问题的例子,可以参考9.5节“下载计数Filter
”。