[10] 过滤器 Filter


1、过滤器的基本概念和作用

在网站的页面访问时,我们往往需要做一些控制,如普通用户无法访问VIP用户的页面。如果在每一个需要访问控制的文件中都加上判断代码,那么代码将会很冗余,一旦需要统一修改时也极其繁琐。

过滤器就可以解决这样的问题,配置完成的过滤器,会强制让指定的页面在访问之前先从过滤器走一趟。

“漏斗”的图片搜索结果

2、过滤器相关的API

Servlet API中,与过滤器有关的API共有三个接口,分别是:
  • Filter
  • FilterChain (在Filter中init方法作为参数)
  • FilterConfig (在Filter中doFilter方法作为参数)

Filter接口
Filter接口是我们自定义的过滤器类必须要实现的接口,该接口有三个方法:
  • init(FilterConfig filterConfig)
  • 该方法是对Filter对象进行初始化的方法,仅在容器初始化Filter对象结束后被调用一次,其中FilterConfig可以获取初始化参数

  • doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  • 该方法是Filter进行过滤操作的方法,是最重要的方法。我们自定义的过滤器类都要实现该方法。
  • 方法体中可以对请求和响应进行预处理,FilterChain则可以将处理后的请求响应传递到过滤链上的下一个资源

  • destroy()
  • 该方法在容器销毁过滤器对象之前被调用

可以看到,其他两个接口是分别作为参数在Filter接口的方法中进行使用。它们的作用在于:

FilterConfig接口
该接口类型作为Filter接口中init方法的参数使用,这个接口有一个常用方法:
  • getInitParameter(String name)
  • 该方法用来获取过滤器的初始化参数,这个初始化参数在web.xml中进行配置,方式和Servlet初始化参数类似

FilterChain接口
该接口类型作为Filter接口中doFilter方法的参数使用,这个接口有一个方法:
  • doFilter(ServletRequest request, ServletResponse response)
  • 该方法可以将当前请求和相应传递到过滤链上的下一个资源,可能是下个过滤器,也可能是目标资源

3、示例:过滤器限制页面访问时间

实现这样的功能,某个页面,在规定的时间内才能访问,否则跳转到通知页面,告知未到开放时间,暂时无法访问。

可以通过修改系统的时间,来完成过滤器的效果测试:

3.1 创建jsp页面

创建四个jsp页面:index、login、home和notice,文件放置目录结构如下:

3.2 自定义过滤器

自定义过滤器,读取初始参数配置,并判断是否符合要求,根据需要进行页面跳转:
public class TimeFilter implements Filter { 
    private int start = 0;
    private int end = 24;

    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("TimeFilter初始化,开始抓取初始化参数");
        start = Integer.parseInt(filterConfig.getInitParameter("start"));
        end = Integer.parseInt(filterConfig.getInitParameter("end"));
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("TimeFilter过滤");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        int curHour = calendar.get(Calendar.HOUR_OF_DAY);
        if (curHour >= end || curHour < start) {
            request.setAttribute("start", start);
            request.setAttribute("end", end);
            request.getRequestDispatcher("/WEB-INF/notice.jsp").forward(request, response);
        }
        
        chain.doFilter(request, response);
    }

    public void destroy() {
        System.out.println("TimeFilter爆炸");
    }
}

3.3 配置web.xml和初始化参数

在web.xml中配置过滤器的具体类,以及过滤的资源和过滤器初始化的参数:
<filter>
    <filter-name>timeFilter</filter-name>
    <filter-class>com.zker.TimeFilter</filter-class>
    <init-param>
        <param-name>start</param-name>
        <param-value>15</param-value>
    </init-param>
    <init-param>
        <param-name>end</param-name>
        <param-value>22</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>timeFilter</filter-name>
    <url-pattern>/limit/*</url-pattern>
</filter-mapping>

4、Filter使用总结和配置说明

  • 首先要实现Filter接口
  • 自定义的过滤方法写在doFilter方法体中,最后并通过形参 FilterChain 的 doFilter(request, response) 方法传递请求和响应
  • 然后要在web.xml中进行配置,包括过滤器的具体类,过滤文件,初始参数等

关于配置文件的部分说明:
  • <filter>  定义Filter的具体类
  • <init-param>  定义初始化参数
  • <filter-mapping>  定义过滤器的限制目录

在<filter-mapping>中实际上还可以通过 <dispatcher> 配置请求方式的过滤:
<filter-mapping>
    <filter-name>timeFilter</filter-name>
    <url-pattern>/limit/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

<dispatcher>配置表示哪些请求传递方式到如上的/limit/*时需要被过滤,默认不写的话为REQUEST
(假如我只写了REQUEST,而没写FORWARD,那么通过转发方式到达的/limit/*的资源,就不会被过滤)


posted @ 2017-09-01 13:59  Dulk  阅读(464)  评论(0编辑  收藏  举报