13SpringMVC中拦截器的配置(拦截规则)和多个拦截器的preHandle,postHandle执行顺序原理详解

拦截器

Servlet中的过滤器的实现及其原理,参考文章

配置一个拦截器

SpringMVC中请求的处理流程: 用户请求—>listener—>filter—>DispatcherServlet—>filter—>preHandle—>controller—>postHandle

第一步: 编写一个Java类实现HandlerInterceptor(HandlerInterceptorAdapter已过时)接口,由于接口中的方法都有默认的方法体,我们可以根据需求实现方法

方法名功能
boolean preHandle(processedRequest, response)在控制器方法执行之前执行 , 返回true表示放行即调用控制器方法 , 返回false表示拦截即不调用控制器方法
postHandle(processedRequest, response, mv)在控制器方法执行之后执行
afterComplation()在控制器方法执行之后,且模型数据都被渲染到视图上后执行
// 将当前bean加入IoC容器,这样就可以在配置文件中引用当前的bean作为拦截器
@Component
public class FirstInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("FirstInterceptor-->preHandle");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("FirstInterceptor-->postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("FirstInterceptor-->afterCompletion");}
}

第二步: 在SpringMVC的配置文件中将实现了HandlerInterceptor接口的类设置为拦截器并设置拦截的规则

  • 通过ref或bean标签可以设置拦截器但是不能设置拦截规则,此时默认拦截DispatcherServlet处理的所有的请求
  • 通过mvc:interceptor标签可以设置拦截器同时设置拦截的规则即拦截哪些请求或放行哪些请求
  • 使用view-controller标签配置的视图控制器对应的跳转页面的请求只要符合拦截器拦截的规则也会被拦截
