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

springmvc中使用interceptor拦截

`HandlerInterceptor` 是Spring MVC中用于在请求处理之前、之后以及完成之后执行逻辑的接口。它与Servlet的`Filter`类似,但更加灵活,因为它可以访问Spring的上下文和模型数据。`HandlerInterceptor` 常用于日志记录、权限验证、性能监控等场景。

### **1. 创建自定义 `HandlerInterceptor`**

要使用 `HandlerInterceptor`,你需要实现 `HandlerInterceptor` 接口,并重写以下方法:

- `preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)`:在请求处理之前被调用,返回`true`表示继续执行后续的拦截器或Controller,返回`false`表示中断执行。
- `postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)`:在请求处理之后被调用,但视图渲染之前。
- `afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)`:在请求处理完成之后被调用,无论是否发生异常。

以下是一个简单的自定义 `HandlerInterceptor` 示例:

```java
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CustomInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 请求处理之前执行
        System.out.println("Pre Handle method is Calling");
        System.out.println("Request URL: " + request.getRequestURL());
        return true; // 返回true继续执行后续逻辑,返回false中断执行
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 请求处理之后执行
        System.out.println("Post Handle method is Calling");
        if (modelAndView != null) {
            modelAndView.addObject("timestamp", System.currentTimeMillis());
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 请求处理完成之后执行
        System.out.println("Request and Response is completed");
        if (ex != null) {
            System.out.println("Exception occurred: " + ex.getMessage());
        }
    }
}
```

### **2. 注册 `HandlerInterceptor`**

在Spring MVC中,可以通过 `WebMvcConfigurer` 接口注册 `HandlerInterceptor`。以下是一个示例:

```java
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 {

    @Autowired
    private CustomInterceptor customInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册自定义拦截器,指定拦截路径
        registry.addInterceptor(customInterceptor)
                .addPathPatterns("/api/**") // 拦截/api路径下的所有请求
                .excludePathPatterns("/api/public/**"); // 排除/api/public路径下的请求
    }
}
```

### **3. 测试 `HandlerInterceptor`**

启动Spring Boot应用后,访问 `/api/**` 路径下的任何接口,`CustomInterceptor` 都会拦截请求并执行相应的逻辑。

### **4. 使用场景**
- **日志记录**:记录请求的URL、参数、响应时间等。
- **权限验证**:在 `preHandle` 方法中检查用户是否登录,是否有权限访问某个资源。
- **性能监控**:在 `preHandle` 和 `afterCompletion` 方法中记录请求处理的时间。
- **数据预处理**:在 `postHandle` 方法中修改模型数据或视图。

### **5. 完整示例**

以下是一个完整的Spring Boot项目示例,包含自定义 `HandlerInterceptor` 和注册逻辑:

#### **`CustomInterceptor.java`**
```java
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CustomInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Pre Handle method is Calling");
        System.out.println("Request URL: " + request.getRequestURL());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Post Handle method is Calling");
        if (modelAndView != null) {
            modelAndView.addObject("timestamp", System.currentTimeMillis());
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("Request and Response is completed");
        if (ex != null) {
            System.out.println("Exception occurred: " + ex.getMessage());
        }
    }
}
```

#### **`WebConfig.java`**
```java
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 {

    @Autowired
    private CustomInterceptor customInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(customInterceptor)
                .addPathPatterns("/api/**")
                .excludePathPatterns("/api/public/**");
    }
}
```

#### **`Controller` 示例**
```java
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @GetMapping("/api/test")
    public String test() {
        return "Hello, World!";
    }

    @GetMapping("/api/public/test")
    public String publicTest() {
        return "This is a public endpoint";
    }
}
```

### **6. 输出示例**
访问 `/api/test` 时,控制台输出:
```
Pre Handle method is Calling
Request URL: http://localhost:8080/api/test
Post Handle method is Calling
Request and Response is completed
```

访问 `/api/public/test` 时,控制台不会输出拦截器的日志,因为该路径被排除了。

通过以上方法,你可以轻松地在Spring项目中使用 `HandlerInterceptor` 来实现各种功能。

下面这个例子是使用了自定义注解方式

在Spring中结合`HandlerInterceptor`和自定义注解可以实现灵活的请求处理逻辑,例如权限校验、日志记录等。以下是一个完整的示例,展示如何定义自定义注解,并在`HandlerInterceptor`中使用它。

### **1. 定义自定义注解**

