SpringMVC之过滤器(Filter)

一、概述

1.1 含义

过滤器是Web三大组件之一,也是项目中常用的工具。过滤器由Servlet提供,基于函数回调实现链式对网络请求和响应的拦截与修改。由于基于Servlet,几乎可以拦截Web服务器管理的所有资源(JSP、图片文件、HTML文件、CSS文件等)。

定义过滤器需要实现javax.servlet.Filter接口。过滤器不是Servlet,无法直接生成对客户端的响应,只能拦截已有请求并预处理不需要或不一致的信息资源。

1.2 流程原理

Web应用中,可以开发编写多个过滤器,这些过滤器组合称为过滤器链。用户发起请求后,请求信息会按过滤器链中过滤器的顺序依次进入每个过滤器。经过每层过滤器时,需通过过滤器的校验逻辑并放行才能进入下一层过滤器,直至服务器获取资源。服务器成功获取资源并响应过滤器后,会按反向顺序经过层层过滤器,最终响应用户。

1.3 分类

Servlet 2.5:

  • REQUEST: 用户直接访问页面时,WEB容器会调用过滤器链。
  • FORWARD: 通过RequestDispatcherforward访问目标资源时调用此过滤器。
  • INCLUDE: 通过RequestDispatcherinclude方法调用目标资源时调用。
  • ERROR: 通过声明式异常处理机制调用目标资源时调用过滤器链。

Servlet 3.0:

  • ASYNC: 支持异步处理。

二、定义过滤器

返回值类型 方法声明 描述
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 实现实际过滤操作。当客户端请求方法与过滤器设置的URL匹配时,Servlet容器会先调用过滤器的doFilter方法。FilterChain用于访问后续过滤器。
void init(FilterConfig filterConfig) Web应用启动时,Web服务器创建过滤器实例对象并调用其init方法完成对象初始化(过滤器对象仅创建一次,init方法仅执行一次)。开发者可通过init方法参数执行读取配置文件等初始化操作。
void destroy() Servlet容器销毁过滤器实例前调用此方法。用于释放过滤器占用的资源。
  • request: 代表客户端的请求对象。
  • response: 代表服务器向客户端发送的响应对象。
  • chain: 用于调用下一个Filter或目标ServletFilterChain对象。

三、使用过滤器

3.1 注解方式

创建步骤:

  1. 实现Filter接口,添加@WebFilter@Order注解配置过滤器:

    java 复制代码
    @Order(1)
    @WebFilter(filterName = "myFilter", urlPatterns = {"*"})
    public class MyCustomFilter1 implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {}
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                             FilterChain filterChain) {
            //TODO...
        }
    
        @Override
        public void destroy() {}
    }
  2. 在启动类添加@ServletComponentScan注解:

    java 复制代码
    @SpringBootApplication
    @ServletComponentScan
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }

3.2 注册Bean方式

  1. 创建实现Filter接口的过滤器类:

    java 复制代码
    public class MyCustomFilter2 implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException { }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                             FilterChain filterChain) {
            //TODO...
        }
    
        @Override
        public void destroy() { }
    }
  2. 创建过滤器配置类,注册过滤器:

    java 复制代码
    @Configuration
    public class FilterConfig {
        @Bean
        public FilterRegistrationBean customFilter(){
            FilterRegistrationBean<MyCustomFilter2> filterBean = new FilterRegistrationBean<>();
            filterBean.setFilter(new MyCustomFilter2());
            filterBean.setName("myFilter");
            filterBean.addUrlPatterns("/*");
            return filterBean;
        }
    }

四、注解方式

4.1 参数说明

@WebFilter可配置多个参数,部分参数说明如下:

参数名称 参数类型 参数描述
description String 设置过滤器的描述信息
displayName String 要显示的过滤器名称
initParams WebInitParam[] 你可以在初始化时配置一些参数
filterName String 过滤器的名称
servletNames String[] 设置要过滤的Servlets
value String[] urlPatterns属性与urlPatterns属性的作用相同,两者都指定要拦截的路径
urlPatterns String[] 指定要拦截的路径
dispatcherTypes DispatcherType[] 设置过滤器过滤的请求类型。 支持以下属性:REQUEST(默认情况下,它过滤所有类型的请求), ASYNC, ERROR, FORWARD, INCLUDE
asyncSupported boolean 设置过滤器是否支持异步模式

4.2 使用示例

(1) 创建Controller类

java 复制代码
@RestController
public class TestController {

    @GetMapping("/a/hello")
    public String hello1() {
        return "hello world! a";
    }

    @GetMapping("/b/hello")
    public String hello2() {
        return "hello world! b";
    }

