Spring MVC的高级功能——拦截器(三)拦截器的执行流程

一、单个拦截器的执行流程

        如果在项目中只定义了一个拦截器,单个拦截器的执行流程如图所示。

二、单个拦截器的执行流程分析

        从单个拦截器的执行流程图中可以看出,程序收到请求后,首先会执行拦截器中的preHandle()方法,如果preHandle()方法返回的值为false,则将中断后续所有代码的执行。

        如果preHandle()方法的返回值为true,则程序会继续向下执行Handler的代码。当Handler执行过程中没有出现异常时,接着会执行拦截器中的postHandle()方法。postHandle()方法执行后会通过DispatcherServlet向客户端返回响应,并且在DispatcherServlet处理完请求后,执行拦截器中的afterCompletion()方法;如果Handler执行过程中出现异常,将跳过拦截器中的postHandle()方法,直接由DispatcherServlet渲染异常页面返回响应,最后执行拦截器中的afterCompletion()方法。

下面通过一个案例演示单个拦截器的执行流程,案例具体实现步骤如下所示。

        1、创建名称为HelloController的控制器类,在HelloControlle类中定义2个方法,其中hello()方法用于正常处理客户端的请求,exp()方法被调用时产生异常。

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
public class HelloController {@RequestMapping("hello")public String hello() {System.out.println("HelloController...Hello");return "success.jsp";}@RequestMapping("exp")public String exp() {System.out.println(1 / 0);return "success.jsp";}
}

        2、创建实现HandlerInterceptor接口的拦截器MyInterceptor。在MyInterceptor类中重写的3个方法内编写输出语句来验证方法的执行情况。MyInterceptor类部分代码如下所示。

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** 实现了HandlerInterceptor接口的自定义拦截器*/
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) {System.out.println("MyInterceptor...preHandle");//对拦截的请求进行放行处理return true;}@Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler,ModelAndView modelAndView) {System.out.println("MyInterceptor...postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response, Object handler,Exception ex) {System.out.println("MyInterceptor...afterCompletion");}
}

        3、Spring MVC的配置文件spring-mvc.xml中添加MyInterceptor拦截器的配置,具体配置如下所示。

<!-- 配置拦截器 -->
<mvc:interceptors>      
<!--使用bean直接定义在<mvc:interceptors>下面的拦截器将拦截所有请求--><bean class="com.itheima.interceptor.MyInterceptor"/>
</mvc:interceptors>

        在spring-mvc.xml中使用<mvc:interceptors>元素的子元素<bean>来配置拦截器,配置的拦截器会拦截所有映射到Handler的请求。

        4、创建一个名称为success.jsp的文件,success.jsp具体代码如下所示。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>执行成功页面</title></head>
<body>
Handler执行成功
</body>
</html>

        5、启动chapter13项目,在浏览器中访问地址http://localhost:8080/chapter13/hello,程序将执行hello()方法,方法执行后控制台打印信息如图所示。

MyInterceptor...preHandle
HelloController...Hello
MyInterceptor...postHandle
MyInterceptor...afterCompletion

        控制台打印上图的信息之后,页面跳转到success.jsp页面。从步骤五的运行结果可以看出,程序先执行了拦截器中的preHandle()方法,然后成功执行了控制器中的hello()方法,接着执行了拦截器中的postHandle()方法,然后页面跳转到success.jsp,最后执行了拦截器的afterCompletion()方法。 

        6、 启动chapter13项目,在浏览器中访问地址为http://localhost:8080/chapter13/exp,后控制台打印信息如图所示。

MyInterceptor...preHandle
MyInterceptor...afterCompletion

        控制台打印上图的信息之后,页面跳转到error.jsp页面。从步骤六的运行接口可以看出,程序先执行了拦截器中的preHandle()方法,然后执行了拦截器的afterCompletion()方法。这是因为访问的地址映射到exp()方法,执行exp()方法时出现异常,由于程序中设置了异常处理器,DispatchServlet会渲染对应的异常处理页面进行页面转跳,程序跳过了拦截器postHandler()方法的执行。

