SpringBoot -拦截器Interceptor、过滤器 Filter 及设置

Spring Boot拦截器(Interceptor)的概念

- 在Spring Boot中,拦截器是一种AOP的实现方式。它主要用于<font style="color:#DF2A3F;">拦截请求</font>,在请求处理之前和之后执行特定的代码逻辑。与过滤器不同的是,拦截器更侧重于对Spring MVC中的<font style="color:#DF2A3F;">控制器(Controller)</font>进行拦截,能够访问到Spring MVC上下文中的对象,比如获取请求的处理器(Handler)信息、模型(Model)和视图(View)相关信息等。

创建拦截器类

- 要创建拦截器,需要实现`HandlerInterceptor`接口。这个接口有三个方法:* `<font style="color:#DF2A3F;">preHandle()</font>`:在请求处理之前调用。可以进行权限验证、日志记录等操作。如果返回`false`,则请求被中断,不会继续执行后续的处理器(Controller)方法;如果返回`true`,则请求继续传递。* `<font style="color:#DF2A3F;">postHandle()</font>`:在请求处理之后,视图渲染之前调用。可以对模型(Model)和视图(View)进行修改等操作。* `<font style="color:#DF2A3F;">afterCompletion()</font>`:在整个请求完成后(包括视图渲染后)调用。主要用于资源清理等操作。
- 例如,创建一个简单的拦截器来记录请求处理时间:RequestTimeInterceptor对象
public class RequestTimeInterceptor implements HandlerInterceptor {private Date startTime;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {startTime = new Date();return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {Date endTime = new Date();System.out.println("Request processing time: " + (endTime.getTime() - startTime.getTime()) + "ms");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 可以在这里进行资源清理等操作}
}

配置拦截器

方式一:通过实现WebMvcConfigurer接口

- 创建一个配置类,实现`WebMvcConfigurer`接口。
- 在`addInterceptors`方法中添加拦截器并配置拦截路径。
- 例如:
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new RequestTimeInterceptor()).addPathPatterns("/**");}
}

