当前位置: 首页 > news >正文

详细分析SpringMvc中HandlerInterceptor拦截器的基本知识(附Demo)

目录

  • 前言
  • 1. 基本知识
  • 2. Demo
  • 3. 实战解析

前言

对于Java的基本知识推荐阅读:

  1. java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
  2. 【Java项目】实战CRUD的功能整理(持续更新)

1. 基本知识

HandlerInterceptor 是 Spring MVC 提供的一种机制,用来在请求处理的不同阶段进行拦截

它通常用于日志记录、权限校验、性能监控等操作
继承 HandlerInterceptor 允许定义自定义的逻辑,在请求被处理之前、之后以及完成后执行额外的任务

HandlerInterceptor 接口中包含三个主要方法

  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
    在请求处理之前调用(即在控制器方法调用之前)
    返回 boolean 类型,如果返回 true,则继续处理请求;如果返回 false,则中断请求

  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
    在请求被处理之后、视图被渲染之前调用
    用于对 ModelAndView 做进一步的修改或处理

  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
    在整个请求完成后(包括视图渲染完成后)调用
    用于清理资源、记录日志或执行后续的逻辑

HandlerInterceptor 使用场景

  1. 日志记录:拦截请求并记录请求信息,如 URL、参数、处理时间等
  2. 权限校验:在进入控制器方法之前,检查用户是否有权限访问某个资源
  3. 性能监控:统计每个请求的耗时,以便优化性能
  4. 会话管理:检查用户会话状态,判断用户是否已经登录

基本的 API 介绍

  • HttpServletRequest:表示客户端的请求,可以从中获取请求的 URL、参数、请求体等
  • HttpServletResponse:表示服务器端的响应,可以向客户端写入响应数据
  • Handler:处理器,通常是控制器方法或其代理对象(通常是 HandlerMethod)
  • ModelAndView:封装了数据模型和视图信息,可以在 postHandle 方法中对其进行修改

使用 HandlerInterceptor 的步骤

  1. 创建拦截器类:实现 HandlerInterceptor 接口并重写其方法
  2. 注册拦截器:在 Spring 配置中,将自定义的拦截器注册到拦截器链中
  3. 配置拦截路径:可以选择对哪些 URL 进行拦截,或者排除哪些 URL

2. Demo

在这里插入图片描述

  1. 创建一个自定义拦截器类
import org.springframework.stereotype.Component;
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 {System.out.println("preHandle: 请求URL -> " + request.getRequestURI());// 这里可以进行权限校验、记录日志等操作// 如果返回 false,请求会被终止return true;}// 在控制器处理请求之后调用,但在视图渲染之前调用@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle: 请求处理完毕");}// 在整个请求完成后调用,通常用于资源清理等操作@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion: 请求完成,清理资源");}
}
  1. 注册拦截器

需要将这个拦截器注册到 Spring MVC 中

通常,在配置类中添加拦截器

import org.springframework.beans.factory.annotation.Autowired;
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 {@Autowiredprivate MyInterceptor myInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 添加拦截器,并指定拦截路径registry.addInterceptor(myInterceptor).addPathPatterns("/**") // 拦截所有路径.excludePathPatterns("/login", "/register"); // 排除某些路径}
}
  1. 创建简单的测试控制器

为了测试拦截器的效果,可以创建一个简单的控制器:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class TestController {@GetMapping("/test")public String test() {return "拦截器测试成功!";}@GetMapping("/login")public String login() {return "这是登录页面,不会被拦截!";}
}
  1. 运行程序并测试

启动 Spring Boot 应用后,访问 /test URL

在这里插入图片描述

将会在控制台看到以下输出:

preHandle: 请求URL -> /test
postHandle: 请求处理完毕
afterCompletion: 请求完成,清理资源

在这里插入图片描述

如果访问 /login,因为在 WebConfig 中排除了 /login 路径,拦截器不会生效

在这里插入图片描述

总的来说

HandlerInterceptor 是 Spring MVC 中非常有用的拦截器机制,它可以在请求处理的各个阶段执行自定义逻辑

  • 常用的拦截器功能包括日志记录、权限检查、性能监控等
  • 使用步骤:定义拦截器类、注册拦截器、配置拦截路径

