HandlerInterceptor介绍-笔记

1. HandlerInterceptor简介

org.springframework.web.servlet.HandlerInterceptor 是 Spring MVC 中用于拦截 HTTP 请求的核心接口。

public interface HandlerInterceptor {default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {return true;}default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {}default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {}
}

HandlerInterceptor 的核心方法介绍

  1. preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

    • 作用:在请求处理之前执行(即在控制器方法执行前)。
    • 返回值:返回 true 表示继续后续处理;返回 false 表示中断请求(直接返回响应)。
    • 典型用途:权限校验、请求日志记录。
  2. postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)

    • 作用:在请求处理完成后、视图渲染之前执行。
    • 参数说明modelAndView 是控制器方法返回的结果。
    • 典型用途:修改模型数据、记录响应日志。
  3. afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)

    • 作用:在整个请求完成时执行(即视图渲染结束后)。
    • 典型用途:资源清理、异常处理、性能统计。

它允许开发者在请求处理的不同阶段插入自定义逻辑,例如权限验证、日志记录、性能监控等。通过实现该接口的三个关键方法,可以灵活控制请求的处理流程。

2. 使用示例

2.1 日志拦截器demo

下面以一个 日志拦截器 为例,演示如何使用HandlerInterceptor。

step1.实现 HandlerInterceptor 接口

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;public class LoggingHandlerInterceptor implements HandlerInterceptor {// 请求处理前执行@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {String requestId = UUID.randomUUID().toString();request.setAttribute("requestId", requestId);System.out.println("=== PreHandle ===");System.out.println("Request ID: " + requestId);System.out.println("Request URL: " + request.getRequestURL());return true; // 继续后续处理}// 请求处理后、视图渲染前执行@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) {System.out.println("=== PostHandle ===");if (modelAndView != null) {System.out.println("View Name: " + modelAndView.getViewName());return;}System.out.println("No view");}// 请求完成时执行@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex) {System.out.println("=== AfterCompletion ===");if (ex != null) {System.out.println("Exception occurred: " + ex.getMessage());}System.out.println("Response Status: " + response.getStatus());System.out.println("Request ID: " + request.getAttribute("requestId"));}
}

step2.注册拦截器到 Spring MVC 配置

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 HandlerInterceptorWebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoggingHandlerInterceptor()).addPathPatterns("/**") // 拦截所有路径.excludePathPatterns("/public/**"); // 排除特定路径;}
}

step3.创建测试controller

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HandlerInterceptorController {@GetMapping("HandlerInterceptorController/test")public String test() {return "test";}
}

step4. 测试

启动应用,浏览器输入  http://127.0.0.1:8080/HandlerInterceptorController/test ,日志输出如下:

2.2 其他使用场景demo

2.2.1 权限验证

在 preHandle 中检查用户是否登录,未登录则重定向到登录页面:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {if (userNotAuthenticated(request)) {response.sendRedirect("/login");return false; // 中断请求}return true;
}

2.2.2 性能监控

在 preHandle 记录开始时间,在 afterCompletion 计算耗时:

private Long startTime;@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {startTime = System.currentTimeMillis();return true;
}@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {long duration = System.currentTimeMillis() - startTime;System.out.println("Request took " + duration + " ms");
}

2.3 注意事项

  1. 拦截器顺序:多个拦截器时,注册顺序决定执行顺序preHandle 按注册顺序执行,afterCompletion 按逆序执行)。
  2. 异常处理afterCompletion 中可以通过 Exception ex 参数捕获控制器抛出的异常。
  3. 线程安全:拦截器默认是单例的,避免在拦截器中使用成员变量存储请求相关数据(可通过 request.setAttribute 传递)。

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

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

相关文章

C++循环效率比较与优化建议

在 C++ 中,不同循环结构(如 for、while、do-while、基于范围的 for)在优化后的性能通常是等效的,因为现代编译器会对它们进行底层优化,生成相似的机器代码。循环的效率更多取决于循环体内的操作和数据访问模式,而非循环结构本身的选择。以下是关键点总结: 1. 传统循环的…

北京孙河傲云源墅:限量典藏的主城墅居臻品

在限墅令的背景下,北京主城的墅居产品日益稀缺,而傲云源墅作为孙河墅区的杰出之作,凭借其独特的价值,成为了众多高端置业者的理想选择。 傲云源墅所处的孙河地区,是北京公认的高价值板块。其地位在 2025 年孙河 2902 …

简单入门RabbitMQ

本章将带大家来写一个简单的程序,使用 Java 创建RabbitMQ 的生产者和消费者 依赖引入 在 Maven 仓库中输入 amqp-client: 找到第一个 RabbitMQ Java Client ,点击进去找到一个合适的版本然后将依赖引入到我们项目中的 pom.xml 文件中。 …

Git基础使用方法与命令总结

Git 是一个分布式版本控制系统,用于跟踪代码或文件的修改历史。以下是 Git 的基础使用方法和常用命令,适合快速上手: 1. 安装与配置 安装 Git 下载地址:https://git-scm.com/downloads(支持 Windows/macOS/Linux&…

Oracle SYSTEM/UNDO表空间损坏的处理思路

Oracle SYSTEM/UNDO表空间损坏是比较棘手的故障,通常会导致数据库异常宕机进而无法打开数据库。数据库的打开故障处理起来相对比较麻烦,读者可以参考本书第5章进一步了解该类故障的处理过程。如果数据库没有备份,通常需要设置官方不推荐的隐含…

The Graph:区块链数据索引的技术架构与创新实践

作为Web3生态的核心基础设施,The Graph通过去中心化索引协议重塑了链上数据访问的范式。其技术设计不仅解决了传统区块链数据查询的效率瓶颈,还通过经济模型与多链兼容性构建了一个开放的开发者生态。本文从技术角度解析其架构、机制及创新实践。 一、技…

