1. Filter简介

    1. 从功能角度来说,Filter能做什么?

    2. 从API角度来说,如何实现Filter?

    3. 从原理角度来说,Filter是如何实现拦截的?

  2. Filter生命周期和Filter链

    1. Filter生命周期的三个方法:init、doFilter和destory

    2. Filter链及其调用顺序

  3. Filter高级开发

    1. HttpServletRequestWrapper

    2. HttpServletResponseWrapper

    3. 动态代理

    4. Filter映射

  4. Filter案例


1、Filter简介


1.1、从功能角度来说,Filter能做什么?

Filter也称之为过滤器,它是Servlet技术中最激动人心的技术。WEB开发人员通过Filter技术,对web服务器管理的所有web资源(例如Jsp, Servlet, 静态图片文件或静态 html 文件等)进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。


1.2、从API角度来说,如何实现Filter?

Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。

Filter开发分为二个步骤

1、编写java类实现javax.servlet.Filter接口,并实现其doFilter方法。

2、在 web.xml 文件中使用和元素对编写的filter类进行注册,并设置它所能拦截的资源。


HelloFilter.java

package com.rk.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class HelloFilter implements Filter
{
	public HelloFilter()
	{
		System.out.println("HelloFilter构造函数!");
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException
	{
		System.out.println("HelloFilter.init()方法");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
			ServletException
	{
		System.out.println("HelloFilter.doFilter()前");
		chain.doFilter(request, response);
		System.out.println("HelloFilter.doFilter()后");
	}

	@Override
	public void destroy()
	{
		System.out.println("HelloFilter.destroy()");
	}

}

web.xml中的Filter映射配置

  
  
  	HelloFilter
  	com.rk.filter.HelloFilter
  
  
  
  	HelloFilter
  	/*
  

1.3、从原理角度来说,Filter是如何实现拦截的?

Filter接口中有一个doFilter方法。WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:

1)调用目标资源之前,让一段代码执行

2)是否调用目标资源(即是否让用户访问web资源)

web服务器在调用doFilter方法时,会传递一个filterChain对象进来。filterChain对象是filter接口中最重要的一个对象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法。如果调用该方法,则web服务器就会调用web资源的service方法,即web资源就会被访问,否则web资源不会被访问。

3)调用目标资源之后,让一段代码执行

Filter拦截的示意图:

Filter编程:(1)Filter基础_第1张图片



2、Filter生命周期和Filter链

Filter生命周期,主要是在一个Filter内部,从Filter创建到Filter销毁的过程中,其内部方法的调用顺序。

Filter链,是当存在多个Filter时,形成的一种Filter对象顺序调用的“链/Chain”。

Filter生命周期解释的是一个Filter内部的执行顺序问题,而Filter链是多个Filter之间的调用顺序问题。

2.1、Filter生命周期的三个方法:init、doFilter和destory


javax.servlet.Filter接口的源码:

package javax.servlet;

import java.io.IOException;

	/** 
	* A filter is an object that performs filtering tasks on either the request to a resource (a servlet or static content), or on the response from a resource, or both.
        * 

* Filters perform filtering in the doFilter method. Every Filter has access to  ** a FilterConfig object from which it can obtain its initialization parameters, a ** reference to the ServletContext which it can use, for example, to load resources ** needed for filtering tasks. ** 

** Filters are configured in the deployment descriptor of a web application ** 

** Examples that have been identified for this design are
** 1) Authentication Filters 
** 2) Logging and Auditing Filters 
** 3) Image conversion Filters 
     ** 4) Data compression Filters 
** 5) Encryption Filters 
** 6) Tokenizing Filters 
** 7) Filters that trigger resource access events 
** 8) XSL/T filters 
** 9) Mime-type chain Filter 
 * @since Servlet 2.3 */ public interface Filter { /**  * Called by the web container to indicate to a filter that it is being placed into * service. The servlet container calls the init method exactly once after instantiating the * filter. The init method must complete successfully before the filter is asked to do any * filtering work. 

      * The web container cannot place the filter into service if the init method either
        * 1.Throws a ServletException 
        * 2.Does not return within a time period defined by the web container  */ public void init(FilterConfig filterConfig) throws ServletException; /** * The doFilter method of the Filter is called by the container * each time a request/response pair is passed through the chain due * to a client request for a resource at the end of the chain. The FilterChain passed in to this * method allows the Filter to pass on the request and response to the next entity in the * chain.

* A typical implementation of this method would follow the following pattern:- 
* 1. Examine the request
* 2. Optionally wrap the request object with a custom implementation to * filter content or headers for input filtering 
* 3. Optionally wrap the response object with a custom implementation to * filter content or headers for output filtering 
* 4. a) Either invoke the next entity in the chain using the FilterChain object (chain.doFilter()), 
    ** 4. b) or not pass on the request/response pair to the next entity in the filter chain to block the request processing
** 5. Directly set headers on the response after invocation of the next entity in the filter chain. **/     public void doFilter ( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException; /** * Called by the web container to indicate to a filter that it is being taken out of service. This  * method is only called once all threads within the filter's doFilter method have exited or after * a timeout period has passed. After the web container calls this method, it will not call the * doFilter method again on this instance of the filter. 

*        * This method gives the filter an opportunity to clean up any resources that are being held (for * example, memory, file handles, threads) and make sure that any persistent state is synchronized * with the filter's current state in memory. */ public void destroy(); }



2.1.1、init(FilterConfig filterConfig)

和我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责。 web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(注:filter对象只会创建一次,init方法也只会执行一次。 )

开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。


javax.servlet.FilterConfig接口的源码:

package javax.servlet;


import java.util.Enumeration;

	 /** 
	 *
	 * A filter configuration object used by a servlet container
	 * to pass information to a filter during initialization.
	 *
	 */


public interface FilterConfig {

	/** 
	* Returns the filter-name of this filter as defined in the deployment descriptor. 
	*/
	
	public String getFilterName();


 /**
     * Returns a reference to the {@link ServletContext} in which the caller
     * is executing.
     */

    public ServletContext getServletContext();
    
    /**
     * Returns a String containing the value of the 
     * named initialization parameter, or null if 
     * the parameter does not exist.
     */

    public String getInitParameter(String name);


    /**
     * Returns the names of the filter's initialization parameters
     * as an Enumeration of String objects, 
     * or an empty Enumeration if the filter has
     * no initialization parameters.
     */

    public Enumeration getInitParameterNames();

}

用户在配置filter时,可以使用为filter配置一些初始化参数;当web容器实例化Filter对象,调用其init方法时,会把封装了filter初始化参数的filterConfig对象传递进来。因此开发人员在编写filter时,通过filterConfig对象的方法:

(1)String getFilterName():得到filter的名称。

(2)String getInitParameter(String name): 返回在部署描述中指定名称的初始化参数的值。如果不存在返回null.

(3)Enumeration getInitParameterNames():返回过滤器的所有初始化参数的名字的枚举集合。

(4)public ServletContext getServletContext():返回Servlet上下文对象的引用。


2.1.2、doFilter ( ServletRequest request, ServletResponse response, FilterChain chain )

WEB服务器每次在调用web资源的service方法之前,都会先调用一下Filter的doFilter方法。

javax.servlet.FilterChain接口的源码:

package javax.servlet;

import java.io.IOException;

    /**
    * A FilterChain is an object provided by the servlet container to the developer
    * giving a view into the invocation chain of a filtered request for a resource. Filters
    * use the FilterChain to invoke the next filter in the chain, or if the calling filter
    * is the last filter in the chain, to invoke the resource at the end of the chain.
    *
    **/

public interface FilterChain {
	
	/**
	* Causes the next filter in the chain to be invoked, or if the calling filter is the last filter
	* in the chain, causes the resource at the end of the chain to be invoked.
	*
	*/
	
    public void doFilter ( ServletRequest request, ServletResponse response ) throws IOException, ServletException;

}


2.1.3、destroy()

在Web容器卸载 Filter 对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。



2.2、Filter链及其调用顺序

【Filter链】在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。

【Filter链调用顺序】WEB服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter。

【代码级别的执行顺序】当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

Filter编程:(1)Filter基础_第2张图片