用户授权、日志记录、编码解码、UA分析、多端应用等都需要拦截请求来进行处理。这时就需要 ServletFilterListenerInterceptor 这几种组件。本章主要讲解Filter的用法。

Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。Filter是可以复用的代码片段,常用来转换 HTTP 请求、响应和 头信息。Filter不像Servlet,它不能产生响应,而是只修改对某一资源的请求或者响应。

一、自定义过滤器

这里模拟登陆过程:拦截所有的请求,放行登录页面,其余请求全部重定向到登陆界面。同时配置参数,指定要放行的路径和请求的字符集。

public class LoginFilter implements Filter {
    private FilterConfig config;

    @Override
    public void init(FilterConfig config) throws ServletException {
        this.config = config;
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        // 获取配置参数
        String loginUI = config.getInitParameter("loginUI");
        String encoding = config.getInitParameter("encoding");


        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        // 设置请求的字符集(post请求方式有效)
        request.setCharacterEncoding(encoding);

        // 不带http://域名:端口的地址
        String uri = request.getRequestURI();
        if (uri.contains(loginUI)) {
            // 请求的登录,放行
            chain.doFilter(request, response);
        } else {
      // 重定向到登录页面
      response.sendRedirect(request.getContextPath() + loginUI);
        }
    }

    @Override
    public void destroy() {
        this.config = null;
    }
}

LoginFilter初始化时,会执行init()方法。每次请求路径匹配urlPatterns 配置的路径时,就会进入doFilter()方法进行具体的请求和响应过滤。
当HTTP请求路径包含/home/loginUrl时,请求会被放行;否则,直接重定向到首页,结束请求处理。

doFilter的参数说明:
1. ServletRequest: 未到达 Servlet 的 HTTP 请求
2. ServletResponse: 由 Servlet 处理并生成的 HTTP 响应
3. FilterChain: 过滤器链对象,可以按顺序注册多个过滤器
一个过滤器链对象可以按顺序注册多个过滤器。符合当前过滤器过滤条件,即请求过滤成功直接放行,则交由下一个过滤器进行处理。
所有请求过滤完成以后,由IndexHttpServlet处理并生成响应,然后在过滤器链以相反的方向对响应进行后置过滤处理。

二、注册过滤器

1. 通过@WebFilter配置

在自定义的过滤器上添加@WebFilter

@WebFilter(filterName = "loginFilter",
    urlPatterns = "/*",
    initParams = {
            @WebInitParam(name = "loginUI", value = "/home/loginUrl"),
            @WebInitParam(name = "encoding", value = "UTF-8")
    })
@Order(1) //过滤顺序

@WebFilter常用属性

属性

类型

是否必需

说明

asyncSupported

boolean


指定Filter是否支持异步模式

dispatcherTypes

DispatcherType[]


指定Filter对哪种方式的请求进行过滤。支持的属性:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST;默认过滤所有方式的请求

filterName

String


Filter名称

initParams

WebInitParam[]


配置参数

displayName

String


Filter显示名

servletNames

String[]


指定对哪些Servlet进行过滤

urlPatterns/value

String[]


两个属性作用相同,指定拦截的路径

注意: 添加此注解的类必须得在启动类的扫描目录下

2. 通过注册配置类使用过滤器
@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean someFilterRegistration1() {
        //新建过滤器注册类
        FilterRegistrationBean registration = new FilterRegistrationBean();
        // 添加我们写好的过滤器
        registration.setFilter( new LoginFilter());
        // 设置过滤器的URL模式
        registration.addUrlPatterns("/*");
        // 设置过滤器配置参数
        registration.addInitParameter("loginUI", "/home/loginUrl");
        registration.addInitParameter("encoding", "UTF-8");
        // 设置过滤器名称
        registration.setName("loginFilter");
        //设置过滤顺序,从小到大依次执行
        registration.setOrder(1);
        return registration;
    }
}

注意: 此配置类必须得在启动类的扫描目录下

3. web.xml

以上两种配置Spring Boot的常用使用,其对应的xml配置如下:

<filter>
    <filter-name>loginFilter</filter-name>
    <filter-class>com.simon.filter.LoginFilter</filter-class>
    <init-param>
        <param-name>loginUI</param-name>
        <param-value>/home/loginUrl</param-value>
    </init-param>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>loginFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>