Filter、FilterChain、FilterConfig介绍

感谢作者:本文内容复制于https://www.runoob.com/w3cnote/filter-filterchain-filterconfig-intro.html

1. Filter程序是一个实现了特殊接口的Java类,与Servlet类似,也是有Servlet容器进行调用和执行的。

2. 当web.xml注册了一个Filter来对某个Servlet进行拦截处理时,他可以决定是否将请求传递给Servlet程序,以及对请求和响应消息是否进行修改。

3. 当Servlet 容器开始调用某个Servlet程序时,如果发现由一个Filter程序对该Servlet进行拦截。而是调用Filter的doFilter()方法,再由doFilter()方法决定是否去激活service()方法。

4. 但是Filter.doFilter()方法不能直接调用Servlet的service()方法,而是调用FilterChain.doFilter方法来激活servlet的service()方法,FilterChain对象时通过Filter.doFilter方法的参数传递进来的。

5. 只要在Filter.doFilter()方法中调用FilterChain.doFilter方法的语句前后增加某些程序代码,这样就可以在Servlet进行响应前后实现某些特殊的功能。

6. 如果filter.dofilter中没有调用FilterChain.doFilter()方法,那么Servlet的service方法就不回被执行。这样通过Filter就可以阻止某些菲方的访问求情。

二:FilterChain

1. 在一个web应用程序中可以注册多个Filter程序,每个Filter都可以对一个或一组Servlet程序进行拦截。如果有多个Filter对某个Servlet程序进行拦截,当针对该Servlet的访问请求到达时,Web容器将把这多个Filter组合成一个FilterChian。也叫过滤器链

2. Filter链中的各个Filter的蓝机器顺序与他们在web.xml文件中的映射顺序时一致的。上一个Filter.doFilter()方法调用FilterChain.doFilter方法将激活下一个Filter.doFilter方法。最后一个Filter.doFilter方法中调用FilterChain.doFilter方法激活Servlet中的service方法。

3. 只要Filterchain中任意一个Filter没有调用FilterChain.doFilter方法,则目标Servlet的service方法就不回执行。

三:Filter接口

一个Filter程序就是一个java类,这个类必须实现Filter接口。javax.servlet.Filter接口中定义了三个方法:int,doFilter,destory.

init方法

  在web应用程序启动时,web服务器将根据器web.xml文件的配置信息来创建每个注册的Filter的实例对象。并将其保存在内存中。

   Web容器在创建Filter对象之后,立即执行Filter对象的init方法。init方法在生命周期内仅仅被执行一次。Web容器在调用int的方法时会传递一个包含Filter配置和运行环境信息的FilterConfig对象。

  

public voic init(FilterConfig filterConfig) throws ServletException

  开发人员可以在init方法中完成于构造方法类似的初始化功能。要注意的时如果初始化代码要使用FilterConfig对象,这些代码只能在init方法中编写,而不能在构造方法中编写。

doFilter

  当一个Filter对象能够拦截访问请求时,Servlet容器将调用Filter容器将调用Filter对象的doFilter方法。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException.ServletException

destory

  该方法在web容器卸载Filter对象之前被调用,也仅执行一次。可以完成于init方法相反的功能。释放Filter对象打开的资源,例如:关闭数据库连接和IO流。

四: FilterChain接口

  该接口用于定义一个Filter链对象应该对外提供的方法,这个接口只有一个doFilter方法

  

public void doFilter(ServletRequest request, ServletResponse response) throws java.io.IOException.ServletException

FilterChain接口的doFilter方法用于通知Web容器把请求交给Filter链中的下一个Filter去处理。如果当前调用此方法Filter链中的最后一个Filter,那么将把请求交给目标Servlet程序处理。

