Spring Boot 整合过滤器拦截器

Spring Boot 整合过滤器

1. 简介

在Spring Boot应用中,我们可以使用Servlet API中的Filter来实现一些全局的功能,比如日志记录、跨域处理、权限验证等。

2. 创建自定义过滤器

创建一个类,实现javax.servlet.Filter接口,并重写其中的方法。

package com.example.filter;import javax.servlet.*;
import java.io.IOException;public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化过滤器时可以做一些准备工作}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 在这里对请求进行预处理,或者对响应进行后处理System.out.println("MyFilter is running");// 调用FilterChain对象的doFilter方法,将请求传递给下一个过滤器或Servletchain.doFilter(request, response);}@Overridepublic void destroy() {// 过滤器被销毁前可以做一些清理工作}
}

3. 注册过滤器到Spring Boot容器

在Spring Boot的配置类中,通过FilterRegistrationBean将过滤器注册到Spring Boot的IoC容器中。

package com.example.config;import com.example.filter.MyFilter;
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> filterRegistration() {FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>();registration.setFilter(new MyFilter());registration.addUrlPatterns("/*"); // 设置过滤器作用的URL路径return registration;}
}

4. 配置过滤器顺序和优先级

可以通过FilterRegistrationBeansetOrder()方法设置过滤器的排序值。排序值越小,优先级越高,会先执行。

registration.setOrder(0); // 设置排序值为0,表示最高优先级

也可以通过过滤器的名字约定排序,如LogFilter和AuthFilter,字母A比L前面,所以AuthFilter会比LogFilter先执行。

5. 多个过滤器的应用

一个URL可以配置多个过滤器,使用逗号分隔。当设置多个过滤器时,全部验证通过,才视为通过。

registration.addUrlPatterns("/path1", "/path2");

部分过滤器可以指定参数,如perms、roles等。

6. 总结

通过上述步骤,我们成功地在Spring Boot应用中整合了自定义的过滤器。这个过滤器会在所有请求进入Controller之前运行,提供了灵活的扩展点来添加全局功能。
以下是一个Spring Boot整合拦截器的详细文档,包括最新的概念和示例代码:

Spring Boot 整合拦截器

1. 简介

在Spring MVC框架中,我们可以使用Interceptor(拦截器)来实现一些全局的功能,比如日志记录、权限验证等。

2. 创建自定义拦截器

创建一个类,实现org.springframework.web.servlet.HandlerInterceptor接口,并重写其中的方法。

package com.example.interceptor;import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Component
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {if (handler instanceof HandlerMethod) {HandlerMethod method = (HandlerMethod) handler;System.out.println("MyInterceptor is running for method: " + method.getMethod().getName());}return true; // 如果返回false,则中断后续流程}
//Object handler: 这个参数代表了将要被调用的处理器。
//通常情况下,它是一个实现了HandlerMethod接口的对象,包含了目标方法的信息。
//你可以通过((HandlerMethod) handler).getMethod().getName()来获取目标方法的名字,
//或者通过((HandlerMethod) handler).getBean()来获取目标方法所在的bean。@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {// 在这里对请求进行后处理,或者对响应进行预处理}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 这个方法会在整个请求完成以后被调用,无论是否有异常抛出}
}

3. 注册拦截器到Spring Boot容器

在Spring Boot的配置类中,通过实现org.springframework.web.servlet.config.annotation.WebMvcConfigurer接口并重写其addInterceptors()方法,将拦截器注册到Spring Boot的IoC容器中。

package com.example.config;import com.example.interceptor.MyInterceptor;
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 InterceptorConfig implements WebMvcConfigurer {@Autowiredprivate MyInterceptor myInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(myInterceptor).addPathPatterns("/**"); // 设置拦截器作用的URL路径}
}

4. 配置拦截器顺序和优先级

可以通过InterceptorRegistryorder()方法设置拦截器的排序值。排序值越小,优先级越高,会先执行。

registry.addInterceptor(myInterceptor).order(0); // 设置排序值为0,表示最高优先级

也可以通过拦截器的名字约定排序,如LogInterceptor和AuthInterceptor,字母A比L前面,所以AuthInterceptor会比LogInterceptor先执行。

5. 多个拦截器的应用

一个URL可以配置多个拦截器,它们按照添加的顺序依次执行。如果前一个拦截器返回false,则后续的拦截器不会执行。

以下是一个Spring Boot整合拦截器的实战应用,该示例演示了如何使用拦截器来实现用户登录验证功能:

6. preHandle、postHandle、afterCompletion三者的区别

