【Spring MVC 系列】Spring MVC 中 Filter 配置的 6 种方式,看看你了解哪些

简介: Filter 简介过滤器 Filter 在 Servlet 2.3 版本中被首次提出,唯一的作用就是过滤,它不仅可以过滤请求,还可以过滤响应,当请求到达 Servlet 容器,会先经过 Filter ,然后再交给 Servlet,之后 Filter 还可以对 Servlet 的响应进一步处理。并且多个 Filter 还能形成一个链。使用图示表达如下。

Filter 简介


过滤器 Filter 在 Servlet 2.3 版本中被首次提出,唯一的作用就是过滤,它不仅可以过滤请求,还可以过滤响应,当请求到达 Servlet 容器,会先经过 Filter ,然后再交给 Servlet,之后 Filter 还可以对 Servlet 的响应进一步处理。并且多个 Filter 还能形成一个链。使用图示表达如下。


image.png


Filter 的特性使得 Filter 可以对请求或响应进行包装,修改请求头、请求体、响应头、响应体。由于请求先到达 Filter,Filter 还可以做一些全局性的工作,例如日志打印、登录校验等等。


Filter 生命周期


Filter 作为一个接口,具体实现由用户负责,先看这个接口的定义。


public interface Filter {
    public void init(FilterConfig filterConfig) throws ServletException;
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
    public void destroy();
}


Filter 中定义了三个方法。


init:这是 Filter 的初始化方法,这个方法只会被容器调用一次,方法参数 FilterConfig 表示 Filter 的配置,可以利用这个参数读取初始化参数、ServletContext 等。

doFilter:这是 Filter 处理请求的核心方法,当请求到达时容器先回调这个方法处理请求,除了 request、response,这个方法还可以拿到过滤器链 FilterChain 对象,只有调用了 FilterChain#doFilter方法,容器才会使用过滤器链中的下一个过滤器处理请求,如果当前 Filter 已经是链中的最后一个,则会交给 Servlet 处理。

destroy:容器停止时回调的方法,用于做一些资源清理的工作。

Spring MVC 内置 Filter

针对一些通用的场景,Spring MVC 内置了一些 Filter,下面看常用的有哪些。


CharacterEncodingFilter:用于设置请求体、响应体字符集的过滤器,使用这个过滤器可以统一字符编码,避免出现乱码现象。

CorsFilter:这是用来处理跨域的过滤器,请求到达这个过滤器时,会根据配置添加跨域相关的响应头。


FormContentFilter:对于请求方法为PUT、PATCH、DELETE,内容类型为表单application/x-www-form-urlencoded的请求,请求体中的参数无法通过 ServletRequest#getParameter 方法读取,这个过滤器对请求已经包装,以便可以通过 #getParameter 方法读取参数。

Spring MVC 中的 Filter 配置

自从 Spring MVC 提供拦截器 HandlerInterceptor 之后,过滤器 Filter 的一部分功能已经可以搬到拦截器了,但有时还是会不可避免的使用到过滤器,如跨域处理。因此需要自定义过滤器 Filter,并配置到 Servlet 容器中,Spring MVC 在不同的阶段也提供了不同的配置方案,具体来说主要有 6 种。


1. 配置文件 web.xml 配置


Spring MVC 基于 Servlet 规范,Spring 早期,Servlet 和 Filter 配置方式与传统的 Java Web 项目并没有任何区别,需要在 web.xml 配置 Filter 清单。示例如下。


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
          http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <filter>
        <filter-name>cors</filter-name>
        <filter-class>com.zzuhkp.mvc.CorsFilter</filter-class>
        <init-param>
            <param-name>allowedMethods</param-name>
            <param-value>GET,POST</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>cors</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>


2. @WebFilter 注解配置


Java 5 注解诞生后,Servlet 在 3.0 新引入了 @WebFilter 注解,用来替代 web.xml 文件中 Filter 的配置。Servlet 容器启动后会扫描类路径下的文件,遇到携带 @WebFilter 的注解后就会将这个类注册到容器中。因此在 Spring MVC 环境下也可以直接使用这个注解,和 xml 配置等同的注解配置如下。


@WebFilter(urlPatterns = "/*", initParams = {@WebInitParam(name = "allowedMethods", value = "GET,POST")})
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        chain.doFilter(request, response);
    }
}


3. ServletContainerInitializer 配置


除了常规的 Servlet 规范中的 xml 和 @WebFilter 配置方式, Servlet 3.0 规范还提供了一个 ServletContainerInitializer 接口,Servlet 容器启动后会扫描类路径,标注了 @HandlesTypes 注解的 ServletContainerInitializer 接口实现将会被回调。因此,在 Spring MVC 中也可以利用这个特性添加 Filter,具体代码如下。


@HandlesTypes({})
public class FilterInitializer implements ServletContainerInitializer {
    @Override
    public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
        FilterRegistration.Dynamic dynamic = ctx.addFilter("cors", new CorsFilter());
        dynamic.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
        dynamic.setInitParameter("allowedMethods","GET,POST");
    }
}


4. WebApplicationInitializer 配置