三、多个拦截器的执行流程

        在大型的企业级项目中,可能会定义很多拦截器来实现不同的功能。假设项目中配置了顺序为Interceptor1、Interceptor2的两个拦截器,多个拦截器的执行流程如图所示。

四、多个拦截器的执行流程分析

        从多个拦截器的执行流程图中可以看出,当有程序中配置了多个拦截器时,拦截器中的preHandle()方法会按照配置文件中拦截器的配置顺序执行,而拦截器中的postHandle()方法和afterCompletion()方法则会按照拦截器的配置顺序的相反顺序执行。

        下面在单个拦截器案例的基础上新增一个拦截器,来演示多个拦截器的执行,具体步骤如下。

        1、新增拦截器MyInterceptor2,在MyInterceptor2中重写HandlerInterceptor接口的3个方法。

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** 实现了HandlerInterceptor接口的自定义拦截器*/
public class MyInterceptor2 implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) {System.out.println("MyInterceptor2...preHandle");//对拦截的请求进行放行处理return true;}@Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler,ModelAndView modelAndView) {System.out.println("MyInterceptor2...postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response, Object handler,Exception ex) {System.out.println("MyInterceptor2...afterCompletion");}
}

        2、在Spring MVC配置文件springmvc-config.xml中的<mvc:interceptors>元素内,新增拦截器MyInterceptor2,<mvc:interceptors>元素内的配置代码具体如下所示。

   <!-- 配置拦截器 --><mvc:interceptors><!-- 拦截器1 --><bean class="com.test.interceptor.MyInterceptor"/><!-- 拦截器2 --><bean class="com.test.interceptor.MyInterceptor2"/></mvc:interceptors>

        3、启动chapter13项目,在浏览器中访问地址http://localhost:8080/chapter13/hello,此时,程序将执行文件HelloController.java中的hello()方法,方法执行后控制台打印信息如图所示。

MyInterceptor...preHandle
MyInterceptor2...preHandle
HelloController...Hello
MyInterceptor2...postHandle
MyInterceptor...postHandle
MyInterceptor2...afterCompletion
MyInterceptor...afterCompletion

        控制台输出上图所示的信息后,页面跳转到success.jsp页面。从步骤三的运行结果可以看出,程序先按两个拦截器的配置顺序,依次执行了两个拦截器中的preHandle()方法;然后成功执行了控制器中的hello()方法;接着按两个拦截器配置顺序的相反顺序,依次执行了两个拦截器中的postHandle()方法;然后页面跳转到success.jsp;最后按两个拦截器配置的相反顺序,依次执行了两个拦截器的afterCompletion()方法。

        4、启动chapter13项目,在浏览器中访问地址http://localhost:8080/chapter13/exp,此时控制台打印信息如图所示。

MyInterceptor...preHandle
MyInterceptor2...preHandle
MyInterceptor2...afterCompletion
MyInterceptor...afterCompletion

        控制台输出上图所示的信息后,页面跳转到error.jsp页面。从步骤四的运行结果可以看出,程序先按两个拦截器的配置顺序,依次执行了两个拦截器中的preHandle()方法;然后按两个拦截器配置的相反顺序,依次执行了两个拦截器的afterCompletion()方法。这是因为执行控制器中的exp()方法时出现异常,由于程序中设置了异常处理器,DispatchServlet会渲染对应的异常处理页面进行页面转跳,跳过了拦截器的postHandler()方法的执行。

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

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

相关文章

bug诞生记——动态库加载错乱导致程序执行异常

大纲 背景问题发生问题猜测和分析过程是不是编译了本工程中的其他代码是不是有缓存是不是编译了非本工程的文件是不是调用了其他可执行文件查看CMakefiles分析源码检查正在运行程序的动态库 解决方案 这个案例发生在我研究ROS 2的测试Demo时发生的。 整体现象是&#xff1a;修改…

