SpringMVC拦截器深度解析与实战

embedded/2024/9/20 1:20:25/ 标签: java, spring, 后端, 开发语言

引言

Spring MVC作为Spring框架的核心模块之一,主要用于构建Web应用程序和RESTful服务。在Spring MVC中,拦截器(Interceptor)是一种强大的机制,它允许开发者在请求处理流程的特定点插入自定义代码,实现诸如权限验证、日志记录、请求预处理等功能。本文将深入解析Spring MVC拦截器的概念、工作原理、使用场景以及实现方式,并通过代码示例进行演示。

拦截器概念

什么是拦截器

拦截器(Interceptor)是Spring MVC中用于动态拦截请求处理流程的一种机制。在请求到达控制器(Controller)之前或响应返回给客户端之后,拦截器可以对请求和响应进行预处理和后处理。拦截器是AOP(面向切面编程)思想在Spring MVC中的具体实现之一。

拦截器与过滤器的区别

拦截器和过滤器(Filter)在Web开发中经常被提及,但它们之间存在明显的区别:

  • 作用范围:过滤器可以拦截几乎所有的请求,包括静态资源,而拦截器只能拦截到控制器(Controller)中的请求方法。
  • 依赖关系:过滤器依赖于Servlet容器,而拦截器不依赖于Web容器,是Spring MVC的组件。
  • 灵活性:拦截器可以方便地访问Spring容器中的bean,而过滤器则相对困难。

拦截器的作用

拦截器主要用于在请求处理流程中的特定点执行自定义逻辑,其作用包括但不限于:

  • 权限验证:检查用户是否拥有访问某个资源的权限。
  • 日志记录:记录请求和响应的详细信息,便于问题追踪。
  • 请求预处理:在请求到达控制器之前对请求数据进行修改或补充。
  • 响应后处理:在响应返回给客户端之前对响应数据进行修改或添加额外的头信息。

拦截器的实现

定义拦截器

在Spring MVC中,定义一个拦截器需要实现HandlerInterceptor接口或继承HandlerInterceptorAdapter类。HandlerInterceptor接口包含三个方法:

  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handler): 在请求处理之前进行调用(Controller方法调用之前)。
  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView): 请求处理之后进行调用,但在视图被渲染之前(Controller方法调用之后,DispatcherServlet渲染视图之前)。
  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex): 在整个请求结束之后被调用,也就是在DispatcherServlet渲染了对应的视图执行之后。

示例代码

以下是一个简单的拦截器实现示例:

java

package com.example.interceptor;

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 {

@Override 

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

System.out.println("在Controller方法执行前执行");

// 可以进行权限验证等操作,如果验证失败,返回false以中断后续流程

return true;

}

@Override 

public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

System.out.println("在Controller方法执行后,视图渲染前执行");

// 可以对ModelAndView进行修改

if (modelAndView != null) {

modelAndView.addObject("customAttribute", "自定义属性值");

}

}

@Override 

public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

System.out.println("在所有请求处理完成后执行");

// 进行资源清理等操作

}

}

配置拦截器

定义拦截器后,需要在Spring MVC配置中注册该拦截器,并指定其拦截的路径。在Spring Boot项目中,通常通过实现WebMvcConfigurer接口并重写addInterceptors方法来完成:

当然,下面是继续完成WebConfig类的实现,包括如何将自定义的拦截器添加到Spring MVC的拦截器链中,并指定其拦截的路径。

完成WebConfig配置

java

package com.example.config;

import com.example.interceptor.MyInterceptor;

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 MyInterceptor myInterceptor;

@Override 

public void addInterceptors(InterceptorRegistry registry) {

// 添加拦截器,并设置拦截路径和排除路径

registry.addInterceptor(myInterceptor)

.addPathPatterns("/**") // 拦截所有请求

.excludePathPatterns("/static/**", "/error"); // 排除静态资源和错误页面的拦截

}

}