Spring 3.1 版本利用了上述 Servlet 规范中 ServletContainerInitializer 的特性,提供了这个接口的实现 SpringServletContainerInitializer,并在实现中回调了 Spring 提供的 WebApplicationInitializer 接口。因此,Spring MVC 环境也可以直接实现 WebApplicationInitializer 来手动配置 Filter。注意:只需要实现接口,无需特定配置,Servlet 容器会把这个类告诉 SpringServletContainerInitializer。示例代码如下。


public class CorsWebApplicationInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        FilterRegistration.Dynamic dynamic = servletContext.addFilter("cors", new CorsFilter());
        dynamic.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
        dynamic.setInitParameter("allowedMethods", "GET,POST");
    }
}


5. Spring Bean 配置


除了普通 Spring MVC 环境下的配置,Spring Boot 环境中,Spring Boot 1.4 及之后版本下还可以直接将 Filter 注册为 Bean,Filter Bean 将应用到所有的请求中。示例代码如下。


@Component
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        chain.doFilter(request, response);
    }
}


6. FilterRegistrationBean 配置


FilterRegistrationBean 同样是 Spring Boot 1.4 版本提出的一个新类型,这个类允许指定过滤的请求路径,将这个类配置为 Bean 即可。示例代码如下。


@Configuration
public class MvcConfig {
    @Bean
    public FilterRegistrationBean<CorsFilter> filterRegistrationBean() {
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter());
        bean.addUrlPatterns("/*");
        bean.addInitParameter("allowedMethods", "GET,POST");
        return bean;
    }
}


总结

本文主要对 Filter 的概念做了简单介绍,并介绍了几种 Spring MVC 内置的 Filter,最后介绍了 6 种在 Spring MVC 配置 Filter 的方式,其中 web.xml、@WebFilter、ServletContainerInitializer、WebApplicationInitializer 这 4 种配置方式适用于普通的 Spring MVC 环境,Filter Bean 配置、FilterRegistrationBean Bean 配置 适用于 Spring Boot 环境下的 Spring MVC,读者需要加以留意。


目录
相关文章
|
6天前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
56 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
6天前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
7天前
|
Java 数据库连接 Maven
Spring基础1——Spring(配置开发版),IOC和DI
spring介绍、入门案例、控制反转IOC、IOC容器、Bean、依赖注入DI
Spring基础1——Spring(配置开发版),IOC和DI
|
18天前
|
IDE Java 开发工具
还在为繁琐的配置头疼吗?一文教你如何用 Spring Boot 快速启动,让开发效率飙升,从此告别加班——打造你的首个轻量级应用!
【9月更文挑战第2天】Spring Boot 是一款基于 Spring 框架的简化开发工具包,采用“约定优于配置”的原则,帮助开发者快速创建独立的生产级应用程序。本文将指导您完成首个 Spring Boot 项目的搭建过程,包括环境配置、项目初始化、添加依赖、编写控制器及运行应用。首先需确保 JDK 版本不低于 8,并安装支持 Spring Boot 的现代 IDE,如 IntelliJ IDEA 或 Eclipse。
57 5
|
20天前
|
Java Spring 开发者
解锁 Spring Boot 自动化配置的黑科技:带你走进一键配置的高效开发新时代,再也不怕繁琐设置!
【8月更文挑战第31天】Spring Boot 的自动化配置机制极大简化了开发流程,使开发者能专注业务逻辑。通过 `@SpringBootApplication` 注解组合,特别是 `@EnableAutoConfiguration`,Spring Boot 可自动激活所需配置。例如,添加 JPA 依赖后,只需在 `application.properties` 配置数据库信息,即可自动完成 JPA 和数据源设置。这一机制基于多种条件注解(如 `@ConditionalOnClass`)实现智能配置。深入理解该机制有助于提升开发效率并更好地解决问题。
33 0
|
20天前
|
Java Spring 开发者
Spring 框架配置属性绑定大比拼:@Value 与 @ConfigurationProperties,谁才是真正的王者?
【8月更文挑战第31天】Spring 框架提供 `@Value` 和 `@ConfigurationProperties` 两种配置属性绑定方式。`@Value` 简单直接,适用于简单场景,但处理复杂配置时略显不足。`@ConfigurationProperties` 则以类级别绑定配置,简化代码并更好组织配置信息。本文通过示例对比两者特点,帮助开发者根据具体需求选择合适的绑定方式,实现高效且易维护的配置管理。
29 0
|
22天前
|
缓存 Java 数据库连接
Spring Boot 资源文件属性配置,紧跟技术热点,为你的应用注入灵动活力!
【8月更文挑战第29天】在Spring Boot开发中,资源文件属性配置至关重要,它让开发者能灵活定制应用行为而不改动代码,极大提升了可维护性和扩展性。Spring Boot支持多种配置文件类型,如`application.properties`和`application.yml`,分别位于项目的resources目录下。`.properties`文件采用键值对形式,而`yml`文件则具有更清晰的层次结构,适合复杂配置。此外,Spring Boot还支持占位符引用和其他外部来源的属性值,便于不同环境下覆盖默认配置。通过合理配置,应用能快速适应各种环境与需求变化。
27 0
|
1月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
31 0
|
4月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
148 0
|
4月前
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
64 0