Java 拦截器Interceptor详解

1、拦截器概念
先看一下web请求的流程。
(1)、当浏览器发送一个请求时,请求到达tomcat容器,tomcat容器会区分静态还是动态资源。
(2)、动态请求会先经过过滤器链filter,直到全部过滤完成之后,会达到spring容器。
(3)、请求达到spring容器后,会经过中央处理器DispatcherServlet进行调度,请求转给指定的控制器Handler进行处理。
(4)、如果给控制器Handler注册了拦截器Interceptor,会先经过拦截器进行处理。
(5)、拦截器放行后,执行控制器的业务,在按照进入相反的路径最终返回给浏览器。
在这里插入图片描述
springMvc的具体流程图
在这里插入图片描述
拦截器的概念:
拦截器Interceptor是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行。

2、拦截器实现原理
拦截器实现主要基于两个原理:AOP(动态代理)和责任链模式
AOP:是面向切面的编程的方式,可以在不改变源代码的基础上,进行业务扩展。
责任链模式:类似过滤器链,可以有多个拦截处理,一个处理后放行,下一个拦截才能处理。

具体执行:
(1)、请求执行Handler之前,生成Action对象,在Action方法执行之前,校验是否有当前Action的拦截器,有的话先走拦截器处理。
Action可以理解为行为,就是Controller中的一个对外接口。Handler则为一个任务调度。
(2)、基于AOP,先生成目标Action对象的proxy代理对象,在执行代理方法前,先执行拦截器链的前置方法preHandle。之后会执行代理方法,以及拦截器的postHandle后置方法。当视图渲染完成后,会执行afterCompletion方法。
在这里插入图片描述
3、代码示例
(1)、编写拦截器类(需要实现HandlerInterceptor接口)

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;public class StudentInterceptor implements HandlerInterceptor{// 在业务处理器处理请求之前被调用(Controller之前)@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("执行了: StudentInterceptor的preHandle");return true;}// 在业务处理器处理请求完成之后,生成视图之前执行(controller执行完成,前端视图生成之前)@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("执行了: StudentInterceptor的postHandle");}// 在DispatcherServlet完全处理完请求之后被调用,可用于清理资源@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("执行了: StudentInterceptor的afterCompletion");}
}

(2)、注册拦截器(实现WebMvcConfigurer接口)

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfigure implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {//静态资源请求的映射,如静态请求为/pages/**,则请求会在程序的类路径(通常是src/main/resources目录)下的/pages/目录中查找这些资源registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");}@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册拦截器,指定拦截和放行路径(先注册的拦截器会先执行)registry.addInterceptor(new StudentInterceptor()).addPathPatterns("/student","/student/*") .excludePathPatterns("/login", "/register");registry.addInterceptor(new TeacherInterceptor()).addPathPatterns("/student/**");}
}

(3)、在controller中正常写接口,可以测试拦截效果。

4、使用类解读
(1)、拦截器生明的方法
实现HandlerInterceptor或继承HandlerInterceptorAdapter,标识当前类试一个拦截器。
如果使用HandlerInterceptor,就需要覆写拦截器默认的三个方法。如果是继承HandlerInterceptorAdapter,则可以按照自己的需要去进行方法覆写,不用把三个方法都定义出来。HandlerInterceptorAdapter实现了HandlerInterceptor接口,提供了空实现的方法,所以你可以选择只覆盖自己关心的方法。
(2)、拦截器preHandle的参数
Object handler 被调用的Action对象,本质上是一个方法对象,对反射中的Method对象进行了再包装,可以基于反射获取相关信息
如:
HandlerMethod hm = (HandlerMethod)handler;
Method method = hm.getMethod();
String methodName = method .getName();//可以获取方法的名称
(3)、拦截器注册到WebMvc
WebMvcConfigurer(接口):用于自定义的Spring MVC配置,如拦截器、视图解析器、消息转换器等,而无需完全重写默认的Spring MVC配置。(推荐)
WebMvcConfigurerAdapter(抽象类):实现了WebMvcConfigurer接口,提供了默认的空配置,不过在java8中已经废弃,(不推荐使用)。
WebMvcConfigurationSupport(抽象类):提供了Spring MVC的默认配置,确实需要完全控制Spring MVC的配置时可以用。这样做可能会导致Spring Boot的自动配置失效,包括那些你可能依赖的自动配置。(特别不推荐)
(4)、ResourceHandlerRegistry
是Spring MVC中用于处理静态资源请求的重要组件,它使得开发者能够灵活地配置和管理静态资源的访问。
(5)、InterceptorRegistry
提供了一种方便的方式来注册和管理拦截器,以实现各种请求处理前后的逻辑操作。