    @GetMapping("/c/hello")
    public String hello3() {
        return "hello world! c";
    }
}

(2) 创建过滤器类

java 复制代码
@Order(1)
@WebFilter(filterName = "myFilter", urlPatterns = {"/a/*", "/b/*"}, description = "自定义过滤器")
public class MyCustomFilter2 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) {
        System.out.println("过滤器初始化");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("请求处理前...");
        chain.doFilter(request, response);  // 放行请求
        System.out.println("请求处理后...");
    }

    @Override
    public void destroy() {
        System.err.println("过滤器销毁");
    }
}

(3) 创建启动类

java 复制代码
@SpringBootApplication
@ServletComponentScan
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

五、注册Bean方式

5.1 方法参数说明

方法名称 方法描述
setName() 设置过滤器的名称。
setFilter() 设置要注册的过滤器。
setOrder() 设置过滤器的顺序位置。
setAsyncSupported() 设置过滤器是否支持异步模式。
addUrlPatterns() 添加拦截的路径。
setUrlPatterns() 设置拦截的路径。
addServletNames() 添加过滤器的servlet名称。
setServletNames() 设置注册过滤器的servlet名称。
setInitParameters() 设置初始化参数。
addInitParameter() 添加初始化参数。
setMatchAfter() 设置是否在Servlet上下文中声明的任何过滤器映射之后匹配过滤器映射。
setDispatcherTypes() 设置过滤器过滤的请求类型。 支持的属性如下:REQUEST(默认情况下,它过滤所有类型的请求), ASYNC, ERROR, FORWARD, INCLUDE。

5.2 使用示例

(1) 创建Controller类

java 复制代码
@RestController
public class TestController {

    @GetMapping("/a/hello")
    public String hello1(){
        return"hello world! a";
    }

    @GetMapping("/b/hello")
    public String hello2(){
        return"hello world! b";
    }

    @GetMapping("/c/hello")
    public String hello3(){
        return"hello world! c";
    }
}

(2) 创建过滤器类

java 复制代码
public class MyCustomFilter1 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) {
        System.out.println("过滤器初始化");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("请求处理前...");
        chain.doFilter(request, response);  // 放行请求
        System.out.println("请求处理后...");
    }

    @Override
    public void destroy() {
        System.err.println("过滤器销毁");
    }
}

(3) 创建过滤器配置类

java 复制代码
@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean customFilter() {
        FilterRegistrationBean<MyCustomFilter1> filterBean = new FilterRegistrationBean<>();
        filterBean.setFilter(new MyCustomFilter1());
        filterBean.setName("FilterController");
        filterBean.addUrlPatterns("/c/*", "/b/*");
        return filterBean;
    }
}

(4) 创建启动类

java 复制代码
@SpringBootApplication
@ServletComponentScan
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

六、使用场景

  1. 日志记录
    过滤器可记录请求和响应的关键信息,便于排查问题和分析系统运行状态。例如记录请求URL、参数、响应状态码等。
  2. 数据统计
    用于采集各类数据指标,如统计请求次数、响应时间分布等,为系统优化提供依据。
  3. 数据格式转换
    不同系统交互时,过滤器可转换数据格式,例如将JSON转为XML
  4. 为数据设置默认值
    检查输入数据,为缺失字段设置默认值,保证数据完整性。
  5. 权限认证、黑白名单
    实现用户权限认证和访问控制,限制特定IP或用户的访问。
  6. 数据加解密、签名验证
    对敏感数据加解密以保证安全,同时进行签名验证确保数据完整性。
相关推荐
用户969996281575 分钟前
PostGreSQL docker 拉取以及部署流程
后端
想用offer打牌12 分钟前
seata要支持Oracle批量插入的语法了吗?
后端·架构·开源
Lisonseekpan1 小时前
IntelliJ IDEA 快捷键全解析与高效使用指南
java·ide·后端·intellij-idea
q***71851 小时前
常见的 Spring 项目目录结构
java·后端·spring
IT_陈寒2 小时前
Java 17实战:我从老旧Spring项目迁移中总结的7个关键避坑点
前端·人工智能·后端
q***06292 小时前
环境安装与配置:全面了解 Go 语言的安装与设置
开发语言·后端·golang
楼田莉子3 小时前
C++/Linux小项目:自主shell命令解释器
linux·服务器·开发语言·c++·后端·学习
用户298698530143 小时前
Java: 为PDF批量添加图片水印实用指南
java·后端·api
昨天的猫3 小时前
《拒绝重复代码!模板模式教你优雅复用算法骨架》
后端·设计模式