五:FilterConfig接口

  1. 与普通的servlet程序一样,Filter程序可能需要访问Servlet容器。Servlet规范将代表ServletContext对象和Filter的配置参数信息封装到一个称之为FilterConfig的对象中。

  2. FilterConfig 接口则用于定义FilterConfig对象应该对外提供的方法。以便在Filter程序中可以调用这些方法来获取ServletContext对象,以及获取web.xml文件中Filter设置友好名称和初始化参数

  3. FilterConfig 接口定义的各个方法:

    a) getFilterName 方法,返回<filter-name>元素设置值

    b) getServletContext 方法,返回FilterConfig 对象中所封装的ServletContext引用

    c) getInitParameter方法,用于返回web.xml文件中为Filter所设置的某个名称的初始化参数值

    d) getInitParameterNames方法,返回一个Enumeration集合对象。

六:Filter 的注册于反射

  1. 注册Filter

  一个<filter>元素用于注册一个Filter。其中<filter-name>时必须的,<filter-classes>元素也是必须的。<init-param>元素时可选的,可以有多个<init_param>元素

<filter>
    <filter-name>FirstFilter</filter-name>
    <filter-class>FirstFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>GB2312</param-value>
    </init-param>
</filter>

  2. 映射Filter

  <filter-mapping>元素用于设置一个Filter所负责拦截器资源。一个Filter拦截器的资源可以通过两种方式来指定:资源的访问请求路径和Servlet名称

  指定资源的访问路径

  

<filter-mapping>
    <filter-name>FirstFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

  <url-pattern> 元素中的访问路径的设置遵循Servlet URL映射规范

    /*:表示拦截所有的访问路径

    /filter/*:表示拦截filter目录下的所有的访问请求,如:http://localhost:8888/testFilter-000/filter/xxxxxxx.

    /text.html:表示拦截根目录下以test.html为资源名的访问请求,访问链接只会是:http://localhost:8888/text.html

  2.1 指定servlet名称

<filter-mapping>
    <filter-name>FirstFilter</filter-name>
    <servlet-name>default></servlet-name>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

    <servlet-name>元素于<url-pattern>元素是二选一的关系,其值是某个Servlet在web.xml文件中的注册名称

    <dispatcher>元素有4钟:REQUEST,INCLUDE,FORWARDERROR分别对应Servlet容器调用资源的四种方式

      正常调用

      通过RequestDispatche.include方法调用

      通过RequestDispatcher.forward方法调用

      作为错误响应资源调用

七一个传统的Filter程序示例

FitstFilter.java
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
 
public class FirstFilter implements Filter {
    private FilterConfig filterConfig = null;
    String paramValue = null;
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
        paramValue = filterConfig.getInitParameter("encoding");
    }
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("begin headers-------------------");
        Enumeration<?> headerNames = ((HttpServletRequest)request).getHeaderNames();
        
        while(headerNames.hasMoreElements()) {
            String headerName = (String)headerNames.nextElement();
            System.out.println(headerName + ": " + ((HttpServletRequest)request).getHeader(headerName));
        }
        System.out.println("end headers-------------------");
        
        //在调用目标前写入响应内容
        response.setContentType("text/html; charset=gb2312");
        PrintWriter out = response.getWriter();
        out.println("IP地址为:" + request.getRemoteHost() + "<br>");
 
        chain.doFilter(request, response);
        
        //在目标返回后写入响应内容
        out.println("<br>名称为encoding的初始化参数的值为:" + paramValue);
        out.println("<br>当前Web程序的真实路径为:" + filterConfig.getServletContext().getRealPath("/"));
        
        //out.println("<br>修改了test.html文件!");
    }
    
    @Override
    public void destroy() {
        this.filterConfig = null;
    }
}
<filter>
    <filter-name>FirstFilter</filter-name>
    <filter-class>FirstFilter</filter-class>
    <init-param>
    <param-name>encoding</param-name>
    <param-value>GB2312</param-value>
    </init-param>
</filter>
    
<filter-mapping>
    <filter-name>FirstFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
test.html(位于WebContent路径的filter目录中)
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
这就是test.html页面的原始内容!
</body>
</html>

访问:http://localhost:8888/testFilter_001/filter/test.html

原文地址:https://www.cnblogs.com/dousil/p/12895334.html