5、与filter区别
(1)、归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术。
(2)、拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强。
(3)、拦截器可以对Action对象获取(获取到方法对象),进行反射等业务处理,过滤器则不行。

使用场景:
(1)、拦截器主要用于AOP(面向切面编程),即在方法执行前后进行相应的处理。典型的应用场景包括:
身份验证:检查用户是否登录或者是否有权限访问某个资源。
日志记录:记录请求参数、响应结果、请求时间等信息,方便后续的调试和分析。
事务处理:在业务方法执行前后,启动或提交事务,保证数据的完整性和一致性。
缓存控制:对请求进行缓存,提高系统性能和响应速度等。

(2)、过滤器主要用于对用户请求进行过滤和修改,并将其发送到目标资源或者返回相应的错误响应。典型的应用场景包括:
字符编码:将请求和响应的字符集转换成指定的编码方式,避免乱码问题。
安全控制:检查请求参数是否合法,避免SQL注入等安全问题。
错误处理:捕获异常并返回相应的错误信息,保证系统的稳定性和可靠性。
日志记录:记录请求路径、请求参数、响应结果等信息,方便后续的分析和排查问题。

6、优化策略
(1)、减少拦截器数量:尽量将相关功能集中到一个拦截器中,避免创建过多的拦截器。
(2)、精确配置拦截规则:通过addPathPatterns和excludePathPatterns方法精确配置拦截规则,避免不必要的拦截。
(3)、使用异步处理:在拦截器中使用异步处理,避免阻塞请求处理过程。
(4)、使用缓存:在拦截器中使用缓存,减少对数据库或其他资源的访问。

7、常见问题分析
(1)、拦截器不生效:拦截器不生效的可能原因有很多,其中最常见的包括拦截器未注册到InterceptorRegistry、拦截规则配置错误等。为了解决这个问题,我们需要首先检查拦截器是否已经正确注册到InterceptorRegistry中,然后再检查拦截规则是否配置正确。如果发现问题,需要及时进行调整和修复。
(2)、拦截器执行顺序错误:拦截器执行顺序错误的主要原因是拦截器的注册顺序错误。在实际应用中,拦截器的执行顺序是根据它们在InterceptorRegistry中的注册顺序来决定的。因此,为了解决这个问题,我们需要调整拦截器在InterceptorRegistry中的注册顺序,确保它们按照预期的顺序执行。(靠上注册的会被先执行)
(3)、拦截器影响性能:拦截器影响性能的主要原因是拦截器中的处理逻辑过于复杂或资源消耗过大。为了解决这个问题,我们需要对拦截器的处理逻辑进行优化,尽量减少不必要的计算和资源消耗。同时,我们还可以考虑使用一些性能监控工具,如JProfiler等,来对拦截器的性能进行实时监控和分析,从而找到性能瓶颈并进行优化。

学海无涯苦作舟!!!

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

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

相关文章

MySQL 事务的原理以及长事务的预防和处置

transaction_isolation 隔离级别 读未提交 读提交 视图是在每个 SQL 语句开始执行的时候创建的 可重复读 视图是在事务启动时创建的,整个事务存在期间都用这个视图 串行化…

Claude3系统解读与使用测评

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

Character类中的方法总结

Character.isDigit(char ch): 检查指定的字符是否是一个数字。 Character.isWhitespace(char ch): 检查指定的字符是否是一个空白字符。空白字符包括空格、制表符、换页符等。 Character.isUpperCase(char ch): 检查指定的字符是否是大写字母。 Character.isLowerCase(char ch)…

3/12/24交换排序、插入排序、选择排序、归并排序

目录 交换排序 冒泡排序 快速排序 插入排序 直接插入排序 选择排序 简单选择排序 堆排序 归并排序 各种排序的时间复杂度、空间复杂度、稳定性和复杂度 快排真题2016 选排真题2022 排序算法分为交换类排序、插入类排序、选择类排序、归并类排序。 交换排序 交换排…

2024基于协同过滤算法springboot微信订餐小程序项目

项目介绍 基于springboot开发的订餐小程序,用户在微信小程序里面进行注册登录,点餐,收藏,评论等,管理员在后台网页端进行对菜品,分类,订单,用户,角色,评论等进行管理,小程序界面通过协同过滤算法给用户推荐菜品 技术栈 后端:springboot+JPA+Mysql8+redis+maven+…

Django 学习笔记(Day1)

「写在前面」 本文为千锋教育 Django 教程的学习笔记。本着自己学习、分享他人的态度,分享学习笔记,希望能对大家有所帮助。 目录 0 课程介绍 1 Django 快速入门 1.1 Django 介绍 1.2 Django 安装 1.3 创建 Django 项目 1.4 运行 Django 项目 1.5 数据迁…

Linux-gdb调试