首先,定义一个自定义注解,用于标记需要特殊处理的Controller方法。例如,定义一个`@Loggable`注解,用于记录方法的调用信息:

```java
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 Loggable {
    String value() default ""; // 可选的描述信息
}
```

### **2. 创建拦截器**

接下来,创建一个`HandlerInterceptor`实现类,用于在请求处理前后执行逻辑:

```java
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoggingInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Loggable loggable = handlerMethod.getMethodAnnotation(Loggable.class);
            if (loggable != null) {
                // 获取注解的值
                String description = loggable.value();
                System.out.println("Logging: " + description);
            }
        }
        return true; // 继续后续处理
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("Request completed");
    }
}
```

### **3. 注册拦截器**

在Spring配置中注册拦截器,使其生效:

```java
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 {

    @Autowired
    private LoggingInterceptor loggingInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loggingInterceptor)
                .addPathPatterns("/**") // 拦截所有路径
                .excludePathPatterns("/static/**", "/css/**", "/js/**"); // 排除静态资源
    }
}
```

### **4. 使用自定义注解**

在Controller方法上使用自定义注解:

```java
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ExampleController {

    @GetMapping("/example")
    @Loggable(value = "This is an example method")
    public String exampleMethod() {
        return "Hello, World!";
    }
}
```

### **5. 测试**

启动Spring Boot应用后,访问`/example`路径,控制台将输出类似以下内容:

```
Logging: This is an example method
Request completed
```

### **总结**

通过定义自定义注解并结合`HandlerInterceptor`,可以在Spring MVC中灵活地为特定方法添加额外的处理逻辑,例如日志记录、权限校验等。这种方法使得代码更加清晰且易于维护。

相关文章:

springmvc中使用interceptor拦截

HandlerInterceptor 是Spring MVC中用于在请求处理之前、之后以及完成之后执行逻辑的接口。它与Servlet的Filter类似,但更加灵活,因为它可以访问Spring的上下文和模型数据。HandlerInterceptor 常用于日志记录、权限验证、性能监控等场景。 ### **1. 创…...

C++基础 [八] - list的使用与模拟实现

目录 list的介绍 List的迭代器失效问题 List中sort的效率测试 list 容器的模拟实现思想 模块分析 作用分析 list_node类设计 list 的迭代器类设计 迭代器类--存在的意义 迭代器类--模拟实现 模板参数 和 成员变量 构造函数 * 运算符的重载 运算符的重载 -- 运…...

使用excel.EasyExcel实现导出有自定义样式模板的excel数据文件,粘贴即用!!!

客户要求导出的excel文件是有好看格式的,当然本文举例模板文件比较简单,内容丰富的模板可以自行设置,话不多说,第一步设置一个"好看"的excel文件模板 上面要注意的地方是{.变量名} ,这里的变量名对应的就是…...

Spring Boot 集成 Elasticsearch怎样在不启动es的情况下正常启动服务

解释 在spingboot 集成es客户端后,每当服务启动时,服务默认都会查看es中是否已经创建了对应的索引,如果没有索引则创建。基于上面的规则我们可以通过配置不自动创建索引来达到在没有es服务的情况下正常启动服务。 解决办法 在entity类的Docu…...

Java面试黄金宝典8

