9.1 Filter API

9.1 Filter API

接下来几节主要介绍Filter相关的接口,包含FilterFilterConfgFilterChain

Filter生命周期方法

Filter的实现必须继承javax.servlet.Filter接口。这个接口包含了Filter的**3个生命周期方法:initdoFilterdestroy**。

init方法

Servlet容器初始化Filter时,会触发Filterinit方法,一般来说是在应用开始时。也就是说,init方法并不是在该Filter相关的资源使用到的时候才初始化的,而且这个方法只调用一次,用于初始化Filterinit方法的定义如下:

1
void init(FilterConfig filterConfig)

注意
FilterConfig实例是由Servlet容器传入init方法中的。FilterConfig将在后面的章节中讲解。

doFilter方法

Servlet容器每次处理Filter相关的资源时,都会调用该Filter实例的doFilter方法。FilterdoFilter方法包含ServletRequestServletResponseFilterChain这3个参数。
doFilter的定义如下:

1
2
void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain)

接下来,说明一下doFilter的实现中访问ServletRequetServletResponse。这也就意味着允许给ServletRequest增加属性或者增加Header。当然也可以修饰ServletRequest或者ServletRespone来改变它们的行为。在第10章中,“修饰RequestsResponses”中将会有详细的说明。

FilterdoFilter的实现中,最后一行需要调用FilterChain中的doChain方法。注意FilterdoFilter方法里的第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”。