文章目录 前言查看(显示)源代码 list/l运行程序run/r打断点b查看断点删除断点打开/关闭断点逐过程 逐语句查看变量常显示continuefinishuntil修改指定变量退出gdb 前言 GDB,即GNU调试器(GNU Debugger),是G…

命令行跑stanford-corenlp

在 https://nlp.stanford.edu/software/stanford-corenlp-4.5.6.zip 下载stanford-corenlp-4.5.6.zip 在 https://stanfordnlp.github.io/CoreNLP/human-languages.html 下载model的jar 然后stanford-corenlp-4.5.6.zip解压,把比如stanford-corenlp-4.5.6-models-…

细粒度IP定位参文27(HGNN):Identifying user geolocation(2022年)

[27] F. Zhou, T. Wang, T. Zhong, and G. Trajcevski, “Identifying user geolocation with hierarchical graph neural networks and explainable fusion,” Inf. Fusion, vol. 81, pp. 1–13, 2022. (用层次图、神经网络和可解释的融合来识别用户的地理定位) 论文地址:…

Matlab工具箱实现相机标定

Matlab工具箱实现张正友相机标定_分别使用蔡氏与张正友标定法完成标定,并与matlab工具箱及(外参)实测结果对照。结-CSDN博客 使用Matlab做相机标定(获取相机的内外参数矩阵)_matlab相机标定结束后如何显示图片的平移矩阵-CSDN博客 【一文弄懂】张正友标…

QML 控件添加键盘事件

在QML中,可以使用Keys类型来处理键盘事件。以下是一个简单的示例,演示如何在QML控件中添加键盘事件: import QtQuick 2.12 import QtQuick.Window 2.12Window {visible: truewidth: 640height: 480title: qsTr("Hello World")Recta…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的常见车型识别系统(Python+PySide6界面+训练代码)

摘要:本文深入探讨了如何应用深度学习技术开发一个先进的常见车型识别系统。该系统核心采用最新的YOLOv8算法,并与早期的YOLOv7、YOLOv6、YOLOv5等版本进行性能比较,主要评估指标包括mAP和F1 Score等。详细解析了YOLOv8的工作机制&#xff0c…

5.Java并发编程—JUC线程池架构

JUC线程池架构 在Java开发中,线程的创建和销毁对系统性能有一定的开销,需要JVM和操作系统的配合完成大量的工作。 JVM对线程的创建和销毁: 线程的创建需要JVM分配内存、初始化线程栈和线程上下文等资源,这些操作会带来一定的时间和…

【ARM架构】讲解

ARM ARM架构,全称为Advanced RISC Machine(先进的精简指令集机器),原先称为Acorn RISC Machine,是一种基于精简指令集计算(RISC)的计算机处理器架构,它被广泛应用在移动设备如智能手…

Linux系统运维脚本:如何查看访问我的linux系统的IP地址,并判断是否有网络攻击?

目 录 一、需求 二、解决思路 三、实现方式 1、抓一定数量的数据包 2、抓取1小时的数据包 3、以小时为周期,周期性的执行抓包1小时 4,抓包分析并输出结果 5,周期性分析并输出结果 (1)定时…

【基于langchain + streamlit 完整的与文档对话RAG】

本地部署文档问答webdemo 支持 pdf支持 txt支持 doc/docx支持 源文档索引 你的点赞和收藏是我持续分享优质内容的动力哦~ 废话不多说直接看效果 准备 首先创建一个新环境(选择性) conda create -n chatwithdocs python3.11 conda activate chatwith…

封装的echarts子组件使用watch监听option失效的问题

项目场景: 我在项目里面封装了一个echarts组件,组件接收一个来自外部的option,然后我用了一个watch函数去监听这个option的变化,option变化之后,销毁,然后再新建一个charts表 碎碎念 问题如标题所示,这篇…

vue的生命周期有那些

1.v-text 相当于js的innerText <div v-text"姓名&#xff1a;name"></div>const name ref(张三); //声明 2.v-html 相当于js的innerHTML <div v-html"html"></div>const html ref(<s>这是一段文字</s>) 3.v-bin…

pytorch 函数整理

pytorch 函数整理 method_code.init.code.co_argcount&#xff1a;获取method_code.init 函数的输入变量的数目&#xff1b; input_params method_code.init.code.co_varnames&#xff1a;获取method_code.init 函数的输入变量的名称列表&#xff1b; __enter__和__exit__魔…

【Preprocessing数据预处理】之Information Leakage

在机器学习中&#xff0c;当使用来自训练数据集之外的信息来创建模型时&#xff0c;就会发生信息泄露。这可能导致在训练期间过于乐观的性能估计&#xff0c;并且可能导致模型在未见数据上表现不佳&#xff0c;因为它可能无法从训练数据泛化到现实世界。 信息泄露的示例 1. 使…