在24GB显存大小的GPU上运行27GB的Pytorch模型

在24GB显存大小的GPU上运行27GB的Pytorch模型 一.背景:显存不足时的破局之道1.1 大模型时代的显存困境1.2 CUDA统一内存的魔法二.性能测试数据深度解读关键发现:三.复现过程3.1 准备自定义分配器3.2 准备测试程序3.3 执行流程3.4 开始测试四.原理深度剖析4.1 统一内存的工作机…

Spring Boot 参数验证

一、依赖配置 首先确保在 pom.xml 中添加了以下依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId> </dependency> 这个依赖包含了 Hibernate Valida…

SHAP分析!Transformer-GRU组合模型SHAP分析,模型可解释不在发愁!

SHAP分析&#xff01;Transformer-GRU组合模型SHAP分析&#xff0c;模型可解释不在发愁&#xff01; 目录 SHAP分析&#xff01;Transformer-GRU组合模型SHAP分析&#xff0c;模型可解释不在发愁&#xff01;效果一览基本介绍程序设计参考资料 效果一览 基本介绍 基于SHAP分析…

在微创手术中使用Kinova轻型机械臂进行多视图图像采集和3D重建

在微创手术中&#xff0c;Kinova轻型机械臂通过其灵活的运动控制和高精度的操作能力&#xff0c;支持多视图图像采集和3D重建。这种技术通过机械臂搭载的光学系统实现精准的多角度扫描&#xff0c;为医疗团队提供清晰且详细的解剖结构模型。其核心在于结合先进的传感器配置与重…

Qt事件循环机制

受事件循环机制影响&#xff0c;按钮的样式表改变了可能不会立即刷新。 需要使用 update() 或 repaint() 或者调用 QApplication::processEvents() 强制处理所有待处理的事件&#xff0c;从而确保界面更新。 在 Qt 中&#xff0c;事件循环&#xff08;Event Loop&#xff09;是…

Leaflet 自定义瓦片地图与 PHP 大图切图算法 解决大图没办法在浏览器显示的问题

为什么使用leaflet 使用 Leaflet 来加载大图片&#xff08;尤其是通过瓦片化的方式&#xff09;是一种高效的解决方案&#xff0c;主要原因如下&#xff1a; 1. 性能优化 减少内存占用&#xff1a;直接加载大图片会占用大量内存&#xff0c;可能导致浏览器崩溃或性能下降。瓦片…

一种应用非常广泛的开源RTOS(实时操作系统):nuttx

什么是NuttX&#xff1f; NuttX&#xff08;读音接近“纳特-艾克斯”&#xff09;是一种应用非常广泛的开源RTOS&#xff08;实时操作系统&#xff09;&#xff0c;由Gregory Nutt博士主要推动开发。RTOS&#xff0c;即 Real-Time Operating System&#xff0c;直译为“实时操…

Python中plotext 库详细使用(命令行界面中直接绘制各种图形)

更多内容请见: python3案例和总结-专栏介绍和目录 文章目录 plotext概述1.1 plotext介绍1.2 安装二、基本用法2.1 简单绘图2.2 散点图2.3 折线图2.4 条形图2.5 直方图2.6 标题和坐标轴标签2.7 网格和坐标轴2.8 颜色和样式2.9 多图叠加三、高级功能3.1 多图绘制3.2 对数坐标3.3…

使用 ESP32 驱动 ±12V 压电无源蜂鸣器(NPN 三极管 + PWM 控制驱动电路)

&#x1f50a; 使用 ESP32 驱动 12V 压电无源蜂鸣器&#xff08;NPN 三极管 PWM 控制驱动电路&#xff09; 本教程将介绍如何使用 ESP32 控制一个额定工作电压为 12V 的压电无源蜂鸣器&#xff0c;通过 NPN 三极管 PWM 信号实现音量更大的驱动方案。 &#x1f9e0; 教程目标…

python调用金蝶api接口

金蝶接口 登录接口 https://xxx.xxx.com/k3cloud/Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc 查询单据接口 https://xxx.xxx.com/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery.common.kdsvc 基础资料保存接口、…

12 web 自动化之基于关键字+数据驱动-反射自动化框架搭建

文章目录 一、如何实现一条用例&#xff0c;实现覆盖所有用例的测试1、结合数据驱动&#xff1a;编辑一条用例&#xff0c;外部导入数据实现循环测试2、用例体&#xff1a;实现不同用例的操作步骤对应的断言 二、实战1、项目路径总览2、common 文件夹下的代码文件3、keywords 文…

Ubuntu shell指定conda的python环境启动脚本

Ubuntu shell指定conda的python环境启动脚本。 通过指令&#xff0c;获取目前系统的conda虚拟python环境 conda info -e 如下图所示&#xff0c;为我自己电脑的python环境 # conda environments: # base * /home/ubuntu/miniconda3 kitti …

博客系统技术需求文档(基于 Flask)

以下内容是AI基于要求生成的技术文档&#xff0c;仅供参考~ &#x1f9f1; 一、系统架构设计概览 层级 内容 前端层 HTML Jinja2 模板引擎&#xff0c;集成 Markdown 编辑器、代码高亮 后端层 Flask 框架&#xff0c;RESTful 风格&#xff0c;Jinja2 渲染 数据库 SQLi…

【Linux 学习计划】-- 权限

目录 权限是什么 权限的本质 权限&#xff08;用户&#xff09;的修改 权限的匹配机制 目录的权限 初始权限&#xff08;文件和目录&#xff09; 粘滞位 结语 权限是什么 在现实世界中就有权限的概念&#xff0c;也就是&#xff0c;一部分人能做但是其他没有相关身份的…