【SpringBoot3】SpringBoot项目Web拦截器使用

server/2025/3/10 11:32:53/

在Spring Boot应用中,Web拦截器(Interceptor)是一种用于在请求处理的不同阶段执行自定义逻辑的机制。拦截器广泛应用于各种场景,以增强应用的功能性、安全性和可维护性。

在Spring Boot项目中实现Wen拦截器主要有以下几种方式

  • 实现 HandlerInterceptor 接口
  • 使用过滤器(Filter
  • 使用 @Aspect 注解实现AOP拦截

这里主要介绍 HandlerInterceptor 接口 和 Filter

一、实现 HandlerInterceptor 接口

这是最常见和直接的方式。需要创建一个类实现 org.springframework.web.servlet.HandlerInterceptor 接口,并重写其中的方法:

1、创建HandlerInterceptor实现类 MyInterceptor

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;@Slf4j
@Component
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info("preHandle");return HandlerInterceptor.super.preHandle(request, response, handler);}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {log.info("postHandle");HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {log.info("afterCompletion");HandlerInterceptor.super.afterCompletion(request, response, handler, ex);}
}

2、注册拦截器

实现完拦截器后,需要将其注册到Spring MVC的配置中。可以通过继承 WebMvcConfigurer 接口并重写 addInterceptors 方法来完成:

import jakarta.annotation.Resource;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Resourceprivate MyInterceptor myInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(myInterceptor).addPathPatterns("/**")//拦截所有请求.excludePathPatterns("/login");// 放行登录请求}
}

这里的myInterceptor 也可以直接new MyInterceptor()

3、运行测试

MyInterceptor         : preHandle
MyInterceptor         : postHandle
MyInterceptor         : afterCompletion

二、使用过滤器(Filter

虽然过滤器不属于拦截器的范畴,但在Spring Boot中,过滤器也是常用的请求处理组件。可以通过实现 javax.servlet.Filter 接口来创建自定义过滤器:

1、创建过滤器实现类

这里我创建了3个测试过滤器,分别是 MyFilterMyFilter2MyFilter2,代码都是相同的,只是打印内容不一样

@Slf4j
public class MyFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// 请求前处理log.info("MyFilter doFilter pre");filterChain.doFilter(servletRequest, servletResponse);// 响应后处理log.info("MyFilter doFilter after");}
}

2、使用@Component 注解配置过滤器

通过将过滤器类声明为Spring组件,Spring Boot会自动检测并注册它。

import org.springframework.stereotype.Component;@Component
public class MyFilter implements Filter {// 实现方法同上
}

注意:默认情况下,使用@Component注册的过滤器会被添加到过滤链中,但顺序可能不确定。如果需要指定顺序,建议使用其他注册方式。

3、通过配置类注册过滤器(FilterRegistrationBean)

通过FilterRegistrationBean可以更灵活地注册过滤器,包括设置过滤器的顺序、URL模式等。

  • 可以精确控制过滤器的顺序。
  • 可以指定过滤器应用的URL模式。
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<MyFilter> myFilter() {FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();bean.setFilter(new MyFilter());bean.addUrlPatterns("/*"); // 拦截所有请求bean.setOrder(1); // 设置过滤器顺序,数值越小优先级越高return bean;}@Beanpublic FilterRegistrationBean<MyFilter2> myFilter2() {FilterRegistrationBean<MyFilter2> bean = new FilterRegistrationBean<>();bean.setFilter(new MyFilter2());bean.addUrlPatterns("/*");bean.setOrder(2);return bean;}@Beanpublic FilterRegistrationBean<MyFilter3> MyFilter3() {FilterRegistrationBean<MyFilter3> bean = new FilterRegistrationBean<>();bean.setFilter(new MyFilter3());bean.addUrlPatterns("/*");bean.setOrder(3);return bean;}
}

运行测试

通过日志可以看见,order值越小优先级越高,过滤器的执行遵循先进后出的原则

