Filter编程:Filter基础

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Filter编程:Filter基础相关的知识,希望对你有一定的参考价值。

  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映射配置

  <!-- Filter配置 -->
  <filter>
  	<filter-name>HelloFilter</filter-name>
  	<filter-class>com.rk.filter.HelloFilter</filter-class>
  </filter>
  <!-- Filter映射配置 -->
  <filter-mapping>
  	<filter-name>HelloFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>

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拦截的示意图:

技术分享



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.
        * <br><br>
	* Filters perform filtering in the <code>doFilter</code> 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.
	** <p>
	** Filters are configured in the deployment descriptor of a web application
	** <p>
	** Examples that have been identified for this design are<br>
	** 1) Authentication Filters <br>
	** 2) Logging and Auditing Filters <br>
	** 3) Image conversion Filters <br>
    	** 4) Data compression Filters <br>
	** 5) Encryption Filters <br>
	** 6) Tokenizing Filters <br>
	** 7) Filters that trigger resource access events <br>
	** 8) XSL/T filters <br>
	** 9) Mime-type chain Filter <br>
	 * @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. <br><br>

     	* The web container cannot place the filter into service if the init method either<br>
        * 1.Throws a ServletException <br>
        * 2.Does not return within a time period defined by the web container 
	*/
	public void init(FilterConfig filterConfig) throws ServletException;
	
	
	/**
	* The <code>doFilter</code> 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.<p>
	* A typical implementation of this method would follow the following pattern:- <br>
	* 1. Examine the request<br>
	* 2. Optionally wrap the request object with a custom implementation to
	* filter content or headers for input filtering <br>
	* 3. Optionally wrap the response object with a custom implementation to
	* filter content or headers for output filtering <br>
	* 4. a) <strong>Either</strong> invoke the next entity in the chain using the FilterChain object (<code>chain.doFilter()</code>), <br>   
	** 4. b) <strong>or</strong> not pass on the request/response pair to the next entity in the filter chain to block the request processing<br>
	** 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. <br><br>
	* 
     	* 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 <code>String</code> containing the value of the 
     * named initialization parameter, or <code>null</code> if 
     * the parameter does not exist.
     */

    public String getInitParameter(String name);


    /**
     * Returns the names of the filter‘s initialization parameters
     * as an <code>Enumeration</code> of <code>String</code> objects, 
     * or an empty <code>Enumeration</code> 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编程:Filter基础的主要内容,如果未能解决你的问题,请参考以下文章

Python基础- 函数式编程

Filter

DirectShow Filter 基础与简单的示例程序

Jquery filter()方法简介

python基础之map/reduce/filter/sorted

Python函数式编程高级函数2/3—filter