JavaWeb—过滤器Filter

1.Filter简介

Filter称之为过滤器,是用来做一些拦截的任务。比如客户端请求服务器的某个资源时(可以是Servlet、JSP、HTML等等),我们可以拦截。当服务器返回资源给客户端的时候,我们也可以拦截。这样我们就可以在调用资源之前和之后分别加入一些业务逻辑。

当我们对某个资源加上多个过滤器的时候,就形成了过滤链。请求(request)会依次通过链上的过滤器,响应(response)会依次以相反的顺序通过过滤器。

 

2.Filter源码分析

Filter接口源代码:

public interface Filter {
    void init(FilterConfig var1) throws ServletException;

    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

    void destroy();
}

2.1 FilterConfig

当容器去初始化一个filter的时候,就会根据web.xml文件的配置和当前的运行环境去构造一个FilterCongif实例并传给filter。所以一个filter对应一个FilterConfig实例。

public interface FilterConfig {
    String getFilterName();

    ServletContext getServletContext();

    String getInitParameter(String var1);

    Enumeration getInitParameterNames();
}

getFilterName方法返回我们在web.xml里面配置的名称。

getServletContext返回ServletContext实例,这个和之前介绍Servlet的时候讲到的是一个东西。一个应用就一个ServletContext实例。

getInitParameter和getInitParameterNames和Servlet的类似。就是获取在web.xml里面配置的初始化参数。

2.2 FilterChain

FilterChain就是我们上面说的过滤链,当请求或响应被filter拦截时,容器提供FilterChain实例给filter让其使用。

public interface FilterChain {
    void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;
}

FilterChain里面就一个方法doFilter,这个方法就是调用过滤链的下一个filter,如果当前filter是链中最后的一个,则跳转至请求的资源或返回响应给客户端。

2.3 Filter

Filter里面有三个方法,也是它的生命周期。

2.3.1 init

filter的初始化方法,跟servlet一样在其生命周期内只会被执行一次。但是filter初始化的时机和servlet不一样,当servlet容器(比如Tomcat)启动完成后就会检索web.xml里面配置的filter,从上往下依次回调每个filter的init方法对其进行初始化。(这里的filterConfig参数是容器构造并传入的。)

2.3.2 doFilter

实现拦截逻辑的地方,比如一个请求被拦截,这里可以在调用具体资源之前编写一些业务逻辑。然后调用chain.doFilter流转到后置filter,如果当前filter是链中最后的一个,则跳转至请求的资源。当chain.doFilter执行完成后,可以再写一些业务逻辑。然后容器将执行权流转到前置filter,如果当前filter是链中最前的一个,则将响应返回给客户端。(这里的参数chain是容器构造并传入的。)

2.3.3 destory

和servlet的destroy方法同样的道理,当servlet容器关闭或需要更多内存的时候,会销毁filter。这个方法就使得servlet容器拥有回收资源的能力。

同样地,destroy方法在filter的生命周期中只会被调用一次。

 

3.Java编写Filter实例

Filter开发分为2步:

  1. 编写java类实现Filter接口,并实现其doFilter方法。
  2. 在web.xml 文件中使用<filter>和<filter-mapping>元素对编写的filter类进行注册,并设置它所能拦截的资源。

注意:web.xml 中的 filter-mapping 元素的顺序决定了 Web 容器应用过滤器到 Servlet 的顺序

Filter接口实现类

package com.xzh;

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;

/**
 * Created by xiangzh on 2017/8/29.
 */
public class FilterDemo implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("--------Filter初始化--------");

        // 获取初始化参数
        String site = filterConfig.getInitParameter("param");
        System.out.println("参数测试: " + site);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("-----------方法执行前处理-----------");
        // 把请求传回过滤链
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("-----------方法执行后处理-----------");
    }

    @Override
    public void destroy() {
        /* 在 Filter 实例被 Web 容器从服务移除之前调用 */
    }
}

web.xml配置filter

<filter>
        <filter-name>FilterDemo</filter-name>
        <filter-class>com.xzh.FilterDemo</filter-class>
        <init-param>
            <param-name>param</param-name>
            <param-value>这是一个测试参数</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>FilterDemo</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

这里需要注意的是,filter可以对url进行过滤,也可以针对具体的servlet进行过滤,只需要制定servlet的名称,如: 

<servlet>
        <servlet-name>ServletDemo</servlet-name>
        <servlet-class>com.xzh.ServletDemo</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>ServletDemo</servlet-name>
        <url-pattern>/ServletDemo</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>FilterDemo</filter-name>
        <filter-class>com.xzh.FilterDemo</filter-class>
        <init-param>
            <param-name>param</param-name>
            <param-value>这是一个测试参数111</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>FilterDemo</filter-name>
        <servlet-name>ServletDemo</servlet-name>
    </filter-mapping>

效果截图

上例中,在web.xml中设置了参数,并在filter中获取。

结果中,init()方法初始化执行一次,doFilter()方法访问一次执行一次。 

 

 

 

参考:

JavaWeb——Filter

Java三大器之过滤器(Filter)的工作原理和代码演示

Java中的Filter过滤器

 

posted @ 2017-08-29 16:51  大象踢足球  阅读(520)  评论(0编辑  收藏  举报