在这个配置中,addInterceptors方法通过InterceptorRegistry注册了MyInterceptor拦截器,并使用addPathPatterns方法指定了拦截器需要拦截的路径模式(在这个例子中是所有请求,即/**)。同时,使用excludePathPatterns方法排除了静态资源(如/static/**)和错误页面(/error)的拦截,这是为了避免对不需要拦截的资源进行不必要的处理。

拦截器的使用场景

  1. 权限控制:在preHandle方法中检查用户是否拥有访问某个资源的权限,如果没有则直接返回错误响应或重定向到登录页面。
  2. 日志记录:在preHandleafterCompletion方法中记录请求和响应的详细信息,包括请求参数、IP地址、处理时间等,有助于问题的追踪和系统的监控。
  3. 请求预处理:在preHandle方法中修改请求参数、设置请求头或执行其他预处理操作。
  4. 响应后处理:在postHandle方法中修改响应内容或状态码,或在afterCompletion方法中执行一些清理工作。
  5. 性能监控:在preHandleafterCompletion方法中记录时间戳,计算请求处理时间,从而监控系统的性能。

注意事项

  • 拦截器的执行顺序:在Spring MVC中,拦截器的执行顺序是通过它们在InterceptorRegistry中的注册顺序来决定的。如果需要改变执行顺序,可以调整注册的顺序。
  • 拦截器链的传递性:在preHandle方法中返回false将中断拦截器链的后续执行,并直接跳到afterCompletion方法(如果存在)。如果返回true,则继续执行下一个拦截器的preHandle方法或最终执行控制器的目标方法。
  • 拦截器的错误处理:在拦截器链中的任何位置发生异常时,都会依次执行已调用拦截器的afterCompletion方法(如果有的话),即使异常发生在preHandle方法中也是如此。

通过上述解析和示例,你应该对Spring MVC中的拦截器有了更深入的理解,并能够在实际项目中灵活运用它们来增强Web应用的功能和性能。


http://www.ppmy.cn/embedded/108350.html

相关文章

今天又学到了——图编号关联章节号,QGIS下载文件存储的瓦片

记录教程来源:​​​​​​【Word图编号关联章节号】图片分章节 编号,图1-1、图2-1_哔哩哔哩_bilibili 上面链接这个实现的是这个效果: word自动目录及章节自动编号教程_哔哩哔哩_bilibili,这个的效果是自己设计多级列表&#xf…

uni-app全局引入js文件

js文件定义 对于js文件内方法的编写,可以采用以下两种形式,两种形式对应两种不同的文件引入: const showToast {test: function() {console.log("测试2")} } export default showToast 引入: import showToast from…

详解TensorRT的C++高性能部署以及C++部署Yolo实践

详解TensorRT的C高性能部署 一. ONNX1. ONNX的定位2. ONNX模型格式3. ONNX代码使用实例 二、TensorRT1 引言 三、C部署Yolo模型实例 一. ONNX 1. ONNX的定位 ONNX是一种中间文件格式,用于解决部署的硬件与不同的训练框架特定的模型格式的兼容性问题。 ONNX本身其…

PostgreSQL的基础知识

什么是数据库? 数据库(Database)是一个用于存储、检索、管理和分析数据的集合。它是按照一定的数据模型组织、存储的集合,具有统一的结构形式、定义的相互关系、制定的约束条件和一定的冗余度,以便于在各种用户、各种…

浅聊kubernetes RBAC

RBAC 基于角色(Role)的访问控制(RBAC)是一种基于组织中用户的角色来调节控制对计算机或网络资源的访问的方法。 RBAC 鉴权机制使用 rbac.authorization.k8s.io API 组来驱动鉴权决定, 允许你通过 Kubernetes API 动态…

C++学习笔记(8)

184、基于范围的 for 循环 对于一个有范围的集合来说,在程序代码中指定循环的范围有时候是多余的,还可能犯错误。 C11 中引入了基于范围的 for 循环。 语法: for (迭代的变量 : 迭代的范围) { // 循环体。 } 注意: 1)迭…

实践reflex:项目架构解析

reflex 是一个使用纯Python构建全栈web应用的库,但是需要使用node,所以你懂的。 reflex安装:实践reflex:一个使用纯Python构建全栈web应用的库-CSDN博客 创建hello项目 (base) skyub:~$ mkdir hello (base) skyub:~$ cd hello/…

【Azure Redis】Redis-CLI连接Redis 6380端口始终遇见 I/O Error

问题描述 使用Redis-cli连接Redis服务,因为工具无法直接支持TLS 6380端口连接,所以需要使用 stunnel 配置TLS/SSL服务。根据文章(Linux VM使用6380端口(SSL方式)连接Azure Redis (redis-cli & stunnel) : https://www.cnblogs.com/luligh…

模型训练套路(二)

接模型训练套路(一)http://t.csdnimg.cn/gZ4Fm 得到预测的值:preds[1][1], 输出目标:inputs target [0][1]; 查看两者的正确率,就看:predsinputs target 输出的结果&#xff1a…

前端WebSocket客户端实现

// 创建WebSocket连接 var socket new WebSocket(ws://your-spring-boot-server-url/websocket-endpoint);// 连接打开时触发 socket.addEventListener(open, function (event) {socket.send(JSON.stringify({type: JOIN, room: general})); });// 监听从服务器来的消息 socke…

K8S日志收集

本章主要讲解在 Kubernetes 集群中如何通过不同的技术栈收集容器的日志,包括程序直接输出到控制台日志、自定义文件日志等。 一、有哪些日志需要收集 为了更加方便的处理异常,日志的收集与分析极为重要,在学习日志收集之前,需要知…

QT基础 QPropertyAnimation简单学习

目录 1.简单介绍 2.使用步骤 3.部分代码示例 4.多项说明 5.信号反馈 6.自定义属性 1. 定义自定义属性 2. 使用 QPropertyAnimation 动画化自定义属性 3. 连接信号和槽 4.注意事项 7.更多高级示例 1.简单介绍 QPropertyAnimation是Qt中的一个类,用于实现属性…

idea安装并使用maven依赖分析插件:Maven Helper

在 IntelliJ IDEA 中安装并使用 Maven Helper 插件可以帮助你更方便地管理 Maven 项目的依赖,比如查看依赖树、排除冲突依赖等。以下是安装和使用 Maven Helper 插件的步骤: 安装 Maven Helper 插件 打开 IntelliJ IDEA 并进入你的项目。 在 IDE 的右下…

百度飞浆OCR半自动标注软件OCRLabel配置【详细

今天帮标注人员写了一份完整的百度飞浆OCR标注软件的安装配置说明书、以供标注人员使用 包括各种环境安装包一起分享出来【conda\python\label项目包、清华源配置文件、pycharm社区版安装包】 提取码:umys 1、解压并安装tools文件下的miniconda,建议安装在D盘下的…

Win32绕过UAC弹窗获取管理员权限

在早些年写一些桌面软件时,需要管理员权限,但是又不想UAC弹窗,所以一般是直接将UAC的级别拉到最低,或者直接禁用UAC的相关功能。 什么是UAC(User Account Control) 用户帐户控制 (UAC) 是一项 Windows 安全功能,旨在保…

Flink SQL 中常见的数据类型

Flink SQL 中常见的数据类型 目标 通过了解Flink SQL 中常见的数据类型,掌握正确编写Flink SQL 语句背景 Apache Flink 支持多种数据类型,这些数据类型被用于 Flink SQL 表达式、Table API 以及 DataStream API 中。以下是 Flink SQL 中常见的数据类型: 基本数据类型 Boo…

<Rust>egui学习之部件(十一):如何在窗口中添加单选框radiobutton部件?

前言 本专栏是关于Rust的GUI库egui的部件讲解及应用实例分析,主要讲解egui的源代码、部件属性、如何应用。 环境配置 系统:windows 平台:visual studio code 语言:rust 库:egui、eframe 概述 本文是本专栏的第十一篇…

算法练习题17——leetcode54螺旋矩阵

题目描述 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 代码 import java.util.*;class Solution {public List<Integer> spiralOrder(int[][] matrix) {// 用于存储螺旋顺序遍历的结果List<Integer>…

学习整理使用jquery实现获取相同name被选中的多选框值的方法

学习整理使用jquery实现获取相同name被选中的多选框值的方法 <html><head><meta charset"gbk"><!-- 引入JQuery --><script src"https://www.qipa250.com/jquery/dist/jquery.min.js" type"text/javascript"><…

flutter开发实战-flutter build web微信无法识别二维码及小程序码问题

flutter开发实战-flutter build web微信无法识别二维码及小程序码问题 GitHub Pages是一个直接从GitHub存储库托管的静态站点服务&#xff0c;‌它允许用户通过简单的配置&#xff0c;‌将个人的代码项目转化为一个可以在线访问的网站。‌这里使用flutter build web来构建web发…