c.hj.springboot3.filter.demo2.MyFilter   : MyFilter doFilter pre
c.hj.springboot3.filter.demo2.MyFilter2  : MyFilter2 doFilter pre
c.hj.springboot3.filter.demo2.MyFilter3  : MyFilter3 doFilter pre
c.h.s.filter.service.UserServiceImpl     : 执行业务代码
c.hj.springboot3.filter.demo2.MyFilter3  : MyFilter3 doFilter after
c.hj.springboot3.filter.demo2.MyFilter2  : MyFilter2 doFilter after
c.hj.springboot3.filter.demo2.MyFilter   : MyFilter doFilter after

三、使用OncePerRequestFilter

OncePerRequestFilter 是 Spring 框架提供的一个非常有用的过滤器基类,旨在确保某个过滤器在每个 HTTP 请求中只执行一次。这在需要确保某些处理逻辑(如身份验证、日志记录、请求修改等)在整个请求生命周期中不被重复执行时特别有用。

它的主要功能是确保其 doFilterInternal 方法在每个请求中仅被调用一次。这是通过检查请求属性来实现的,防止在某些情况下(如转发请求)过滤器被多次执行。

1 主要方法

  • doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain):这是需要子类实现的方法,在其中编写自定义的过滤逻辑。该方法保证在每个请求中只被调用一次。
  • shouldNotFilter(HttpServletRequest request):可以重写此方法来指定某些请求不需要被过滤。
  • doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain):这是 Filter 接口的方法,OncePerRequestFilter 已经实现了该方法,确保 doFilterInternal 只执行一次。

2. 使用 OncePerRequestFilter

2.1 创建自定义过滤器

要使用 OncePerRequestFilter,通常需要创建一个继承自它的子类,并实现 doFilterInternal 方法。

示例代码:

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;public class CustomOncePerRequestFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {// 请求预处理逻辑System.out.println("CustomOncePerRequestFilter: 请求前处理");// 继续过滤器链filterChain.doFilter(request, response);// 响应后处理逻辑System.out.println("CustomOncePerRequestFilter: 响应后处理");}
}
2.2 注册自定义过滤器

创建完自定义过滤器后,需要将其注册到 Spring Boot 应用中。可以使用 FilterRegistrationBean 进行注册。

示例代码:

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<CustomOncePerRequestFilter> customFilterRegistration() {FilterRegistrationBean<CustomOncePerRequestFilter> registration = new FilterRegistrationBean<>();registration.setFilter(new CustomOncePerRequestFilter());registration.addUrlPatterns("/*"); // 拦截所有请求registration.setName("customOncePerRequestFilter");registration.setOrder(1); // 设置过滤器顺序return registration;}
}

四、其他类似过滤器

1、CharacterEncodingFilter

简介CharacterEncodingFilter 用于设置请求和响应的字符编码,确保请求参数和响应内容的编码一致,防止乱码问题。

使用场景:在处理国际化应用或需要特定字符编码的场景下非常有用。

示例配置

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CharacterEncodingFilter;@Configuration
public class EncodingFilterConfig {@Beanpublic FilterRegistrationBean<CharacterEncodingFilter> characterEncodingFilter() {CharacterEncodingFilter filter = new CharacterEncodingFilter();filter.setEncoding("UTF-8");filter.setForceEncoding(true);FilterRegistrationBean<CharacterEncodingFilter> registration = new FilterRegistrationBean<>(filter);registration.addUrlPatterns("/*");registration.setName("characterEncodingFilter");registration.setOrder(1);return registration;}
}

2、HiddenHttpMethodFilter

简介HiddenHttpMethodFilter 用于将带有特殊参数(如 _method)的 POST 请求转换为对应的 HTTP 方法(如 PUT、DELETE)。这在 HTML 表单不支持某些 HTTP 方法时非常有用。

使用场景:在使用 RESTful API 且前端仅支持 POST 请求时,通过隐藏字段指定实际的 HTTP 方法。

启用方式

在 Spring Boot 中,默认情况下,HiddenHttpMethodFilter 是启用的。如果需要自定义,可以手动注册:

@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter() {return new HiddenHttpMethodFilter();
}

3、CorsFilter

简介CorsFilter 用于处理跨域资源共享(CORS)配置,允许或限制来自不同源的请求。

使用场景:在构建需要与前端分离的应用,且前端和后端部署在不同域时。

示例配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;@Configuration
public class CorsConfig {@Beanpublic CorsFilter corsFilter() {UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();CorsConfiguration config = new CorsConfiguration();config.setAllowCredentials(true);config.addAllowedOrigin("http://example.com");config.addAllowedHeader("*");config.addAllowedMethod("*");source.registerCorsConfiguration("/**", config);return new CorsFilter(source);}
}

http://www.ppmy.cn/server/173925.html

相关文章

C语言学习day25:WinAPI编程进阶07-游戏辅助时钟周期事件、定时器消息

接下来我们说一下时间周期&#xff08;定时器&#xff09;事件 我们接下来继续用上一章中的代码来举例 这次课程我们需要用的函数SetTimer&#xff08;&#xff09;函数和KillTimer&#xff08;&#xff09;函数 SetTimer() 语法&#xff1a; UINT_PTR SetTimer([in, opti…

前端快速搭建Node服务(解决跨域问题)

服务搭建应用场景 前端模块化基本成为了不可或缺的一步了&#xff0c;最近自己学习的时候&#xff0c;用的cdn引入的vue&#xff0c;使用了EsModule语法&#xff0c;但使用import语法&#xff0c;会产生跨域问题&#xff0c;故自己本地搭建一个服务&#xff08;不需要下载npm包…

Linux下的shell指令(二)

作业 1> 编写脚本&#xff0c;实现文件分类的功能。 编写脚本的过程中&#xff0c;要特别注意路径问题 1.判断用户的家目录($HOME)下是否存在 file_dir 这个目录文件 如果存在&#xff0c;则询问用户是否清空&#xff0c;如果用户输入的是Y&#xff0c;则清空该目录文…

KMP 算法的 C 语言实现

# include <stdio.h> # include <stdlib.h> # include <string.h>// 打印 KMP 匹配结果. void ColorPrint(char *T, int *result, int result_size, int m) {int green_size strlen("\x1b[31m");int reset_size strlen("\x1b[0m");cha…

优维眼中的Manus:AI工程化思维重构Agent的运维端启示

继DeepSeek后&#xff0c;中国AI叕特么行了&#xff01; 2025年3月6日&#xff0c;AI行业被两则消息同时点燃&#xff1a;一边是阿里开源QwQ-32B模型以极简参数追平顶尖闭源产品&#xff0c;另一边则是名不见经传的Monica团队推出通用Agent产品Manus&#xff0c;在GAIA基准测试…

解锁AIGC新时代:通义万相2.1与蓝耘智算平台的完美结合引领AI内容生成革命

前言 通义万相2.1作为一个开源的视频生成AI模型&#xff0c;在发布当天便荣登了VBench排行榜的榜首&#xff0c;超越了Sora和Runway等业内巨头&#xff0c;展现出惊人的潜力。模型不仅能够生成1080P分辨率的视频&#xff0c;而且没有时长限制&#xff0c;能够模拟自然动作&…

泛型、泛型上限、泛型下限、泛型通配符

DAY8.1 Java核心基础 泛型 Generics 是指在类定义时不指定类中信息的具体数据类型&#xff0c;而是用一个标识符来代替&#xff0c;当外部实例化对象时再指定具体的数据类型。 在定义类或者接口时不明确指定类中信息的具体数据类型&#xff0c;在实例化时再来指定具体的数据类…

基于单片机的室外休闲智能座椅设计(论文+源码)

1系统总体设计 本课题为基于单片机的室外休闲智能座椅的设计&#xff0c;其可以实现温湿度检测&#xff0c;座椅加热&#xff0c;自动照明&#xff0c;背靠调节等工作。整个系统架构如图2.1所示其中包括了按键模块&#xff0c;温湿度检测模块&#xff0c;显示模块&#xff0c;加…