上述代码中,addInterceptor方法添加了RequestTimeInterceptor拦截器,addPathPatterns方法指定了拦截的路径为所有路径(/**`)。

  • 方式二:通过扩展WebMvcConfigurationSupport类(不推荐,可能会覆盖Spring Boot的默认配置)
    • 创建一个配置类,继承自WebMvcConfigurationSupport
    • 重写addInterceptors方法来配置拦截器。
    • 例如:

public class InterceptorConfiguration extends WebMvcConfigurationSupport {@Overrideprotected void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new RequestTimeInterceptor()).addPathPatterns("/**");}
}
- 不过这种方式可能会导致Spring Boot自动配置的一些Web相关的配置失效,如静态资源处理等,所以一般推荐使用第一种方式。

拦截器的执行顺序

- 当有多个拦截器时,它们的执行顺序是按照在`InterceptorRegistry`中添加的顺序来执行的。先添加的拦截器先执行`preHandle`方法,后执行`postHandle`和`afterCompletion`方法。例如,假设有拦截器`Interceptor1`和`Interceptor2`,配置如下:
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new Interceptor1()).addPathPatterns("/**");registry.addInterceptor(new Interceptor2()).addPathPatterns("/**");}
}
- 在这个例子中,`Interceptor1`的`preHandle`方法会先于`Interceptor2`的`preHandle`方法执行。而`Interceptor2`的`postHandle`和`afterCompletion`方法会先于`Interceptor1`的相应方法执行。

过滤器 Filter 的概念

  • 在 Spring Boot 中,过滤器是一种用于拦截和处理请求和响应的组件。它可以在请求到达控制器(Controller)之前进行预处理,例如验证请求头、验证用户身份等,也可以在响应返回客户端之前进行后处理,例如修改响应头、添加日志信息等。过滤器可以对多个请求和响应进行统一的处理,是实现横切关注点(如安全、日志记录等)的重要手段。

实现Filter接口,并使用@WebFilter注解(原生servlet配置方式)

- **使用注解方式(推荐)**-Spring Boot中,更方便的是使用`@WebFilter`注解来创建过滤器。例如:- ```java@WebFilter(urlPatterns = "/*")public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化方法,在过滤器初始化时调用,可以进行一些初始化操作,如加载配置文件等}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// 过滤方法,在这里可以对请求进行处理,然后决定是否将请求传递给下一个过滤器或控制器// 例如,可以在这里检查请求头中的令牌(Token)是否有效filterChain.doFilter(servletRequest, servletResponse);// 在调用filterChain.doFilter后,可以对响应进行处理}@Overridepublic void destroy() {// 销毁方法,在过滤器销毁时调用,可以进行一些资源释放等}}
  • 其中@WebFilter(urlPatterns = "/*")注解用于指定过滤器要拦截的 URL 模式,/*表示拦截所有的请求路径。
  • 自动配置使用@WebFilter注解的过滤器:
    • 需要在 Spring Boot 的主应用程序类上添加@ServletComponentScan注解,这样 Spring Boot 才能扫描到过滤器并自动进行配置。例如:

@SpringBootApplication
@ServletComponentScan
public class MySpringBootApp {public static void main(String[] args) {SpringApplication.run(MySpringBootApp.class, args);}
}
  • 手动配置(通过FilterRegistrationBean
    • 有时候可能需要更灵活的配置,例如设置过滤器的执行顺序、添加初始化参数等。可以通过FilterRegistrationBean对象 来手动配置过滤器。例如:
    • <font style="color:rgb(38, 38, 38);background-color:rgb(242, 242, 247);">FilterRegistrationBean对象可以:</font>
      • 设置实际过滤器 setFilter()
      • 设置过滤器名 setName(“myFilter”);
      • 设置过滤路径 addUrlPatterns(“/*”);
      • 设置优先级 setOrder(1);

@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<MyFilter> myFilterRegistration() {FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();registrationBean.setFilter(new MyFilter());registrationBean.addUrlPatterns("/*");registrationBean.setName("myFilter");registrationBean.setOrder(1); // 设置过滤器的执行顺序,数字越小越先执行return registrationBean;}
}

过滤器链(Filter Chain)

- 当有多个过滤器时,它们会形成一个过滤器链。请求会依次经过每个过滤器,每个过滤器都可以对请求进行处理,然后决定是否将请求传递给下一个过滤器。在`doFilter`方法中,通过调用`filterChain.doFilter(servletRequest, servletResponse)`来将请求传递给下一个过滤器或控制器。如果某个过滤器没有调用这个方法,那么请求就会被截断,后续的过滤器和控制器都不会收到这个请求。同样,在响应返回时,也会按照相反的顺序经过各个过滤器,每个过滤器可以对响应进行处理。例如,假设有两个过滤器`Filter1`和`Filter2`,请求首先会到达`Filter1`,`Filter1`处理后传递给`Filter2`,`Filter2`处理后传递给控制器;响应返回时,先经过`Filter2`,再经过`Filter1`,最后返回给客户端。

**1.**通过xml文件配置过滤器链:

    * 创建两个过滤器:CharacterEncodingFilter、LoggingFilter
public class CharacterEncodingFilter implements Filter {private String encoding;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {encoding = filterConfig.getInitParameter("encoding");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {servletRequest.setCharacterEncoding(encoding);filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {// 可以在这里进行资源释放等操作}
}
public class LoggingFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("Request received at: " + new Date());filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {}
}
    * **配置过滤器链(在 web.xml 中)*** 在这个配置中,`LoggingFilter`会应用到所有的请求(`/*`)。`CharacterEncodingFilter`会应用到名为`MyServlet`的 Servlet。当请求到来时,会先经过`LoggingFilter`,然后根据请求的目标是`MyServlet`时,再经过`CharacterEncodingFilter`。
<filter><filter - name>LoggingFilter</filter - name><filter - class>com.example.filters.LoggingFilter</filter - class>
</filter>
<filter - mapping><filter - name>LoggingFilter</filter - name><url - pattern>/*</url - pattern>
</filter - mapping><filter><filter - name>CharacterEncodingFilter</filter - name><filter - class>com.example.filters.CharacterEncodingFilter</filter - class><init - param><param - name>encoding</param - name><param - value>UTF - 8</param - value></init - param>
</filter>
<filter - mapping><filter - name>CharacterEncodingFilter</filter - name><servlet - name>MyServlet</servlet - name>
</filter - mapping>
  • 上述代码中,首先定义了一个名为CharacterEncodingFilter的过滤器,并且通过<init - param>标签设置了一个初始化参数encodingUTF - 8。然后通过<filter - mapping>标签将这个过滤器应用到所有的请求(/*)。当请求到来时,这个过滤器会设置请求的字符编码为UTF - 8,然后将请求传递给下一个过滤器或者目标资源。

**2.**使用注解方式(Servlet 3.0+)实现过滤器链

- 当有多个注解式过滤器时,过滤器的执行顺序是按照类名的字典序来确定的。如果需要更精确地控制顺序,可以使用`@javax.annotation.Priority`注解来指定优先级。数字越小,优先级越高。
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.annotation.Priority;
import java.io.IOException;@WebFilter(filterName = "AuthFilter", urlPatterns = "/*")
@Priority(1)
public class AuthFilter implements Filter {//...
}@WebFilter(filterName = "AnotherFilter", urlPatterns = "/*")
@Priority(2)
public class AnotherFilter implements Filter {//...
}

DelegatingFilterProxyRegistrationBean 对象代理过滤器。

  • DelegatingFilterProxyRegistrationBean 是 Spring Boot 中用于注册一个代理过滤器(DelegatingFilterProxy)的配置类。它主要用于将一个基于 Servlet 的过滤器集成到 Spring 的应用上下文中,使得这个过滤器能够利用 Spring 的特性,如依赖注入、配置属性等。
  • 这个类在将传统的 Servlet 过滤器与 Spring 应用进行整合时非常有用。例如,在一些安全认证过滤器或者日志记录过滤器的场景下,通过它可以更好地管理和配置这些过滤器,让它们能够从 Spring 的环境配置(如配置文件、环境变量等)中获取必要的参数,并且能够方便地与 Spring 管理的其他组件(如服务层组件、数据源等)进行交互。

·配置**DelegatingFilterProxyRegistrationBean**

假设我们有一个自定义的过滤器MyFilter,并且希望通过DelegatingFilterProxyRegistrationBean 来注册它,使其能够与 Spring 应用上下文集成。

1**.创建一个过滤器:MyFilter**


public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化过滤器,这里可以获取初始化参数等操作}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// 执行过滤操作,例如检查请求头、验证用户身份等filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {// 销毁过滤器,释放资源}
}

2.然后,在Spring Boot的配置类中注册DelegatingFilterProxyRegistrationBean

@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<DelegatingFilterProxy> myFilterRegistration() {FilterRegistrationBean<DelegatingFilterProxy> registrationBean = new FilterRegistrationBean<>();DelegatingFilterProxy delegatingFilterProxy = new DelegatingFilterProxy("myFilter");registrationBean.setFilter(delegatingFilterProxy);registrationBean.addUrlPatterns("/*");return registrationBean;}@Bean(name = "myFilter")public MyFilter myFilter() {return new MyFilter();}
}
  • 在上述配置中,首先创建了一个DelegatingFilterProxyRegistrationBean,并将一个DelegatingFilterProxy 实例设置为其过滤器。DelegatingFilterProxy 的构造函数参数 "myFilter" 是要在 Spring 应用上下文中查找的真正过滤器 Bean 的名称。然后,通过addUrlPatterns("/*") 设置了过滤器拦截的 URL 模式为所有请求。同时,还通过@Bean(name = "myFilter") 方法定义了真正的过滤器MyFilter,这样DelegatingFilterProxy 就能在 Spring 应用上下文中找到它并进行委托。

DelegatingFilterProxyRegistrationBean的优点:

1 .灵活性高,它允许过滤器成为 Spring 的 Bean,从而可以利用 Spring 的各种功能,

2 .便与维护和管理。有多个过滤器需要集成和管理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/62792.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu 20.04 Server版连接Wifi

前言 有时候没有网线口插网线或者摆放电脑位置不够时&#xff0c;需要用Wifi联网。以下记录Wifi联网过程。 环境&#xff1a;Ubuntu 20.04 Server版&#xff0c;无UI界面 以下操作均为root用户&#xff0c;如果是普通用户&#xff0c;请切换到root用户&#xff0c;或者在需要权…

Java项目实战II基于微信小程序的亿家旺生鲜云订单零售系统的设计与实现(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着移动互联网技术的不断…

多线程安全单例模式的传统解决方案与现代方法

在多线程环境中实现安全的单例模式时&#xff0c;传统的双重检查锁&#xff08;Double-Checked Locking&#xff09;方案和新型的std::once_flag与std::call_once机制是两种常见的实现方法。它们在实现机制、安全性和性能上有所不同。 1. 传统的双重检查锁方案 双重检查锁&am…

Javaweb梳理21——Servlet

Javaweb梳理21——Servlet 21 Servlet21.1 简介21.3 执行流程21.4 生命周期4.5 方法介绍21.6 体系结构21.7 urlPattern配置21.8 XML配置 21 Servlet 21.1 简介 Servlet是JavaWeb最为核心的内容&#xff0c;它是Java提供的一门动态web资源开发技术。使用Servlet就可以实现&…

MySQL 主从同步一致性详解

MySQL主从同步是一种数据复制技术&#xff0c;它允许数据从一个数据库服务器&#xff08;主服务器&#xff09;自动同步到一个或多个数据库服务器&#xff08;从服务器&#xff09;。这种技术主要用于实现读写分离、提升数据库性能、容灾恢复以及数据冗余备份等目的。下面将详细…

点云3DHarris角点检测算法推导

先回顾2D的Harris角点检测算法推导 自相关矩阵是Harris角点检测算法的核心之一&#xff0c;它通过计算图像局部区域的梯度信息来描述该区域的特征。在推导Harris角点检测算法中的自相关矩阵时&#xff0c;我们首先需要了解自相关矩阵的基本思想和数学背景。 参考 [经典角点检…

在 CentOS 上安装 Docker:构建容器化环境全攻略

一、引言 在当今的软件开发与运维领域&#xff0c;Docker 无疑是一颗璀璨的明星。它以轻量级虚拟化的卓越特性&#xff0c;为应用程序的打包、分发和管理开辟了崭新的高效便捷之路。无论是开发环境的快速搭建&#xff0c;还是生产环境的稳定部署&#xff0c;Docker 都展现出了…

Unity-Particle System属性介绍(一)基本属性

什么是ParticleSystem 粒子系统是Unity中用于模拟大量粒子的行为的组件。每个粒子都有一个生命周期&#xff0c;包括出生、运动、颜色变化、大小变化和死亡等。粒子系统可以用来创建烟雾、火焰、水、雨、雪、尘埃、闪电和其他各种视觉效果。 开始 在项目文件下创建一个Vfx文件…

.NET8/.NETCore 依赖注入:自动注入项目中所有接口和自定义类

.NET8/.NETCore 依赖接口注入&#xff1a;自动注入项目中所有接口和自定义类 目录 自定义依赖接口扩展类&#xff1a;HostExtensions AddInjectionServices方法GlobalAssemblies 全局静态类测试 自定义依赖接口 需要依赖注入的类必须实现以下接口。 C# /// <summary>…

Brain.js(二):项目集成方式详解——npm、cdn、下载、源码构建

Brain.js 是一个强大且易用的 JavaScript 神经网络库&#xff0c;适用于前端和 Node.js 环境&#xff0c;帮助开发者轻松实现机器学习功能。 在前文Brain.js&#xff08;一&#xff09;&#xff1a;可以在浏览器运行的、默认GPU加速的神经网络库概要介绍-发展历程和使用场景中&…

使用pyQT完成简单登录界面

import sysfrom PyQt6.QtGui import QMovie,QPixmap from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QPushButton,QLineEdit#封装我的窗口类 class MyWidget(QWidget):#构造函数def __init__(self):#初始化父类super().__init__()# 设置窗口大小self.resize(330,…

理解 Python PIL库中的 convert(‘RGB‘) 方法:为何及如何将图像转换为RGB模式

理解 Python PIL库中的 convert(RGB) 方法&#xff1a;为何及如何将图像转换为RGB模式 在图像处理中&#xff0c;保持图像数据的一致性和可操作性是至关重要的。Python的Pillow库&#xff08;继承自PIL, Python Imaging Library&#xff09;提供了强大的工具和方法来处理图像&…

avcodec_alloc_context3,avcodec_open2,avcodec_free_context,avcodec_close

avcodec_alloc_context3 是创建编解码器上下文&#xff0c;需要使用 avcodec_free_context释放 需要使用avcodec_free_context 释放 /** * Allocate an AVCodecContext and set its fields to default values. The * resulting struct should be freed with avcodec_free_co…

linux安装部署mysql资料

安装虚拟机 等待检查完成 选择中文 软件选择 网络和主机名 开始安装 设置root密码 ADH-password 创建用户 等待安装完成 重启 接受许可证 Centos 7 64安装完成 安装mysql开始 Putty连接指定服务器 在 opt目录下新建download目录 将mysql文件传到该目录下 查看linux服务器的…

vscode 怎么下载 vsix 文件?

参考&#xff1a;https://marketplace.visualstudio.com/items?itemNameMarsCode.marscode-extension 更好的办法&#xff1a;直接去相关插件的 github repo 下载老版本 https://github.com/VSCodeVim/Vim/releases?page5 或者&#xff0c;去 open-vsx.org 下载老版本 点击这…

医院管理系统

私信我获取源码和万字论文&#xff0c;制作不易&#xff0c;感谢点赞支持。 医院管理系统 摘要 随着信息互联网信息的飞速发展&#xff0c;医院也在创建着属于自己的管理系统。本文介绍了医院管理系统的开发全过程。通过分析企业对于医院管理系统的需求&#xff0c;创建了一个计…

AWS账号提额

Lightsail提额 控制台右上角&#xff0c;用户名点开&#xff0c;选择Service Quotas 在导航栏中AWS服务中找到lightsail点进去 在搜索框搜索instance找到相应的实例类型申请配额 4.根据自己的需求选择要提额的地区 5.根据需求来提升配额数量,提升小额配额等大约1小时生效 Ligh…

SprinBoot整合KafKa的使用(详解)

前言 1. 高吞吐量&#xff08;High Throughput&#xff09; Kafka 设计的一个核心特性是高吞吐量。它能够每秒处理百万级别的消息&#xff0c;适合需要高频次、低延迟消息传递的场景。即使在大规模分布式环境下&#xff0c;它也能保持很高的吞吐量和性能&#xff0c;支持低延…

Day52 | 动态规划 :单调栈 每日温度下一个更大的元素I下一个更大元素II

Day52 | 动态规划 &#xff1a;单调栈 每日温度&&下一个更大的元素I&&下一个更大元素II 单调栈【基础算法精讲 26】_哔哩哔哩_bilibili 及时去掉无用数据&#xff0c;保证栈中元素有序 文章目录 Day52 | 动态规划 &#xff1a;单调栈 每日温度&&下一…

第30天:安全开发-JS 应用NodeJS 指南原型链污染Express 框架功能实现审计0

时间轴&#xff1a; 演示案例&#xff1a; 环境搭建-NodeJS-解析安装&库安装 功能实现-NodeJS-数据库&文件&执行 安全问题-NodeJS-注入&RCE&原型链 案例分析-NodeJS-CTF 题目&源码审计 开发指南-NodeJS-安全 SecGuide 项目、 环境搭建-NodeJ…