8-1-Filter过滤器

Filter和Listener是Servlet规范中的两个高级特性,不同于Servlet,它们不用于处理客户端请求。Filter用于对request、response对象进行修改,Listener用于对context、session、request事件进行监听,善用Servlet规范中的这两个高级特性能够轻松地解决一些特殊问题。


什么是Filter

Filter被称作过滤器,其基本功能就是对Servlet容器调用Servlet的过程进行拦截,从而在Servlet进行响应处理前后实现一些特殊功能。这就好比现实中的污水净化设备,它可以看作一个过滤器,专门用于过滤污水杂质。Filter在Web应用中的拦截过程如图所示。

在上图中,当浏览器访问服务器中的目标 资源时,会被Filter拦截,在Filter中进行 预处理操作,然后再将请求转发给目标资 源。当服务器接收到这个请求后会对其进行响应,在服务器处理响应的过程中,也需要先将响应结果发送给过滤器,在过滤器中对响应结果进行处理后,才会发送给客户端。 

其实,Filter过滤器就是一个实现了javax.servlet.Filter接口的类,在javax.servlet.Filter接口中定义了三个方法,具体如表所示。

表中的这三个方法都是Filter 的生命周期方法,其中init() 方法在Web应用程序加载的 时候调用,destroy()方法在 Web应用程序卸载的时候调 用,这两个方法都只会被调用一次,而doFilter()方法只要有客户端请求时就会被调用,并且Filter所有的工作集中在doFilter()方法中。

案例:实现第一个Filter程序 

过滤器的配置信息中包含多个元素,这些元素分别具有不同的作用,具体如下:

(1)<filter>根元素用于注册一个Filter。

(2)<filter-name>子元素用于设置Filter名称。

(3)<filter-class>子元素用于设置Filter类的完整名称。

(4)<filter-mapping>根元素用于设置一个过滤器所拦截的资源。

(5)<filter-name>子元素必须与<filter>中的<filter-name>子元素相同。

(6)<url-pattern>子元素用于匹配用户请求的URL,例如“/MyServlet”,这个URL还可以使用通配符“*”来表示,例如“*.do”适用于所有以“.do”结尾的Servlet路径。

Filter映射

1.使用通配符“*”拦截用户的所有请求

Filter的<filter-mapping>元素用于配置过滤器拦截的资源信息,如果想让过滤器拦截所有的请求访问,那么需要使用通配符“*”来实现,具体示例如下。

    <filter>
		<filter-name>CharacterFilter</filter-name>
		<filter-class>cn.itcast.chapter08.filter.CharacterFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>CharacterFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

2.拦截不同方式的访问请求

在web.xml文件中,一个<filter-mapping>元素用于配置一个Filter所负责拦截的资源。 <filter-mapping>元素中有一个特殊的子元素<dispatcher>,该元素用于指定过滤器所拦截的资源被Servlet容器调用的方式,<dispatcher>元素的值共有4个,具体如下:

1)REQUEST 当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器将不会被调用。

2)INCLUDE 如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。

3)FORWARD 如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。

4)ERROR 如果目标资源是通过声明式异常处理机制(web.xml中<error-page>)调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

以FORWARD为例,分步骤演示Filter对转发请求的拦截效果

Filter链

在一个Web应用程序中可以注册多个Filter程序,每个Filter程序都可以针对某一个URL进行拦截。如果多个Filter程序都对同一个URL进行拦截,那么这些Filter就会组成一个Filter链(也叫过滤器链)。Filter链用FilterChain对象来表示,FilterChain对象中有一个doFilter()方法,该方法的作用就是让Filter链上的当前过滤器放行,使请求进入下一个Filter,接下来通过一个图例来描述Filter链的拦截过程,如图所示。

在上图中,当浏览器访问Web服务器中的资源时需要经过两个过滤器Filter1和Filter2,首先Filter1会对这个请求进行拦截,在Filter1过滤器中处理好请求后,通过调用Filter1的doFilter()方法将请求传递给Filter2,Filter2将用户请求处理后同样调用doFilter()方法,最终将请求发送给目标资源。当Web服务器对这个请求做出响应时,也会被过滤器拦截,这个拦截顺序与之前相反,最终将响应结果发送给客户端。

如果用注解开发,无法确定拦截顺序

分步骤演示如何使用Filter链拦截MyServlet的同一个请求

FilterConfig接口

为了获取Filter程序在web.xml文件中的配置信息,Servlet API提供了一个FilterConfig接口,该接口封装了Filter程序在web.xml中的所有注册信息,并且提供了一系列获取这些配置信息的方法,具体如表所示。

演示FilterConfig接口的getInitParameter(String name)方法

【任务8-1】使用Filter实现用户自动登录

【任务8-2】通过Filter统一全站编码

猜你喜欢

转载自blog.csdn.net/daqi1983/article/details/121345266