聊一聊前端动画的种类,以及动画的触发方式有哪些?

引言 动画在前端开发中扮演着重要的角色。它不仅可以提升用户体验&#xff0c;还可以使界面更加生动和有趣。在这篇文章中&#xff0c;我们将深入探讨前端动画的各种实现方式&#xff0c;包括 CSS 动画、JavaScript 动画、SVG 动画等。我们还将讨论一些触发动画的方式和动画在…

【MQTT(2)】开发一个客户端,ubuntu版本

基本流程如下&#xff0c;先生成Mosquitto的库&#xff0c;然后qt调用库进行开发界面。 文章目录 0 生成库1 有界面的QT版本2 无界面版本 0 生成库 下载源码&#xff1a;https://github.com/eclipse/mosquitto.git 编译ubuntu 版本很简单&#xff0c;安装官方说明直接make&am…

rk3568 OpenHarmony4.1 Launcher定制开发—桌面壁纸替换

Launcher 作为系统人机交互的首要入口&#xff0c;提供应用图标的显示、点击启动、卸载应用&#xff0c;并提供桌面布局设置以及最近任务管理等功能。本文将介绍如何使用Deveco Studio进行单独launcher定制开发、然后编译并下载到开发板&#xff0c;以通过Launcher修改桌面背景…

记录|如何打包C#项目

参考文章&#xff1a; c#窗体应用程序怎么打包 经过检验确实有效 Step1. 生成发布文件 在Visual Studio的菜单中&#xff0c;找到“生成”->“发布” 第一次会有个向导&#xff0c;基本上一路next下来既可以 最后&#xff0c;点击完成即可以 Step2. 获得publish文件 自…

【JavaEE】AQS原理

本文将介绍AQS的简单原理。 首先有个整体认识&#xff0c;全称是 AbstractQueuedSynchronizer&#xff0c;是阻塞式锁和相关的同步器工具的框架。常用的ReentrantLock、Semaphore、CountDownLatch等都有实现它。 本文参考&#xff1a; 深入理解AbstractQueuedSynchronizer只需…

[C++]TinyWebServer

TinyWebServer 文章目录 TinyWebServer1 主体框架2 Buffer2.1 向Buffer写入数据2.2 从Buffer读取数据2.3 动态扩容2.4 从socket中读取数据2.5 具体实现 3 日志系统3.1 生产者-消费者模型3.2 数据一致3.3 代码 4 定时器4.1 调整堆中元素操作4.2 堆的操作4.2.1 增4.2.2 删4.2.3 改…

微信小程序-应用,页面和组件生命周期总结

情景1&#xff1a;小程序冷启动时候的顺序 情景2: 使用navigator&#xff08;保留并打开另一个页面&#xff09;和redirect&#xff08;关闭并打开另一个页面&#xff09;的执行顺序 情景3&#xff1a;切后台和切前台

Linux——组管理和权限管理

目录 组管理 Linux 组基本介绍 文件/目录所有者 组的创建 查看&修改文件/目录所在组 改变用户所在组 权限管理 基本介绍 rwx 文件/目录权限详解 chmod 修改文件或目录权限 chown 修改文件所有者 组管理 Linux 组基本介绍 关于第二张图中问题&#xff0c;答案…

【Qt】Qt的坐标转换(mapToGlobal)

1、QPoint QWidget::mapToGlobal(const QPoint &pos) const 将小部件坐标转换为全局坐标。mapToGlobal(QPoint(0,0))可以得到小部件左上角像素的全局坐标。2、QPoint QWidget::mapToParent(const QPoint &pos) const 将小部件坐标转换为父部件坐标。如果小部件没有父部…

Jmeter之count函数

counter函数 1、功能解释 count函数--计数器&#xff0c;每调用这个函数一次&#xff0c;它就会自动加1。它有两个参数&#xff0c;第一个参数是布尔型的&#xff0c;只能设置成 “TRUE”或者“FALSE”&#xff0c;如果是TRUE&#xff0c;那么每个用户有自己的计数器&#xf…