3. 实战解析

@Slf4j // 引入 Lombok 提供的注解,用于简化日志的使用,不需要显式定义 logger 对象。
public class ApiAccessLogInterceptor implements HandlerInterceptor {// 定义一个常量,用于存储处理方法(HandlerMethod)的属性名称,这个属性将在后续的过滤器中使用。public static final String ATTRIBUTE_HANDLER_METHOD = "HANDLER_METHOD";// 定义一个常量,用于存储 StopWatch 对象的属性名称,StopWatch 是用于记录请求耗时的计时器。private static final String ATTRIBUTE_STOP_WATCH = "ApiAccessLogInterceptor.StopWatch";/*** 拦截器的前置处理方法 (preHandle),在请求处理前调用。* * @param request  当前的 HttpServletRequest 对象,包含了请求信息。* @param response 当前的 HttpServletResponse 对象,包含了响应信息。* @param handler  请求处理器,通常是一个 Controller 中的方法,或其对应的代理对象。* @return 如果返回 true,则继续执行后续的拦截器或目标方法;如果返回 false,则中断请求流程。*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 记录 HandlerMethod(处理方法),将其存储到 request 属性中,以供后续的过滤器或日志使用。HandlerMethod handlerMethod = handler instanceof HandlerMethod ? (HandlerMethod) handler : null;if (handlerMethod != null) {request.setAttribute(ATTRIBUTE_HANDLER_METHOD, handlerMethod);}// 打印请求日志。如果当前环境不是生产环境(非 prod 环境),则执行日志输出。if (!SpringUtils.isProd()) { // 检查当前是否是生产环境,如果不是则记录日志// 获取请求的查询参数,以键值对的形式存储。Map<String, String> queryString = ServletUtils.getParamMap(request);// 如果请求是 JSON 请求类型,则从请求中提取出请求体。String requestBody = ServletUtils.isJsonRequest(request) ? ServletUtils.getBody(request) : null;// 如果既没有查询参数,也没有请求体,则打印无参数的日志;否则打印包含参数或请求体的日志。if (CollUtil.isEmpty(queryString) && StrUtil.isEmpty(requestBody)) {log.info("[preHandle][开始请求 URL({}) 无参数]", request.getRequestURI());} else {log.info("[preHandle][开始请求 URL({}) 参数({})]", request.getRequestURI(),StrUtil.nullToDefault(requestBody, queryString.toString()));}// 计时操作:为请求创建一个 StopWatch(计时器),并启动它,用于后续计算请求的处理耗时。StopWatch stopWatch = new StopWatch();stopWatch.start();// 将 StopWatch 对象存储到 request 的属性中,以便在 afterCompletion 方法中使用。request.setAttribute(ATTRIBUTE_STOP_WATCH, stopWatch);}return true; // 返回 true,表示允许请求继续往下处理。}/*** 拦截器的后置处理方法 (afterCompletion),在整个请求处理完成(包括视图渲染完成)之后调用。* * @param request  当前的 HttpServletRequest 对象,包含了请求信息。* @param response 当前的 HttpServletResponse 对象,包含了响应信息。* @param handler  请求处理器,通常是一个 Controller 中的方法,或其对应的代理对象。* @param ex       如果请求处理过程中出现异常,这里可以捕获到。*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {// 打印响应日志。如果当前环境不是生产环境(非 prod 环境),则执行日志输出。if (!SpringUtils.isProd()) {// 从 request 属性中获取在 preHandle 方法中创建的 StopWatch 对象。StopWatch stopWatch = (StopWatch) request.getAttribute(ATTRIBUTE_STOP_WATCH);// 停止计时器,计算请求处理总耗时。stopWatch.stop();// 打印完成请求的日志,包括请求的 URL 和耗时(单位:毫秒)。log.info("[afterCompletion][完成请求 URL({}) 耗时({} ms)]",request.getRequestURI(), stopWatch.getTotalTimeMillis());}}
}

截图如下:

在这里插入图片描述

相关文章:

详细分析SpringMvc中HandlerInterceptor拦截器的基本知识(附Demo)

目录 前言1. 基本知识2. Demo3. 实战解析 前言 对于Java的基本知识推荐阅读&#xff1a; java框架 零基础从入门到精通的学习路线 附开源项目面经等&#xff08;超全&#xff09;【Java项目】实战CRUD的功能整理&#xff08;持续更新&#xff09; 1. 基本知识 HandlerInter…...

阳光能源嵌入式面试及参考答案(2万字长文)

管道能够承载的最大传输数据量是多少? 在嵌入式系统中,管道能够承载的最大传输数据量取决于多个因素。 首先,管道的容量受到操作系统的限制。不同的操作系统对管道的大小有不同的规定。一般来说,管道的容量通常是有限的,并且在不同的操作系统版本和配置下可能会有所不同。…...

P10483 小猫爬山

1. #include<bits/stdc.h> using namespace std; //一个记录小猫的重量&#xff0c;sum记录当前小猫的重量之和 int n, w, a[3000],sum[3000],ans; bool cmp(int a,int b) {return a > b; } //x表示小猫当前的编号&#xff0c;cnt表示缆车的数量 void dfs(int x,int …...

技术速递|加入 .NET 智能组件生态系统

作者&#xff1a;Daniel Roth - 首席产品经理 排版&#xff1a;Alan Wang .NET 智能组件是一组示例嵌入式 UI 组件&#xff0c;使得在应用中轻松添加 AI 启用的功能变得更加简单&#xff0c;例如从剪贴板数据自动填写表单、智能文本补全以及语义搜索等场景。.NET 智能组件演示了…...

python/requests库的使用/爬虫基础工具/

requests 是一个 Python 库&#xff0c;它允许你发送 HTTP 请求。这个库需要单独安装&#xff0c;因为它不是 Python 标准库的一部分 1.让我们安装requests 在控制台运行 pip install requests 使用 requests 发送请求 1.GET 请求&#xff1a; import requestsresponse …...

【STM32-HAL库】MQ2烟雾传感器使用(STM32F407ZET6)

MQ2可燃气体传感器介绍 MQ2是一种广谱气体传感器&#xff0c;能够检测多种可燃气体和烟雾。它是一种低成本、高灵敏度的传感器&#xff0c;广泛应用于家庭和工业环境中的气体监测。 原理 MQ2传感器的工作原理基于金属氧化物半导体&#xff08;MOX&#xff09;技术。当传感器暴露…...

玩转指针(3)

一、字符指针变量 字符指针变量&#xff08;如char* p&#xff09;的两种赋值方式 ①将字符类型地址赋值给字符指针变量 int main() {char a w;char* p &a;*p m;return 0; }②将常量字符串赋值给字符指针变量 常量字符串的介绍&#xff1a;用" "引起来的就…...

【CSS in Depth 2 精译_040】6.3 CSS 定位技术之:相对定位(下)—— 用纯 CSS 绘制一个三角形

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一章 层叠、优先级与继承&#xff08;已完结&#xff09;第二章 相对单位&#xff08;已完结&#xff09;第三章 文档流与盒模型&#xff08;已完结&#xff09;第四章 Flexbox 布局&#xff08;已…...

HTML流光爱心

文章目录 序号目录1HTML满屏跳动的爱心&#xff08;可写字&#xff09;2HTML五彩缤纷的爱心3HTML满屏漂浮爱心4HTML情人节快乐5HTML蓝色爱心射线6HTML跳动的爱心&#xff08;简易版&#xff09;7HTML粒子爱心8HTML蓝色动态爱心9HTML跳动的爱心&#xff08;双心版&#xff09;1…...

java技能

日志实际使用 log.error(“111”,e);和 System.out.println(ExceptionUtils.getStackTrace(error)); 日志查询 tail -f root.log 前端页面命名&#xff1a; mounted(){ document.title‘设备可视页面’ } 查看ips所属mac nbtstat -a 10.87.236.60 获取容器名称 hostName In…...

本省第一所!新大学,揭牌!