preHandlepostHandleafterCompletion是Spring MVC中的拦截器(Interceptor)接口org.springframework.web.servlet.HandlerInterceptor的三个方法,它们在请求处理的不同阶段执行,分别用于实现预处理逻辑、后处理逻辑和清理工作。

  1. preHandle:

    • 执行时机:在目标Controller方法调用之前。
    • 返回值:布尔值。如果返回true,则允许请求继续进行;如果返回false,则中断请求流程,后续的拦截器和目标方法都不会被执行。
    • 用途:通常用于权限检查、登录验证等操作,决定是否允许请求到达Controller。
  2. postHandle:

    • 执行时机:在目标Controller方法调用之后,视图渲染之前。
    • 返回值:无。
    • 用途:可以修改ModelAndView对象,添加或修改模型数据,但不能改变响应状态码和头信息。常用于对处理器方法的后处理,比如修改返回给客户端的数据。
  3. afterCompletion:

    • 执行时机:在整个请求处理完成之后,包括视图渲染。
    • 返回值:无。
    • 用途:主要用于资源清理等收尾工作,如关闭数据库连接、清除缓存等。类似于try-catch-finally中的finally块。

这三个方法的关系可以用下面这张简化的时序图来表示:

+---------+      +----------+      +-------------+
| preHandle | ---> | Controller Method |
+---------+      +----------+      +-------------+|                      |                  ||                      V                  V|         +------------+      +--------------++-------->| postHandle | ---> | afterCompletion |+------------+      +--------------+

总结来说,preHandle主要负责前期的权限控制和决策,postHandle用于对处理器方法返回的结果进行加工,而afterCompletion则是用来做一些善后的工作。这三者共同构成了一个完整的请求处理链,在不同的阶段为应用提供了扩展点。

1. 拦截器实际应用

在这个实战应用中,我们将创建一个拦截器,用于检查每个请求是否已经通过了登录验证。如果没有通过验证,将返回401 Unauthorized响应。

2. 创建自定义拦截器

首先,我们创建一个名为LoginInterceptor的类,实现org.springframework.web.servlet.HandlerInterceptor接口,并重写其中的方法。

package com.example.interceptor;import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Component
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HandlerMethod method = (HandlerMethod) handler;// 检查当前请求是否需要登录验证if (method.getMethodAnnotation(LoginRequired.class) != null) {// 获取当前登录用户的ID(这里假设已存在从session或token中获取用户ID的方法)Object o = getUserId(request);if (o == null) {// 如果未登录,返回401 Unauthorized响应response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Please log in first.");return false; // 中断后续流程}}return true;}private Object getUserId(HttpServletRequest request) {// 这里只是一个示例,实际项目中应根据实际情况从session或token中获取用户IDreturn request.getSession().getAttribute("userId");}// 可以选择性地实现postHandle和afterCompletion方法
}

在上述代码中,我们定义了一个LoginInterceptor类,它会在每个请求到达Controller之前运行。如果请求的方法上标记了@LoginRequired注解,那么我们就检查当前用户是否已经登录。如果没有登录,就返回401 Unauthorized响应。

3. 注册拦截器到Spring Boot容器

接下来,在Spring Boot的配置类中,通过实现org.springframework.web.servlet.config.annotation.WebMvcConfigurer接口并重写其addInterceptors()方法,将拦截器注册到Spring Boot的IoC容器中。

