过滤器Filter
概念:
当客户端发出Web资源的请求时,Web服务器根据应用程序配置文件设置的过滤规则进行检查,若客户请求满足过滤规则,则对客户请求/响应进行拦截,对请求头和请求数据进行检查或改动,并依次通过过滤器链,最后把请求/响应交给请求的Web资源处理。请求信息在过滤器链中可以被修改,也可以根据条件让请求不发往资源处理器,并直接向客户机发回一个响应。当资源处理器完成了对资源的处理后,响应信息将逐级逆向返回。同样在这个过程中,用户可以修改响应信息,从而完成一定的任务。
当一个请求符合某个过滤器的过滤条件时该请求就会交给这个过滤器去处理。那么当两个过滤器同时过滤一个请求时谁先谁后呢?这就涉及到了过滤链FilterChain。
用Filter的FilterChain。服务器会按照web.xml中过滤器定义的先后循序组装成一条链,然后依次执行其中的doFilter()方法。
通常我们所访问的资源是一个servlet或jsp页面,而jsp其实是一个被封装了的servlet,于是我们就可以统一地认为我们每次访问的都是一个Servlet,而每当我们访问一个servlet时,web容器都会调用该Servlet的service方法去处理请求。而在service方法又会根据请求方式的不同(Get/Post)去调用相应的doGet()或doPost()方法,实际处理请求的就是这个doGet或doPost方法。写过servlet的朋友都应该知道,我们在doGet(或doPost)方法中是通过response.getWriter()得到客户端的输出流对象,然后用此对象对客户进行响应。
Servlet和JSP中的过滤器都是Java类,它们存在的目的如下:
- 在请求访问后端资源时拦截它
- 管理从服务器返回给客户端的响应
Servlet过滤器API
Servlet过滤器API包含了3个接口,它们都在javax.servlet包中,分别是Filter接口、FilterChain接口和FilterConfig接口。
public Interface Filter
所有的过滤器都必须实现Filter接口。该接口定义了init,doFilter0,destory()三个方法
public void doFilter(ServletRequest request,ServletResponse response)
此方法是由Servlet容器提供给开发者的,用于对资源请求过滤链的依次调用,通过FilterChain调用过滤链中的下一个过滤器,如果是最后一个过滤器,则下一个就调用目标资源。
public interface FilterConfig
FilterConfig接口检索过滤器名、初始化参数以及活动的Servlet上下文。该接口提供了以下4个方法:
(1)public java.1ang.String getFilterName()
返回web.xml部署文件中定义的该过滤器的名称。
(2)public ServletContext getServletContext()
返回调用者所处的servlet上下文。
(3)public java.1ang.String getlnitParameter(java.1ang.String name)
返回过滤器初始化参数值的字符串形式,当参数不存在时,返回nul1.name是初始化参数名。
(4)public java.util.Enumeration getlnitParameterNames()
以Enumeration形式返回过滤器所有初始化参数值,如果没有初始化参数,返回为空。
Servlet过滤器开发步骤:
1、创建实现javax.servlet.Filter接口的类。
2、过滤器的xml配置。
下面列出了多种常用的过滤器类型:
- 认证过滤器
- 数据压缩过滤器
- 加密过滤器
- 触发资源访问事件的过滤器
- 图像转换过滤器
- 登录和验证过滤器
- MIME类型链过滤器
- 令牌过滤器
- 转换XML内容的XSL/T过滤器
过滤器将会被插入进web.xml文件中,然后映射servlet、JSP文件的名字,或URL模式。部署描述文件web.xml可以在 <Tomcat-installation-directory>\conf 目录下找到。
当JSP容器启动网络应用程序时,它会创建每一个过滤器的实例,这些过滤器必须在部署描述文件web.xml中声明,并且按声明的顺序执行。
Servlet过滤器方法
一个过滤器就是一个Java类,它实现了javax.servlet.Filter 接口。javax.servlet.Filter接口定义了三个方法:
1 // 引入Java包 2 import java.io.*; 3 import javax.servlet.*; 4 import javax.servlet.http.*; 5 import java.util.*; 6 7 // 实现 Filter 类 8 public class LogFilter implements Filter { 9 public void init(FilterConfig config) 10 throws ServletException{ 11 // 获取初始化参数 12 String testParam = config.getInitParameter("test-param"); 13 14 //打印初始化参数 15 System.out.println("Test Param: " + testParam); 16 } 17 public void doFilter(ServletRequest request, 18 ServletResponse response, 19 FilterChain chain) 20 throws java.io.IOException, ServletException { 21 22 // 获取客户端ip地址 23 String ipAddress = request.getRemoteAddr(); 24 25 // 输出ip地址及当前时间 26 System.out.println("IP "+ ipAddress + ", Time " 27 + new Date().toString()); 28 29 // 传递请求道过滤器链 30 chain.doFilter(request,response); 31 } 32 public void destroy( ){ 33 /* 在Filter实例在服务器上被移除前调用。*/ 34 } 35 }
使用多重过滤器
您的网络应用程序可以定义很多不同的过滤器。现在,您定义了两个过滤器,AuthenFilter和LogFilter,其它的步骤与前面讲的一样,除非要创建一个不同的映射,就像下面这样:
1 <filter> 2 <filter-name>LogFilter</filter-name> 3 <filter-class>LogFilter</filter-class> 4 <init-param> 5 <param-name>test-param</param-name> 6 <param-value>Initialization Paramter</param-value> 7 </init-param> 8 </filter> 9 10 <filter> 11 <filter-name>AuthenFilter</filter-name> 12 <filter-class>AuthenFilter</filter-class> 13 <init-param> 14 <param-name>test-param</param-name> 15 <param-value>Initialization Paramter</param-value> 16 </init-param> 17 </filter> 18 19 <filter-mapping> 20 <filter-name>LogFilter</filter-name> 21 <url-pattern>/*</url-pattern> 22 </filter-mapping> 23 24 <filter-mapping> 25 <filter-name>AuthenFilter</filter-name> 26 <url-pattern>/*</url-pattern> 27 </filter-mapping>
过滤器的应用顺序
在web.xml中<filter>元素的映射顺序决定了容器应用这些过滤器的顺序。要反转应用的顺序,您只需要反转web.xml中<filter>元素的定义顺序就行了。