9月26日&#xff0c;海南艺术职业学院举行揭牌仪式&#xff0c;标志着海南省第一所公办艺术类高等职业院校正式揭牌成立。海南省旅文厅党组成员、副厅长刘成出席揭牌仪式&#xff0c;省教育厅党组成员、副厅长邢孔政在揭牌仪式上宣读省人民政府同意设立海南艺术职业学院的批复。…...

企业微信(企微)审批与影刀RPA结合

企业微信审批与影刀RPA结合 效果先看视频&#xff1a; 影刀与企业微信审批结合 具体步骤&#xff1a; 1、登录企微管理后台&#xff0c;新建一个审批流。 添加模板→自定义模板&#xff0c;根据需求添加审批节点。 添加完之后&#xff0c;回到审批界面&#xff0c;可以看…...

新手教学系列——用 VSCode 实现高效远程开发

随着软件开发环境日益复杂,远程开发已成为许多开发者的日常工作方式。尤其当项目需要直接在服务器上运行或本地计算资源有限时,能够使用一款便捷、强大的工具至关重要。在众多 IDE 中,VSCode 因其轻量、灵活且支持丰富插件,成为远程开发的理想选择。本文将详细介绍如何通过…...

[uni-app]小兔鲜-04推荐+分类+详情

热门推荐 新建热门推荐组件, 动态设置组件的标题 <template><!-- 推荐专区 --><view class"panel hot"><view class"item" v-for"item in list" :key"item.id">... ...<navigator hover-class"none&…...

PHP人才机遇桥梁招聘求职全能系统小程序源码

人才机遇桥梁 —— 招聘求职全能系统全解析 &#x1f4bc;&#x1f680; &#x1f309; 搭建人才与机遇的桥梁 在这个竞争激烈的职场环境中&#xff0c;找到一份心仪的工作或招募到合适的人才&#xff0c;往往不是一件容易的事。但幸运的是&#xff0c;我们有了“人才机遇桥梁…...

计算机毕业设计Hadoop+Spark抖音可视化 抖音舆情监测 预测算法 抖音爬虫 抖音大数据 情感分析 NLP 自然语言处理 Hive 机器学习 深度学习

Python抖音可视化开题报告 一、研究背景与意义 随着移动互联网的迅猛发展&#xff0c;短视频平台如抖音已成为人们日常生活中不可或缺的一部分。抖音以其独特的算法和内容推荐机制&#xff0c;吸引了数以亿计的用户。然而&#xff0c;随着用户规模的不断扩大&#xff0c;如何…...

Linux 学习 awk 和sed 命令使用

awk 命令 awk 是一种处理文本文件的语言&#xff0c;是一个强大的文本分析工具。 awk 通过提供编程语言的功能&#xff0c;如变量、数学运算、字符串处理等&#xff0c;使得对文本文件的分析和操作变得非常灵活和高效。 之所以叫 awk 是因为其取了三位创始人 Alfred Aho&#x…...

双端搭建个人博客

1. 准备工作 确保你的两个虚拟机都安装了以下软件: 虚拟机1(Web服务器): Apache2, PHP虚拟机2(数据库服务器): MariaDB2. 安装步骤 虚拟机1(Web服务器) 安装Apache2和PHP 更新系统包列表: sudo apt update安装Apache2: sudo apt install apache2 -y安装PHP及其Apac…...

PHP 面向对象编程

PHP 面向对象编程 PHP 是一种流行的服务器端脚本语言&#xff0c;广泛用于 web 开发。它支持多种编程范式&#xff0c;包括面向对象编程&#xff08;OOP&#xff09;。面向对象编程是一种编程风格&#xff0c;它使用“对象”来设计软件&#xff0c;其中对象是数据和行为的集合…...

应急响应(1)-同事电脑

一、现象 重要时间节点&#xff0c;同事反馈桌面有鼠标移动、随机断网&#xff1b;发现登录账户多了一个&#xff0c;由于电脑长时间没有更改过密码&#xff0c;导致忘记密码无法登录。随机联系进行应急处理。 二、排查 2.1、密码重置/删除 由于同事忘记密码导致无法进行登录…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...