package com.example.config;import com.example.interceptor.LoginInterceptor;
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 InterceptorConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/**"); // 设置拦截器作用的URL路径}
}

4. 创建登录验证注解

为了方便地为需要登录验证的Controller方法添加注解,我们可以创建一个名为LoginRequired的注解。

package com.example.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {
}

5. 使用登录验证注解

现在,我们可以在Controller类的方法上使用@LoginRequired注解,表示这个方法需要登录验证。

package com.example.controller;import com.example.annotation.LoginRequired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class UserController {@GetMapping("/user/profile")@LoginRequiredpublic String getUserProfile() {return "This is your profile.";}
}

在上述代码中,getUserProfile方法被标记了@LoginRequired注解,所以只有登录用户才能访问这个方法。

6. 示例代码

完整的示例代码可以在GitHub上找到:https://github.com/yourusername/spring-boot-interceptor-login-example

7. 总结

通过上述步骤,我们成功地在Spring Boot应用中整合了一个自定义的拦截器,实现了用户登录验证功能。这个拦截器可以在全局范围内控制哪些请求需要登录验证,增强了应用的安全性。

6. 总结

通过上述步骤,我们成功地在Spring Boot应用中整合了自定义的拦截器。这个拦截器会在所有请求进入Controller之前运行,提供了灵活的扩展点来添加全局功能。

过滤器和拦截器执行的先后顺序

创建一个简单的过滤器(Filter):

import javax.servlet.*;
import java.io.IOException;public class MyFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("Filter is running");chain.doFilter(request, response);}
}

然后在Spring Boot的配置类中注册这个过滤器:

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> filterRegistration() {FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>();registration.setFilter(new MyFilter());registration.addUrlPatterns("/*");return registration;}
}

接下来,我们创建一个拦截器(Interceptor):

import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Component
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {if (handler instanceof HandlerMethod) {HandlerMethod method = (HandlerMethod) handler;System.out.println("Interceptor is running for method: " + method.getMethod().getName());}return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {// ...}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// ...}
}

最后,在Spring Boot的配置类中添加对拦截器的支持:

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 InterceptorConfig implements WebMvcConfigurer {@Autowiredprivate MyInterceptor myInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(myInterceptor).addPathPatterns("/**");}
}

现在,当你发送一个HTTP请求到你的应用时,你会看到这样的输出:

Filter is running
Interceptor is running for method: yourControllerMethodName

这说明过滤器先执行,然后才是拦截器。

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

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

相关文章

力扣5、 最长回文子串

转到力扣 考察知识&#xff1a;字符串、动态规划 这个题目力扣给的难度是中等&#xff0c;感觉是中等难度题目中比较难的一个了&#xff0c;写代码之前理清楚思路再去写&#xff0c; 方法一、动态规划 时间复杂度&#xff1a;O(n2) 空间复杂度&#xff1a;O(n2) public cla…

SpringBoot对PDF进行模板内容填充、电子签名合并

1. 依赖引入–这里只包含额外引入的包 原有项目包不含括在内 <!-- pdf编辑相关--> <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13.3</version> </dependency><de…

C# 提取PDF中指定文本、图片的坐标

获取PDF文件中文字或图片的坐标可以实现精确定位&#xff0c;这对于快速提取指定区域的元素&#xff0c;以及在PDF中添加注释、标记或自动盖章等操作非常有用。本文将详解如何使用国产PDF库通过C# 提取PDF中指定文本或图片的坐标位置&#xff08;X, Y轴&#xff09;。 ✍ 用于…

Python机器学习19——常用六种机器学习的异常值监测方法(孤立森林,数据支持描述,自编码器,高斯混合,DBSCAN,LOF)

案例背景 异常值监测是机器学习的一个重要领域&#xff0c;博主以前做预测多&#xff0c;异常值监测涉及得少&#xff0c;但之后的工作可能需要做异常值方面的工作&#xff0c;所以大致总结了一下常用的机器学习来做异常值监测的方法以及代码。 标题的这些机器学习方法基本都…

WPF-一个简单登录界面

一个简单登录界面 文章目录 一个简单登录界面一、效果展示二、准备代码 一、效果展示 二、准备代码 创建一个WPF工程&#xff0c;创建名为 Login5 的WPF项目。 添加Nuget包 MaterialDesignThemes 界面的整体布局和样式代码 <Window x:Class"Login5.MainWindow&quo…

Java - 异常(三)- 声明异常(throws)和手动抛出异常throw

目录 6.3 方式2&#xff1a;声明异常&#xff08;throws&#xff09; 6.4 手动抛出异常throw 6.4.1 概述 6.4.2 使用格式&#xff1a; 6.4.3 实例代码 6.4.4 为什么要手动抛出异常对象&#xff1f; 6.4.5 如何理解“自动”和“手动” 抛出异常对象 6.4.6 注意点 ❓面试…

数字化赋能实体经济,凌雄科技发挥DaaS模式提质增效价值

11月中旬&#xff0c;市场监管总局发布了2023年前三季度经营主体数据。其中&#xff0c;前三季度全国新设民营企业总计706.5万户&#xff0c;截至9月底&#xff0c;全国登记在册的民营企业数量超过5200万户&#xff0c;在企业总量中占比高达92.3%。如何帮助民营企业实现高质量发…

【数学建模美赛M奖速成系列】报名流程与论文的基本格式

数学建模美赛M奖速成系列 写在前面报名方式1.官网直接报名2.赛氪软件辅助报名 论文的基本格式摘要模型建立模型求解结果分析与检验模型评价 竞赛的基本注意事项1. 选题后查找资料2. 写作能力和编程能力 历年优秀论文标题与摘要简明扼要善用图表 最后 写在前面 最近&#xff0c…

通过Jenkins将应用发布到K8s1.24.3

一、准备基础环境 cat >> /etc/hosts <<EOF 192.168.180.210 k8s-master 192.168.180.200 k8s-node1 192.168.180.190 k8s-node2 192.168.180.180 gitlab 192.168.180.170 jenkins 192.168.180.160 harbor EOF 配置主机名 hostnamectl set-hostname k8s-master &am…

Vue 3 开发中遇到的问题及解决方案(fix bug)

开发环境&#xff1a;mac系统&#xff0c;node版本&#xff1a; 16.15.0 版本兼容问题 vite v3.2.4 building for development... hasInjectionContext is not exported by node_modules/pinia/node_modules/vue-demi/lib/index.mjs, imported by node_modules/pinia/dist/pini…

深圳移动与大富科技助力深圳人工智能教育高质量发展

12月12日&#xff0c;中国移动通信集团广东有限公司深圳分公司(以下简称“深圳移动”) 与大富科技&#xff08;安徽&#xff09;股份有限公司&#xff08;以下简称“大富科技”&#xff09;在中国移动深圳信息大厦签署“战略合作框架协议”&#xff0c;共同推进人工智能教育、I…

常见的工作流编排引擎

常见工作流框架&#xff1a;微服务编排引擎 工作流框架还是比较多的&#xff0c;按照语言分类的话&#xff0c;有 Java: jBPM、Activiti、SWF PHP: Tpflow、PHPworkflow Go: Cadence&#xff08;Cadence由Uber开发并开源&#xff0c;Maxim Fateev是Cadence的主架构师&#…

解决文件默认打开程序选择被联想管家劫持

问题描述 当选择文件右键->“打开方式”->“选择其他应用”时&#xff0c;弹出了联想电脑管家的软件安装推荐。一不小心就会下载了它推荐的软件。特恶心。 问题原因 这个推荐软件的程序&#xff0c;是联想开发的一个叫“LeASOpen”的垃圾软件。联想把系统右键菜单“选…

Java面试题1-10

1、一个".java"源文件中是否可以包括多个类&#xff08;不是内部类&#xff09;&#xff1f;有什么限制&#xff1f; 可以有多个类&#xff0c;但只能有一个public的类&#xff0c;并且public的类名必须与文件名相一致。 2、Java有没有goto? java中的保留字&am…

K8S(七)—污点、容忍

目录 污点、容忍污点&#xff08;Taints&#xff09;&#xff1a;容忍&#xff08;Tolerations&#xff09;&#xff1a;如何一起使用污点和容忍&#xff1a;操作符&#xff08;Equal、Exists&#xff09;例子基于污点的驱逐基于节点状态添加污点 污点、容忍 官网地址&#xf…

【大数据】详解 AVRO 格式

详解 AVRO 格式 1.Avro 介绍2.schema2.1 原始类型2.2 复杂类型2.2.1 Records2.2.2 Enums2.2.3 Arrays2.2.4 Maps2.2.5 Unions2.2.6 Fixed 3.Avro 的文件存储格式3.1 数据编码3.1.1 原始类型3.1.2 复杂类型 3.2 存储格式3.3 存储格式 4.小结 1.Avro 介绍 Apache Avro 是 Hadoop…

three.js(一)

文章目录 three.js环境搭建正文补充 示例效果知识点补充1:一个标准的html知识点补充2:原生的前端框架和Vue框架的区别原生的前端框架Vue框架声明式编程和响应式编程 three.js环境搭建 正文 搭建 Three.js 的环境通常包括以下几个步骤&#xff1a; 1.创建项目目录&#xff1a…

Spark读写MySQL数据库

Spark读写MySQL数据库 文章目录 Spark读写MySQL数据库一、读取数据库&#xff08;一&#xff09;通过RDD的方式读取MySQL数据库&#xff08;二&#xff09;通过DataFrame的方式读取MySQL数据库 二、添加数据到MySQL&#xff08;一&#xff09;通过RDD的方式插入数据到MySQL&…

初级数据结构(三)——栈

文中代码源文件已上传&#xff1a;数据结构源码 <-上一篇 初级数据结构&#xff08;二&#xff09;——链表 | 初级数据结构&#xff08;四&#xff09;——队列 下一篇-> 1、栈的特性 1.1、函数栈帧简述 即使是刚入门几天的小白&#xff0c;对栈这个字…

基于YOLOv8深度学习的吸烟/抽烟行为检测系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…