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;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        startTime = new Date();
        return true;
    }
    @Override
    public 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");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 可以在这里进行资源清理等操作
    }
}

配置拦截器

方式一:通过实现WebMvcConfigurer接口

- 创建一个配置类,实现`WebMvcConfigurer`接口。
- 在`addInterceptors`方法中添加拦截器并配置拦截路径。
- 例如:


@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new RequestTimeInterceptor()).addPathPatterns("/**");
    }
}

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

  • 方式二:通过扩展WebMvcConfigurationSupport类(不推荐,可能会覆盖Spring Boot的默认配置)

    • 创建一个配置类,继承自WebMvcConfigurationSupport
    • 重写addInterceptors方法来配置拦截器。
    • 例如:

    public class InterceptorConfiguration extends WebMvcConfigurationSupport {
    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new RequestTimeInterceptor()).addPathPatterns(“/**”);
    }
    }

    • 不过这种方式可能会导致Spring Boot自动配置的一些Web相关的配置失效,如静态资源处理等,所以一般推荐使用第一种方式。

拦截器的执行顺序

- 当有多个拦截器时,它们的执行顺序是按照在`InterceptorRegistry`中添加的顺序来执行的。先添加的拦截器先执行`preHandle`方法,后执行`postHandle`和`afterCompletion`方法。例如,假设有拦截器`Interceptor1`和`Interceptor2`,配置如下:


@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public 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 {
          @Override
          public void init(FilterConfig filterConfig) throws ServletException {
              // 初始化方法,在过滤器初始化时调用,可以进行一些初始化操作,如加载配置文件等
          }
          @Override
          public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
              // 过滤方法,在这里可以对请求进行处理,然后决定是否将请求传递给下一个过滤器或控制器
              // 例如,可以在这里检查请求头中的令牌(Token)是否有效
              filterChain.doFilter(servletRequest, servletResponse);
              // 在调用filterChain.doFilter后,可以对响应进行处理
          }
          @Override
          public 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 {
    @Bean
    public FilterRegistrationBean myFilterRegistration() {
    FilterRegistrationBean 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;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        encoding = filterConfig.getInitParameter("encoding");
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding(encoding);
        filterChain.doFilter(servletRequest, servletResponse);
    }
    @Override
    public void destroy() {
        // 可以在这里进行资源释放等操作
    }
}


public class LoggingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("Request received at: " + new Date());
        filterChain.doFilter(servletRequest, servletResponse);
    }
    @Override
    public 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 {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化过滤器,这里可以获取初始化参数等操作
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 执行过滤操作,例如检查请求头、验证用户身份等
        filterChain.doFilter(servletRequest, servletResponse);
    }
    @Override
    public void destroy() {
        // 销毁过滤器,释放资源
    }
}

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

@Configuration
public class FilterConfig {
    @Bean
    public 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 .便与维护和管理。有多个过滤器需要集成和管理。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL性能调优实战手册:从慢查询到执行计划全解析

一、调优流程四步走 &#x1f680; 当我们遇到数据库调优问题的时候&#xff0c;该如何思考呢? 这里把思考的流程整理成下面这张图。 整个流程划分成了观察&#xff08;Show status&#xff09;和 行动(Action&#xff09;两个部分。字母S的部分代表观察&#xff08;会使用相…

算法007——三数之和

力扣——三数之和&#xff08;点击跳转&#xff09; 做这道三数之和的题之前一定要先看我的上一篇笔记——两数之和&#xff08;点击跳转&#xff09;&#xff0c;只有把这个弄清楚这个 三数之和 才能明白 因为要去重&#xff0c;我们可以先将数组排序 我们先固定一个数&…

智慧城市智慧社区项目建设方案

一、项目背景 在全球化进程加速的今天&#xff0c;城市化问题日益凸显&#xff0c;传统的城市管理模式已难以满足现代社会对高效、智能化管理的需求。智慧城市和智慧社区的概念应运而生&#xff0c;其核心目标是通过信息技术手段&#xff0c;提升城市资源的利用效率&#xff0…

文件上传漏洞(upload靶场)

目录 Pass-01&#xff1a;前端绕过 方法一&#xff1a;浏览器禁用js 方法二:直接修改或删除js脚本 方法三&#xff1a;修改后缀绕过 Pass-02:服务器检测 Pess-03:黑名单绕过 Pass-04:.htaccess文件 Pass-05:windows特性和user.ini 方法一&#xff1a;php.自动解析为ph…

C++学习之QT综合项目二经典翻金币小游戏及打包

1.项目简介及创建 #include "chooselevelscene.h" #include <QMenuBar> #include <QMenu> #include <QPainter> #include "mypushbutton.h" #include <QTimer> #include <QDebug> #include <QLabel> #include…

前端项目中export和import的作用

之前写过代码&#xff0c;但是那个时候是使用jspdivcss写页面&#xff0c;jquery负责页面数据展示和数据请求。近期在学习前端&#xff0c;发现有export和import&#xff0c;想起了之前没用过&#xff0c;就研究搜索了一下&#xff0c;发现这个是在 ES6中添加的&#xff0c;难怪…

JVM 类加载原理之双亲委派机制(JDK8版本)

对 Java 程序的运行过程而言&#xff0c;类的加载依赖类加载器完成&#xff0c;而在 Java 默认的类加载器又分为启动类加载器、扩展类加载器和应用程序类加载器三种&#xff0c;但是一个类通常仅仅需要被加载一次即可&#xff0c;双亲委派机制即规定各个类该被何种类加载器加载…

【每日学点HarmonyOS Next知识】对话框去掉圆角、数组拼接、自定义对话框依附某个控件、平移动画、页面栈管理

1、 HarmonyOS CustomDialog怎么去掉左右和底部的透明以及圆角&#xff1f; CustomDialog怎么去掉左右和底部的透明以及圆角 设置customStyle为true即可开启使用自定义样式。设置borderRadius为0去掉圆角属性。 属性用法参考文档&#xff1a;https://developer.huawei.com/c…

坐落于杭州的电商代运营公司品融电商

坐落于杭州的电商代运营公司品融电商 在中国电商行业蓬勃发展的浪潮中&#xff0c;品融电商&#xff08;PINKROON&#xff09;作为一家扎根杭州的新锐品牌管理公司&#xff0c;凭借其独特的全域增长方法论和实战经验&#xff0c;迅速崛起为行业标杆。自2020年成立以来&#x…

【python爬虫】酷狗音乐爬取练习

注意&#xff1a;本次爬取的音乐仅有1分钟试听&#xff0c;仅作学习爬虫的原理&#xff0c;完整音乐需要自行下载客户端。 一、 初步分析 登陆酷狗音乐后随机选取一首歌&#xff0c;在请求里发现一段mp3文件&#xff0c;复制网址&#xff0c;确实是我们需要的url。 复制音频的…

Vue3 路由的历史记录 如何不允许浏览器前进后退 在函数中使用路由切换组件 路由的重定向

路由的历史记录模式 第一种push push会保留所有的切换记录&#xff0c;通过操作浏览器的前进后退&#xff0c;可以返回刚才浏览的页面 第二章replace replace不会保留路由的切换记录&#xff0c;不支持浏览器的前进后退 在函数中使用路由切换组件 页面挂载3秒后&#x…

【CSS3】金丹篇

目录 标准流概念元素类型及排列规则块级元素行内元素行内块元素 标准流的特点打破标准流 浮动基本使用清除浮动额外标签法单伪元素法双伪元素法&#xff08;推荐&#xff09;overflow 法 Flex 布局Flex 组成主轴对齐方式侧轴对齐方式修改主轴方向弹性盒子伸缩比弹性盒子换行行对…

解锁DeepSpeek-R1大模型微调:从训练到部署,打造定制化AI会话系统

目录 1. 前言 2.大模型微调概念简述 2.1. 按学习范式分类 2.2. 按参数更新范围分类 2.3. 大模型微调框架简介 3. DeepSpeek R1大模型微调实战 3.1.LLaMA-Factory基础环境安装 3.1大模型下载 3.2. 大模型训练 3.3. 大模型部署 3.4. 微调大模型融合基于SpirngBootVue2…

深入理解string:从模拟实现看本质

文章目录 摘要&#xff1a;一、引言二、string的模拟实现2.1 string类的定义 三、深拷贝和深赋值3.1 深浅拷贝构造函数3.2 深赋值运算符 四、总结五、附录5.1 完整代码6.2 测试用例 六、致谢 摘要&#xff1a; 本文将通过模拟实现一个简单的 String 类&#xff0c;深入探讨字符…

Unity组件TrailRenderer屏幕滑动拖尾

Unity组件TrailRenderer屏幕滑动拖尾 介绍制作总结 介绍 今天要做一个拖动效果&#xff0c;正好用到了TrailRenderer这个组件&#xff0c;正好分享一下 效果参考如下&#xff1a; 制作 1.创建空物体TrailObject添加组件TrailRenderer 下面的材质可以根据自己想要制作的效果去…

laravel中 添加公共/通用 方法/函数

一&#xff0c;现在app 下面创建Common目录&#xff0c;然后在创建Common.php 文件 二&#xff0c;修改composer.json文件 添加这个到autoload 中 "files": ["app/Common/Common.php"]"autoload": {"psr-4": {"App\\": &quo…

C#程序加密与解密Demo程序示例

目录 一、加密程序功能介绍 1、加密用途 2、功能 3、程序说明 4、加密过程 5、授权的注册文件保存方式 二、加密程序使用步骤 1、步骤一 ​编辑2、步骤二 3、步骤三 4、步骤四 三、核心代码说明 1、获取电脑CPU 信息 2、获取硬盘卷标号 3、机器码生成 3、 生成…

批量将 Excel 转换 PDF/Word/CSV以及图片等其它格式

Excel 格式转换是我们工作过程当中非常常见的一个需求&#xff0c;我们通常需要将 Excel 转换为其他各种各样的格式。比如将 Excel 转换为 PDF、比如说将 Excel 转换为 Word、再比如说将 Excel文档转换为图片等等。 这些操作对我们来讲都不难&#xff0c;因为我们通过 Office 都…

【报错】微信小程序预览报错”60001“

1.问题描述 我在微信开发者工具写小程序时&#xff0c;使用http://localhost:8080是可以请求成功的&#xff0c;数据全都可以无报错&#xff0c;但是点击【预览】&#xff0c;用手机扫描二维码浏览时&#xff0c;发现前端图片无返回且报错60001&#xff08;打开开发者模式查看日…

概念|RabbitMQ 消息生命周期 待消费的消息和待应答的消息有什么区别

目录 消息生命周期 一、消息创建与发布阶段 二、消息路由与存储阶段 三、消息存活与过期阶段 四、消息投递与消费阶段 五、消息生命周期终止 关键配置建议 待消费的消息和待应答的消息 一、待消费的消息&#xff08;Unconsumed Messages&#xff09; 二、待应答的消息…