1. 什么是 Spring MVC 定义 Spring MVC 是 Spring 框架里用于构建 Web 应用程序的模块,它严格遵循 MVC(Model - View - Controller)设计模式。这种设计模式把应用程序清晰地划分成三个主要部分: Model(模型&#xff0…...

JVM常见概念之条件移动

问题 当我们有分支频率数据时,有什么有趣的技巧可以做吗?什么是条件移动? 基础知识 如果您需要在来自一个分支的两个结果之间进行选择,那么您可以在 ISA 级别做两件不同的事情。 首先,你可以创建一个分支&#xff…...

Android AI ChatBot-v1.6.3-28-开心版[免登录使用GPT-4o和DeepSeek]

Android AI ChatBot- 链接:https://pan.xunlei.com/s/VOLi1Ua071S6QZBGixcVL5eeA1?pwdp3tt# 免登录使用GPT-4o和DeepSeek...

集成学习(上):Bagging集成方法

一、什么是集成学习? 在机器学习的世界里,没有哪个模型是完美无缺的。就像古希腊神话中的"盲人摸象",单个模型往往只能捕捉到数据特征的某个侧面。但当我们把多个模型的智慧集合起来,就能像拼图一样还原出完整的真相&a…...

DeepSeek R1 本地部署指南 (3) - 更换本地部署模型 Windows/macOS 通用

0.准备 完成 Windows 或 macOS 安装: DeepSeek R1 本地部署指南 (1) - Windows 本地部署-CSDN博客 DeepSeek R1 本地部署指南 (2) - macOS 本地部署-CSDN博客 以下内容 Windows 和 macOS 命令执行相同: Windows 管理员启动:命令提示符 CMD ma…...

【TI MSPM0】Timer学习

一、计数器 加法计数器:每进入一个脉冲,就加一减法计算器:每进入一个脉冲,就减一 当计数器减到0,触发中断 1.最短计时时间 当时钟周期为1khz时,最短计时时间为1ms,最长计时时间为65535ms 当时…...

Windows部署deepseek R1训练数据后通过AnythingLLM当服务器创建问答页面

如果要了解Windows部署Ollama 、deepseek R1请看我上一篇内容。 这是接上一篇的。 AnythingLLM是一个开源的全栈AI客户端,支持本地部署和API集成。它可以将任何文档或内容转化为上下文,供各种语言模型(LLM)在对话中使用。以下是…...

重删算法中的Bloom滤波器详解与C++实现

一、Bloom滤波器基础概念 Bloom滤波器(Bloom Filter)是一种空间高效的概率型数据结构,用于快速判断某个元素是否存在于集合中。其核心特性: 存在不确定性:可能出现假阳性(False Positive)&…...

信奥赛CSP-J复赛集训(模拟算法专题)(27):P5016 [NOIP 2018 普及组] 龙虎斗

信奥赛CSP-J复赛集训(模拟算法专题)(27):P5016 [NOIP 2018 普及组] 龙虎斗 题目背景 NOIP2018 普及组 T2 题目描述 轩轩和凯凯正在玩一款叫《龙虎斗》的游戏,游戏的棋盘是一条线段,线段上有 n n n 个兵营(自左至右编号 1 ∼ n 1 \sim n 1∼n),相邻编号的兵营之间…...

多模态大模型常见问题

1.视觉编码器和 LLM 连接时,使用 BLIP2中 Q-Former那种复杂的 Adaptor 好还是 LLaVA中简单的 MLP 好,说说各自的优缺点? Q-Former(BLIP2): 优点:Q-Former 通过查询机制有效融合了视觉和语言特征…...

SpringBoot项目实战(初级)

目录 一、数据库搭建 二、代码开发 1.pom.xml 2.thymeleaf模块处理的配置类 3.application配置文件 4.配置(在启动类中) 5.编写数据层 ②编写dao层 ③编写service层 接口 实现类 注意 补充(注入的3个注解) 1.AutoWir…...

Linux NFS、自动挂载与系统启动管理指南

1. NFS客户端挂载导出的目录的方式 NFS(网络文件系统) 允许将远程服务器的目录挂载到本地,像访问本地文件一样操作远程文件。挂载方式主要有两种: 手动挂载:使用 mount 命令(临时生效,重启后丢…...

uniapp实现全局拖拽按钮

要先引入 “vue3-draggable-resizable”: “^1.6.5” 1.创建DragComponent组件 <template><!-- 抽屉组件 --><div class"drag-container" id"dragBox" :style"{ zIndex: zIndex }"><Vue3DraggableResizable :initW"…...

SOFABoot-10-聊一聊 sofatboot 的十个问题

前言 大家好&#xff0c;我是老马。 sofastack 其实出来很久了&#xff0c;第一次应该是在 2022 年左右开始关注&#xff0c;但是一直没有深入研究。 最近想学习一下 SOFA 对于生态的设计和思考。 sofaboot 系列 SOFABoot-00-sofaboot 概览 SOFABoot-01-蚂蚁金服开源的 s…...

计算机网络——总结

01. 网络的发展及体系结构 网络演进历程 从1969年ARPANET的4个节点发展到如今覆盖全球的互联网&#xff0c;网络技术经历了电路交换到分组交换、有线连接到无线覆盖的革命性变革。5G时代的到来使得网络传输速度突破10Gbps&#xff0c;物联网设备数量突破百亿级别。 网络体系…...

Umi-OCR- OCR 文字识别工具,支持截图、批量图片排版解析

Umi-OCR 是免费开源的离线 OCR 文字识别软件。无需联网&#xff0c;解压即用&#xff0c;支持截图、批量图片、PDF 扫描件的文字识别&#xff0c;能识别数学公式、二维码&#xff0c;可生成双层可搜索 PDF。内置多语言识别库&#xff0c;界面支持多语言切换&#xff0c;提供命令…...

高速网络包处理,基础网络协议上内核态直接处理数据包,XDP技术的原理

文章目录 预备知识TCP/IP 网络模型&#xff08;4层、7层&#xff09;iptables/netfilterlinux网络为什么慢 DPDKXDPBFPeBPFXDPXDP 程序典型执行流通过网络协议栈的入包XDP 组成 使用 GO 编写 XDP 程序明确流程选择eBPF库编写eBPF代码编写Go代码动态更新黑名单 预备知识 TCP/IP…...

C++:背包问题习题

1. 货币系统 1371. 货币系统 - AcWing题库 给定 V 种货币&#xff08;单位&#xff1a;元&#xff09;&#xff0c;每种货币使用的次数不限。 不同种类的货币&#xff0c;面值可能是相同的。 现在&#xff0c;要你用这 V 种货币凑出 N 元钱&#xff0c;请问共有多少种不同的…...

数据可信安全流通实战,隐语开源社区Meetup武汉站开放报名

隐语开源社区 Meetup 系列再出发&#xff01;2025 年将以武汉为始发站&#xff0c;聚焦"技术赋能场景驱动"&#xff0c;希望将先进技术深度融入数据要素流转的各个环节&#xff0c;推动其在实际应用场景中落地生根&#xff0c;助力释放数据要素的最大潜能&#xff01…...

java使用Apache POI 操作word文档

项目背景&#xff1a; 当我们对一些word文档&#xff08;该文档包含很多的标题比如 1.1 &#xff0c;1.2 &#xff0c; 1.2.1.1&#xff0c; 1.2.2.3&#xff09;当我们删除其中一项或者几项时&#xff0c;需要手动的对后续的进行补充。该功能主要是对标题进行自动的补充。 具…...

【 C/C++ 包管理工具】vcpkg安装+使用

【 C/C 包管理工具】vcpkg安装使用 Vcpkg 是由 Microsoft 和 C 社区维护的免费开源 C/C 包管理器&#xff0c;可在 Windows、macOS 和 Linux 上运行。 可以很方便的安装管理 C/C 库。 1. 安装 不要安装到Program Files这种有空格的路径下&#xff0c;否则后面安装库可能出现…...

免费开源的NAS解决方案:TrueNAS

TrueNAS是业内知名的FreeNAS系统的升级版&#xff0c;是一款开源的网络存储系统&#xff0c;具有高性能、稳定性和易用性等优点。 TrueNAS目前有三个版本&#xff0c;分别是TrueNAS CORE、TrueNAS ENTERPRISE、TrueNAS SCALE。其中&#xff0c;TrueNAS CORE基于FreeBSD开发&…...

LeetCode热题100精讲——Top1:两数之和【哈希】

你好&#xff0c;我是安然无虞。 文章目录 题目背景两数之和C解法Python解法 题目背景 如果大家对于 哈希 类型的概念并不熟悉, 可以先看我之前为此专门写的算法详解: 蓝桥杯算法竞赛系列第九章巧解哈希题&#xff0c;用这3种数据类型足矣 两数之和 题目链接&#xff1a;两数…...

github上传操作简单说明

前期准备 0.下载git&#xff08;如果已经有了就不用了&#xff09; 1.在GitHub上新建一个存储库 2.先在本地创建一个目录作为本地库目录&#xff0c;在目录里打开git bash进行上传 上传过程 echo "# Garbled_repair" >> README.md 作用&#xff1a;创建一个…...

GitLens with `Commit Graph`

文章目录 GitLens with Commit Graph GitLens with Commit Graph 想要更直观地查看 Git 提交历史&#xff1f;我打包了一个支持 Commit Graph 的 GitLens 版本&#xff0c;让你轻松在 VSCode 中查看分支、合并、变更记录等内容&#xff0c;一目了然&#xff01; &#x1f4cc…...

Rocky9.5基于sealos快速部署k8s集群

首先需要下载 Sealos 命令行工具&#xff0c;sealos 是一个简单的 Golang 二进制文件&#xff0c;可以安装在大多数 Linux 操作系统中。 以下是一些基本的安装要求&#xff1a; 每个集群节点应该有不同的主机名。主机名不要带下划线。 所有节点的时间需要同步。 需要在 K8s …...