标签名描述
bean标签的class属性根据全类名告诉SpringMVC哪个类是拦截器
ref标签的bean属性引用IoC容器中的某个bean的Id作为拦截器,所以需要保证容器中注册了对应的bean
mvc:mapping设置需要拦截的请求路径
/**表示拦截所有请求,/* 表示拦截上下文路径后的一层路径的请求
mvc:exclude-mapping设置排除即不需要拦截的请求路径
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"><!--扫描组件--><context:component-scan base-package="com.atguigu.mvc"></context:component-scan><!--使用view-controller标签配置的视图控制器对应的跳转页面的请求也会被拦截--><mvc:view-controller path="/" view-name="index"></mvc:view-controller><mvc:annotation-driven /><!--配置拦截器--><mvc:interceptors><!--根据全类名将某个类设置为拦截器--><bean class="com.atguigu.mvc.interceptors.FirstInterceptor"></bean><!--引用IoC容器中的某个bean的Id作为拦截器,需要保证容器中注册了对应的bean--><ref bean="firstInterceptor"></ref><!--设置拦截器及拦截的规则--><mvc:interceptor><!--配置需要拦截的请求路径--><mvc:mapping path="/**"/><!--配置不需要拦截的请求路径--><mvc:exclude-mapping path="/"/><!--引用容器中的某个bean作为拦截器--><ref bean="firstInterceptor"></ref></mvc:interceptor></mvc:interceptors>
</beans>

第三步: 编写处理请求的控制器方法,测试拦截器方法的执行顺序,只要请求符合拦截的规则,拦截器中重写的方法就一定会执行,无论有没有匹配请求的控制器方法

<a th:href="@{/testInterceptor}">测试拦截器</a>
@Controller
public class TestController {@RequestMapping("/testInterceptor")@ResponseBodypublic String testInterceptor(){return "success";}
}
FirstInterceptor-->preHandle
success
FirstInterceptor-->postHandle
FirstInterceptor-->afterCompletion

配置多个拦截器

多个拦截器的执行顺序和在SpringMVC的配置文件的中配置的拦截器顺序以及拦截器的preHandle()方法的返回值有关

在这里插入图片描述

第一步: 创建一个拦截器类并且preHandle方法的返回值是false

// 将当前bean加入IoC容器,这样就可以在配置文件中引用当前的bean作为拦截器
@Component
public class SecondInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("SecondInterceptor-->preHandle");return false;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("SecondInterceptor-->postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("SecondInterceptor-->afterCompletion");}
}

第二步: 在SpringMVC的配置文件中设置多个拦截器及其拦截规则

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"><!--扫描组件--><context:component-scan base-package="com.atguigu.mvc"></context:component-scan><!--配置视图控制器--><mvc:view-controller path="/" view-name="index"></mvc:view-controller><mvc:annotation-driven /><!--配置拦截器--><mvc:interceptors><ref bean="firstInterceptor"></ref><ref bean="secondInterceptor"></ref></mvc:interceptors>
</beans>

第三步: 编写控制器方法测试多个拦截器中方法的执行顺序

Controller
public class TestController {@RequestMapping("/testInterceptor")@ResponseBodypublic String testInterceptor(){return "success";}
}
FirstInterceptor-->preHandle
SecondInterceptor-->preHandle
success
FirstInterceptor-->afterCompletion

拦截器执行顺序的原理

mappedHandler是控制器执行链,包含控制器方法,拦截器集合(自定义的和SpringMvc提供的),拦截器的索引

正序执行所有拦截器的prehandle方法

if (!mappedHandler.applyPreHandle(processedRequest, response)) {// 如果有一个拦截器的prehandle方法返回fasle,直接终止当前方法即剩下的拦截器和对应控制器的方法都不会执行return;
}
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {// 遍历拦截器集合中的每一个拦截器for(int i = 0; i < this.interceptorList.size(); i++) {HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);// 判断当前拦截器的prehandle方法的返回值if (!interceptor.preHandle(request, response, this.handler)) {// 如果prehandle方法返回false,调用当前拦截器的afterComplation方法this.triggerAfterCompletion(request, response, (Exception)null);// 返回false后剩下的拦截器和对应控制器的方法都不会执行return false;}// interceptorIndex的值是prehandle方法返回的是false的某个拦截器之前的拦截器的索引this.interceptorIndex = i;}// 返回true后才会执行下一个拦截器或对应控制器的方法return true;
}

反序执行所有拦截器的posthandle方法

mappedHandler.applyPostHandle(processedRequest, response, mv);void applyPostHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {// i的初始值是拦截器集合中的最后一个拦截器的索引for(int i = this.interceptorList.size(); i >= 0; i--) {HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);interceptor.postHandle(request, response, this.handler,mv);    }
}

反序执行所有拦截器的aftercompletion方法

if(mappedHandler != null){mappedHandler.triggerAfterCompletion(request, response, (Exception)null);      
}void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response) throws Exception {// i的初始值是最后一个prehandle方法返回的是false的某个拦截器之前的拦截器的索引for(int i = this.interceptorIndex; i >= 0; i--) {HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);interceptor.afterCompletion(request, response, this.handler,ex);    }
}

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

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

相关文章

(十五)VBA常用基础知识:正则表达式的使用

vba正则表达式的说明 项目说明Pattern在这里写正则表达式&#xff0c;例&#xff1a;[\d]{2,4}IgnoreCase大小写区分&#xff0c;默认false&#xff1a;区分&#xff1b;true&#xff1a;不区分Globaltrue&#xff1a;全体检索&#xff1b;false&#xff1a;最小匹配Test类似p…

[GXYCTF2019]Ping Ping Ping - RCE(空格、关键字绕过[3种方式])

[GXYCTF2019]Ping Ping Ping 1 解题流程1.1 小试牛刀1.2 三种解法1.2.1 解法一:变量定义拼接绕过1.2.2 解法二:base64编码绕过1.2.3 解法三:内联执行绕过2 思考总结1 解题流程 1.1 小试牛刀 1、提示?ip,结合题目名称,我们直接输入?ip=127.0.0.1 PING 127.0.0.1 (127.…

go 项目打包部署到服务器

1、window打包到Linux 步骤1 依次执行一下命令&#xff0c;就会得到一个exe 文件 步骤2 把打包的文件&#xff0c;放到服务器上&#xff08;可以使用FinalShell工具&#xff09; chmod x main # 执行这个命令&#xff0c;给main 文件添加 执行权限&#xff0c;然后执行 ls &…

【BI工具】-- Superset 、Metabase 和 Redash 对比

目录 1.1 基本信息 1.2 制作面板步骤 1.3 支持的数据源 1.4 图表类型 1.4.1 Apache superset 1.4.2 Meta

PCB射频天线设计基本要点及布局技巧

射频天线设计与布局是需要认真关注细节的领域之一&#xff0c;也是混合信号设计师给出的一些提示。如果刚开始接触高频模拟设计&#xff0c;可采用本文给出的这些技巧&#xff0c;以确保RF设计具有良好的隔离效果和信号完整性。 如今&#xff0c;人们已很难想到哪个消费产品不含…

Go 结构体深度探索:从基础到应用

1. 结构体概述 在计算机编程中&#xff0c;数据结构是组织、管理和存储数据的一种方式&#xff0c;它允许高效地执行各种操作。Go语言中的结构体&#xff08;Struct&#xff09;是这些数据结构中的一员&#xff0c;它为数据的组织提供了一种具体的方式。 结构体可以被视为是多…

大数据学习(4)-hive表操作

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博>主哦&#x…

Vite + TypeScript + Node 开发一个简易脚手架

前言 使用 Vite TypeScript Node 开发一个使多个命令为一个命令的脚手架当然这个题材你也可以使用 bat 实现 思路 创建一个 node 项目&#xff0c;开发一系列逻辑&#xff0c;发布到线上&#xff0c;需要的时候全局安装使用 初始化项目 选择 自定义预选 > cli npm c…

数据结构--》连接世界的无限可能—— 图

图作为数据结构中的一种重要概念&#xff0c;扮演着连接世界的纽带。与树和二叉树相比&#xff0c;图更加灵活和多样化&#xff0c;它能够描述各种实际问题中的复杂关系&#xff0c;如社交网络中的人际联系、城市交通中的路线规划以及电子网络中的通信路径等。 无论你是初学者还…

python:从Excel或者CSV中读取因变量与多个自变量,用于训练机器学习回归模型,并输出预测结果

作者:CSDN @ _养乐多_ 本文详细记录了从Excel读取用于训练机器学习模型的数据,包括独立变量和因变量数据,以供用于机器学习模型的训练。这些机器学习模型包括但不限于随机森林回归模型(RF)和支持向量机回归模型(SVM)。随后,我们将测试数据集应用于这些模型,进行预测和…

[开源]基于流程编排的自动化测试工具,插件驱动,测试无限可能

一、开源项目简介 流程编排&#xff0c;插件驱动&#xff0c;测试无限可能 一款基于流程编排的自动化测试工具 二、开源协议 使用Apache-2.0开源协议 三、界面展示 四、功能概述 在软件开发旅程中&#xff0c;测试流程的管理和执行常常是复杂且耗时的挑战。传统测试工具主…

spring6项目搭建(入门)

文章目录 环境要求构建模块引入依赖初试Bean创建测试类测试对象实现的原理 环境要求 JDK&#xff1a;Java17&#xff08;Spring6要求JDK最低版本是Java17&#xff09; Maven&#xff1a;3.6 Spring&#xff1a;6.0.2 构建模块 首先建立的spring的项目&#xff08;project&…

如何使用Jmeter进行http接口测试?

前言&#xff1a; 本文主要针对http接口进行测试&#xff0c;使用Jmeter工具实现。 Jmter工具设计之初是用于做性能测试的&#xff0c;它在实现对各种接口的调用方面已经做的比较成熟&#xff0c;因此&#xff0c;本次直接使用Jmeter工具来完成对Http接口的测试。 一、开发接…

STM32使用HAL库驱动TA6932数码管驱动芯片

TA6932介绍 8段16位&#xff0c;支持共阴共阳LED数码管。 2、STM32CUBEMX配置引脚 推挽配置即可。 3、头文件 /******************************************************************************************** * TA6932&#xff1a;8段16位数码管驱动 *******************…

ffmpeg视频解码器的配置选项含义

lowres的含义 lowres是AVCodecContext结构体中的一个成员变量&#xff0c;用于指定编解码器的降低分辨率级别。 在某些情况下&#xff0c;为了加快编解码的速度或减少计算资源的消耗&#xff0c;可以通过设置lowres参数来降低编解码器的分辨率级别。这将导致编解码器在处理视…

vue3封装分页组件

1.新建Pagination文件以及该文件夹下新建index.vue 2.在index.vue文件中编写一下代码 <template><div :class"{ hidden: hidden }" class"pagination-container"><el-pagination:background"background"v-model:current-page&qu…

GPU 基础知识整理

萌新&#xff1a; 在接触一款硬件时我会&#xff1a;基础硬件结构&#xff0c;线程结构&#xff0c;内存布局&#xff0c;数据吞吐量&#xff0c;等方面进行学习 首先GPU的特点: 并行性能&#xff1a;GPU 是专门设计用于并行计算的硬件&#xff0c;通常具有大量的处理单元&am…

辉视客房控制系统:宾至如归,智能科技的贴心体现

辉视酒店客房控制系统&#xff0c;这不仅仅是一个系统&#xff0c;它更像是一个聪明的酒店管家&#xff0c;运用计算机技术、通讯技术和管理技术等手段&#xff0c;为宾客营造一个舒适、便捷且富有科技感的住宿体验。 辉视酒店客房控制系统&#xff0c;以客房内的RCU为核心&…

文字与视频结合效果

效果展示 CSS 知识点 mix-blend-mode 属性的运用 实现整体页面布局 <section class"sec"><video autoplay muted loop><source src"./video.mp4" type"video/mp4" /></video><h2>Run</h2><!-- 用于切…

流式数据湖平台Hudi核心概念一:时间线

1. 什么是Hudi Hudi(Hadoop Upserts Deletes and Incrementals)是一个开源的数据湖工具,用于管理大规模数据湖中的数据。 Hudi旨在解决数据湖中常见的一些挑战,如数据的增量更新、删除和查询等。它提供了一套API和工具,可以帮助用户在数据湖中进行写入、更新、删除和查询等…