常用的网络爬虫工具推荐

在推荐常用的网络爬虫工具时&#xff0c;我们可以根据工具的易用性、功能强大性、用户口碑以及是否支持多种操作系统等多个维度进行考量。以下是一些常用的网络爬虫工具推荐&#xff1a; 1. 八爪鱼 简介&#xff1a;八爪鱼是一款免费且功能强大的网站爬虫&#xff0c;能够满足…

vxe-table——实现切换页码时排序状态的回显问题(ant-design+elementUi中table排序不同时回显的bug)——js技能提升

之前写的后台管理系统&#xff0c;都是用的antdelement&#xff0c;table组件中的【排序】问题是有一定的缺陷的。 想要实现的效果&#xff1a; antv——table组件一次只支持一个参数的排序 如下图&#xff1a; 就算是可以自行将排序字段拼接到列表接口的入参中&#xff0c…

环信+亚马逊云科技服务:助力出海AI社交应用扬帆起航

随着大模型技术的飞速发展&#xff0c;AI智能体的社交体验得到了显著提升&#xff0c;AI社交类应用在全球范围内持续火热。尤其是年轻一代对新技术和新体验的热情&#xff0c;使得AI社交产品在海外市场迅速崛起。作为领先的即时通讯解决方案提供商&#xff0c;环信与亚马逊云科…

计算机体系结构|| 再定序缓冲(ROB)原理(6)

实验6 再定序缓冲&#xff08;ROB&#xff09;原理 6.1实验目的 &#xff08;1&#xff09;加深对指令级并行性及其开发的理解。 &#xff08;2&#xff09;加深对基于硬件的前瞻执行的理解。 &#xff08;3&#xff09;掌握 ROB 在流出、执行、写结果确认4 个阶段所进行的…

vue3 -layui项目-左侧导航菜单栏

1.创建目录结构 进入cmd,先cd到项目目录&#xff08;项目vue3-project&#xff09; cd vue3-project mkdir -p src\\views\\home\\components\\menubar 2.创建组件文件 3.编辑menu-item-content.vue <template><template v-if"item.icon"><lay-ic…

SQL injection UNION attacks SQL注入联合查询攻击

通过使用UNION关键字&#xff0c;拼接新的SQL语句从而获得额外的内容&#xff0c;例如 select a,b FROM table1 UNION select c,d FROM table2&#xff0c;可以一次性查询 2行数据&#xff0c;一行是a&#xff0c;b&#xff0c;一行是c&#xff0c;d。 UNION查询必须满足2个条…

java面试题,有synchronized锁,threadlocal、数据可以设置默认值、把redis中的json转为对象

有面试题&#xff0c;有synchronized锁&#xff0c;threadlocal 一、面试题小记二、加锁synchronized1. 先看代码2. synchronized 讲解2.1. 同步代码块2.2. 同步方法2.3. 锁的选择和影响2.4. 注意事项2.5 锁的操作&#xff0c;手动释放锁&#xff0c;显式地获取锁&#xff08;属…

开源XDR-SIEM一体化平台 Wazuh (1)基础架构

简介 Wazuh平台提供了XDR和SIEM功能&#xff0c;保护云、容器和服务器工作负载。这些功能包括日志数据分析、入侵和恶意软件检测、文件完整性监控、配置评估、漏洞检测以及对法规遵从性的支持。详细信息可以参考Wazuh - Open Source XDR. Open Source SIEM.官方网站 Wazuh解决…

AV1技术学习:Transform Coding

对预测残差进行变换编码&#xff0c;去除潜在的空间相关性。VP9 采用统一的变换块大小设计&#xff0c;编码块中的所有的块共享相同的变换大小。VP9 支持 4 4、8 8、16 16、32 32 四种正方形变换大小。根据预测模式选择由一维离散余弦变换 (DCT) 和非对称离散正弦变换 (ADS…