过滤器的简介
Servlet实现的过滤器功能是Web中的一个小型组件,其拦截来自客户端的请求和响应信息,从而进行查看、提取或者对客户端和服务器之间交换的数据信息进行某项特定的操作。实现的过滤器通常是用来封装一些辅助性的功能方法,这些过滤器方法可能对真正意义上的客户端请求和响应处理不起决定性作用,但还是非常重要的。可以使用Servlet中的过滤器来记录有关客户端请求和响应的数据、处理数据传递过程中所存在的安全性问题以及管理会话属性等。过滤器提供了一种面向对象的模块化机制,将公共的过滤器方法封装到可插入组件中,然后再由一个配置文件来声明这些组件,并动态地进行调用和处理。
Servlet中的过滤器结合了许多元素,已经使得过滤器成为独特、强大和模块化的Web组件。从而概括起来,Servlet过滤器是:
Servlet实现的过滤器是需要通过一个配置文件(web.xml)来灵活声明的模块化以及可重用组件。过滤器是动态地(不需要程序员编写程序进行调用)处理传入的客户端请求和传出的响应,并且也不需要修改任何应用程序代码就可以透明地通过配置文件添加或删除某个过滤器。{zh1},过滤器也具有可移植性,可以独立于任何平台或者Servlet容器,从而允许将这些过滤器容易地部署到大部分的J2EE环境中。
在接下来的小节中,将进一步考察Servlet过滤器的总体设计,以及如何实现、配置和部署过滤器所涉及的步骤。{zh1},还将继续探讨Servlet过滤器的一些实际应用,简要考察一下模型-视图-控制器(MVC)体系结构中包含的Servlet过滤器。
Servlet过滤器的体系结构
其实,过滤器就是一个Servlet,只是比较特殊而已,可以用它来对客户端请求以及发出的响应进行部分的过滤操作。
过滤器并不是真正意义上对来自客户端的请求作出最终的响应,而是进行部分的过滤工作,对请求数据进行检测或者安全性检查等工作。多个特定的过滤器可以一起组成一个过滤器链。
过滤器只有在客户端请求或者发出响应时才会自动进行调用,所有没有必要把这些过滤器字节嵌入到整个Web应用系统的框架中,而是通过配置文件来设定。
当然,大部分情况下,并不需要给Web应用程序设置过滤器,因为它不是必需的。如果需要设置过滤器,除了可以设置单个过滤器关联,还可以设置Web应用程序与一个过滤器链(多个单过滤器相串联)相关联。那么整个过滤器的工作过程是怎样的呢?下面列举出过程步骤:
(1)通过部署描述符web.xml中对过滤器的配置,特定过滤器会捕捉到客户端的请求信息。
(2)过滤器调用内置方法来检查捕获到的请求对象,根据分析结果来决定是把该请求传递给下一个过滤器(如果存在另一个过滤器的话),还是中止该请求并向客户端发出一个响应。如果不存在过滤器链,即仅为单个过滤器,则上一个过滤器直接把客户端请求转发给Web服务器作相应处理。
(3)如果Web应用程序关联了过滤器,在客户端请求设法通过各个过滤器被服务器处理时,最终的响应将以相反的顺序通过过滤器链,{zh1}发送给客户端。
过滤器的概念是从Servlet 2.3才开始引入的,一开始仅仅能够过滤Web客户端和客户首次所需访问服务器资源之间的数据信息。当{dy}个访问的资源(例如某一个JSP页面)把客户端请求再转发给另外一个服务器资源(例如另外一个JSP页面)时,这时过滤器就不起作用了。到了Servlet 2.4发布之后,这样的过滤器限制得到了修改。也就是说,现在的过滤器可以作用于J2EE环境中的任何请求过程中,可以在客户端和Servlet以及JSP之间,也可以是服务器端的Servlet与Servlet以及JSP页面之间,这大大增加了过滤器在Web应用程序中的可适用性。
实现一个Servlet过滤器
在Web应用程序中实现一个Servlet过滤器需要经历3个步骤:
(1)编写Servlet过滤器的实现类程序。
(2)需要把实现的过滤器添加到Web应用程序中,也就是说,需要在Web部署描述文件web.xml中声明该过滤器。
(3){zh1}要把相关联的过滤器与应用程序一起打包并部署。
下面将详细介绍其中的每个步骤:
1.编写过滤器的实现类程序
编写过滤器一般需要使用3个简单的接口: Filter.java、FilterChain.java和FilterConfig.java,这3个接口封装在java.servlet包中。从编程的角度来看,过滤器类必须要实现Filter 接口,然后使用这个过滤器类中的FilterChain和FilterConfig接口。该过滤器类的一个引用将传递给FilterChain对象,以允许过滤器把控制权传递给链中的下一个资源。FilterConfig对象将由容器提供给过滤器,以允许访问该过滤器的初始化数据。
与实现Servlet过滤器的3步模式保持一致,过滤器必须实现如下的3个方法,以便xx实现Filter接口:
下面创建的TimeTrackFilter.java类展示了一个非常简单的过滤器,它跟踪满足一个客户机的Web请求所花的大致时间:
import javax.servlet.*;
import java.util.*;
import java.io.*;
public class TimeTrackFilter implements Filter {
private FilterConfig filterConfig = null;
public void init(FilterConfig filterConfig)throws ServletException {
}
}
}
程序说明:
2.在web.xml文件中配置Servlet过滤器
实现了Servlet过滤器之后,还需要通过web.xml文件中的两个XML元素来声明该过滤器。<filter>元素定义过滤器的名称,并且声明实现类和init()参数。<filter-mapping>元素将过滤器与Servlet或URL模式相关联。
下面展示在web.xml配置文件中声明一个过滤器的方法,把下面这段配置代码插入到web.xml文件中的</web-app>标记前面:
<filter>
<filter-name>Page Request Timer</filter-name>
<filter-class>TimeTrackFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Page Request Timer</filter-name>
<servlet-name>Main Servlet</servlet-name>
</filter-mapping>
<servlet>
<servlet-name>Main Servlet</servlet-name>
<servlet-class>MainServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Main Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
上面的代码示例声明了一个过滤器("Page Request Timer"),并把它映射到一个servlet("Main Servlet")。然后为该servlet定义了一个映射,以便把每个请求(由通配符指定)都发送到该servlet。这是控制器组件的典型映射声明。应该注意这些声明的顺序,千万不能背离这些元素的顺序。
3.部署Servlet过滤器
Servlet过滤器的部署非常简单,只需把过滤器的实现类和其他Web组件类放置在一起。重点是部署描述符web.xml对各类过滤器的配置要正确,然后把配置文件web.xml文件(连同过滤器定义和过滤器映射声明)放进Web应用程序结构中,servlet容器将处理之后的其他所有事情。
过滤器的应用
过滤器不是真正用来完成客户端请求的,客户端请求操作最终还是要交付给服务器进行相应处理,过滤器只是做一些辅助性的工作。但是在某些情况下,过滤器是非常有用的,例如安全性检查等。在适合可以使用装饰过滤器模式或者拦截模式的地方都可以使用过滤器。总结起来,过滤器可以使用在如下方面:
使过滤器适应MVC体系结构
在第13章中将会向读者重点介绍模型-视图-控制器(Model-View-Controller,MVC)体系结构,和Model1模式相比,MVC模式的优势非常明显,而且MVC现在已经成为一个非常重要和流行的框架设计方法。第13章介绍的Struts技术就是使用的MVC框架结构,而且使用Servlet过滤器技术来管理客户端请求和服务器端响应之间的处理流,例如页面的定向。
过滤器可以在MVC框架中作为一个调度器组件,根据xml配置文件可以将客户端请求转发给相应的应用程序组件进行逻辑处理。过滤器也是成为MVC框架中的控制层的{zj0}选择。
通过使用过滤器作为MVC框架中的控制层,负责页面的转发以及安全检测等工作,这样仅仅需要通过xml配置文件就可以统一对页面转换进行管理。使得应用程序的结构清晰,易于后期程序的维护和管理。