2.9 Filter介绍 2.9.1 创建Filter类

2.9 Filter介绍

Filter可认为是Servlet的一种“加强版”,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链。Filter也可对用户请求生成响应,这一点与Servlet相同,但实际上很少会使用Filter向用户请求生成响应。

使用Filter的流程

使用Filter完整的流程是:

  • Filter对用户请求进行预处理,
  • 接着将请求交给Servlet进行处理并生成响应,
  • 最后Filter再对服务器响应进行后处理。

Filter用途

Filter有如下几个用处:

  • HttpServletRequest到达Servlet之前,拦截客户的HttpservletRequest
  • 根据需要检查HttpservletRequest,也可以修改HttpServletRequest头和数据。
  • HttpservletResponse到达客户端之前,拦截HttpServletResponse
  • 根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据

Filter有如下几个种类。

  • 用户授权的Filter:Filter负责检查用户请求,根据请求过滤用户非法请求。
  • 日志Filter:详细记录某些特殊的用户请求
  • 负责解码的Filter:包括对非标准编码的请求解码。
  • 能改变XML内容的XSLTFilter等。
  • Filter可负责拦截多个请求或响应:一个请求或响应也可被多个Filter拦截。

创建Filter步骤

创建一个Filter只需两个步骤

  1. 创建Filter处理类。
  2. web.Xml文件中配置Filter或用注解配置Filter

2.9.1 创建Filter类

Filter接口方法

创建Filter必须实现javax.servlet.Filter接口,在该接口中定义了如下三个方法:

  1. void init(FilterConfig config):用于完成Filter的初始化。
  2. void destroy():用于Filter销毁前,完成某些资源的回收。
  3. void dofilter(ServletRequest request, ServletResponse response, FilterChain chain):实现过滤功能,该方法就是对每个请求及响应增加的额外处理。

LogFilter.java

下面介绍一个日志Filter,这个Filter负责拦截所有的用户请求,并将请求的信息记录在日志中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package lee;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.*;

@WebFilter(filterName = "log", urlPatterns = { "/*" })
public class LogFilter implements Filter {
// FilterConfig可用于访问Filter的配置信息
private FilterConfig config;

// 实现初始化方法
public void init(FilterConfig config) {
this.config = config;
}

// 实现销毁方法
public void destroy() {
this.config = null;
}

// 执行过滤的核心方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// ---------下面代码用于对用户请求执行预处理---------
// 获取ServletContext对象,用于记录日志
ServletContext context = this.config.getServletContext();
long before = System.currentTimeMillis();
System.out.println("开始过滤...");
// 将请求转换成HttpServletRequest请求
HttpServletRequest hrequest = (HttpServletRequest) request;
// 输出提示信息
System.out.println("Filter已经截获到用户的请求的地址: " + hrequest.getServletPath());
// Filter只是链式处理,请求依然放行到目的地址
chain.doFilter(request, response);
// ---------下面代码用于对服务器响应执行后处理---------
long after = System.currentTimeMillis();
// 输出提示信息
System.out.println("过滤结束");
// 输出提示信息
System.out.println("请求被定位到" + hrequest.getRequestURI() + " 所花的时间为: " + (after - before));
}
}

上面的程序中实现了doFilter方法,实现doFilter方法就可实现对用户请求进行预处理,也可实现对服务器响应进行后处理

预处理和后处理的分界线为是否调用了chain.doFilte(r),执行该方法之前,即对用户请求进行预处理;执行该方法之后,即对服务器响应进行后处理.
在上面的请求Filter中,仅在日志中记录请求的URL,对所有的请求都执行chain do Filter( request, reponse)方法,当Filter对请求过滤后,依然将请求发送到目的地址。

使用Filter进行权限检查

如果需要检查权限,可以在Filter中根据用户请求的Httpsession,判断用户权限是否足够。如果权限不够,直接调用重定向即可,无须调用chain.doFilter(request,reponse)方法。