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.rhkb.cn/news/155831.html

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

相关文章

TCP/IP(五)TCP的连接管理(二)三次握手细节

一 ISN序列号探究 本文主要探究三次握手建立TCP连接的细节备注&#xff1a; 某些问题探究的比较深入,当前用不到,暂时通过链接引入进来吃水不忘挖井人&#xff1a; 小林 coding ① 初始序列号 ISN 是如何随机产生的 ISN: 初始化序列号 Initial Sequence Number 接收方和…

SQLAlchemy 使用封装实例

类封装 database.py #! /usr/bin/env python # -*- coding: utf-8 -*-import sys import json import logging from datetime import datetimefrom core.utils import classlock, parse_bool from core.config import (MYSQL_HOST,MYSQL_PORT,MYSQL_USER,MYSQL_PASS,MYSQL_DA…

CustomShapes/自定义形状, CustomCurves/自定义曲线, AnimateableData/数据变化动画 的使用

1. CustomShapes 自定义形状视图 1.1 资源图文件 therock.png 1.2 创建自定义形状视图 CustomShapesBootcamp.swift import SwiftUI/// 三角形 struct Triangle: Shape{func path(in rect: CGRect) -> Path {Path { path inpath.move(to: CGPoint(x: rect.midX, y: rect.mi…

Win10玩游戏老是弹回桌面的解决方法

在Win10电脑中&#xff0c;用户不仅可以办公&#xff0c;也可以畅玩各种各样的游戏。但是&#xff0c;有时候用户在玩游戏的时候&#xff0c;遇到了游戏老是自己弹回桌面的问题&#xff0c;这样是非常影响游戏体验的&#xff0c;却不清楚具体的解决方法。下面小编给大家带来了简…

二叉搜索树-- 删除节点-力扣 450 题

例题细节已经讲过&#xff08;二叉搜索树的基础操作-CSDN博客&#xff09;&#xff0c;用非递归和递归均可实现&#xff0c;这里只给出递归参考代码&#xff1a; public TreeNode deleteNode(TreeNode node, int key) {if (node null) {return null;}if (key < node.val) …

算法进阶——字符串的排列

题目 输入一个长度为 n 字符串&#xff0c;打印出该字符串中字符的所有排列&#xff0c;你可以以任意顺序返回这个字符串数组。 例如输入字符串ABC,则输出由字符A,B,C所能排列出来的所有字符串ABC,ACB,BAC,BCA,CBA和CAB。 数据范围&#xff1a;n<10 要求&#xff1a;空间复…

【JavaEE初阶】 死锁详解

文章目录 &#x1f38b;死锁的概念&#x1f333;死锁的三个典型情况&#x1f6a9;一个线程一把锁&#x1f6a9;两个线程两把锁&#x1f6a9;n个线程m把锁(哲学家就餐问题) &#x1f384;如何破除死锁&#x1f6a9;破坏循环等待 本文重点&#xff1a; 死锁咋回事 死锁的三个典型…

【SkyWalking】SkyWalking是如何实现跨进程传播链路数据?

文章目录 一、简介1 为什么写这篇文章2 跨进程传播协议-简介 二、协议1 Standard Header项2 Extension Header项3 Correlation Header项 三、跨进程传播协议的源码分析1 OpenTracing规范2 通过dubbo插件分析跨进程数据传播3 分析跨进程传播协议的核心源码 四、小结参考 一、简介…

亚马逊,速卖通,敦煌产品测评补单攻略:低成本、高安全实操指南

随着电商平台的发展和消费者对产品质量的要求提升&#xff0c;测评补单成为了商家们提升销售和用户口碑的关键环节。然而&#xff0c;如何在保持成本低廉的同时确保操作安全&#xff0c;一直是卖家们面临的挑战。今天林哥分享一些实用的技巧和策略&#xff0c;帮助卖家们产品的…

嵌入式C语言自我修养《内存堆栈管理》学习笔记

目录 一、Linux环境下的内存管理 二、栈的管理 三、堆内存管理 四、mmap映射区 五、内存泄漏与防范 六、常见的内存错误及检测 C程序中定义的函数、全局变量、静态变量经过编译链接后&#xff0c;分别以section的形式存储在可执行文件的代码段、数据段和BSS段中。当程序运…

【Zabbix】Zabbix学习笔记

现在Zabbix Server存在的问题&#xff1a; 问题1&#xff1a; Zabbix server: Utilization of discoverer processes over 75% 问题2&#xff1a; Zabbix server: Utilization of icmp pinger processes over 75% 优化的解决办法是修改配置文件把Discovery和Pinger进程数量调大…

04-RocketMQ源码解读

目录汇总&#xff1a;RocketMQ从入门到精通汇总 上一篇&#xff1a;03-RocketMQ高级原理 这一部分&#xff0c;我们开始深入RocketMQ的源码。源码的解读是个非常困难的过程&#xff0c;每个人的理解程度都会不一样&#xff0c;也不太可能通过讲解把其中的细节全部讲明白。我们今…

panads操作excel

panads简介 pandas是基于Numpy创建的Python包&#xff0c;内置了大量标准函数&#xff0c;能够高效地解决数据分析数据处理和分析任务&#xff0c;pandas支持多种文件的操作&#xff0c;比如Excel&#xff0c;csv&#xff0c;json&#xff0c;txt 文件等&#xff0c;读取文件之…

unity发布微信小游戏,未找到 game.json报错原因

unity发布微信小游戏&#xff0c;未找到 game.json报错原因 同一个问题相隔一年遇到两次&#xff0c;两次原因都不一样&#xff0c;记录一下&#xff0c;以后不要再掉坑里 原因一&#xff1a;申请的appID是小程序不是小游戏 解决方法&#xff1a;需要在程序平台修改服务类目 如…

哈希应用之布隆过滤器

文章目录 1.介绍1.1百度搜索1.2知乎好文1.3自身理解 2.模拟实现2.1文档阅读2.2代码剖析 3.误判率的研究4.布隆过滤器的应用4.1如何找到两个分别有100亿个字符串的文件的交集[只有1G内存].分别给出精确算法和近似算法4.2如何扩展BloomFilter使得它支持删除元素的操作 5.整体代码…

pytorch中nn.DataParallel多次使用

pytorch中nn.DataParallel多次使用 import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader# 定义模型 class MyModel(nn.Module):def __init__(self):super(MyModel, self).__init__()self.fc nn.Linear(10, 1)def forwa…

ROS为机器人装配激光雷达

移动机器人在环境中获取障碍物的具体位置、房间的内部轮廓等信息都是非常必要的&#xff0c;这些信息是机器人创建地图、进行导航的基础数据&#xff0c;除上面所讲的Kinect&#xff0c;还可以使用激光雷达作为这种场景应用下的传感器。 激光雷达可用于测量机器人和其他物体之间…

3.简单场景构建

在新建的项目中&#xff0c;默认存在 Main Camera 和 Directional Light两个对象。若是缺失&#xff0c;可通过选择菜单中的 Game Object->Camera 和 Geme Object->Light->Directional Light进行创建。 1.添加地形及底图 通过在Cesium面板中选择 Cesium World Terrai…

批量文件重命名软件 A Better Finder Rename 11汉化for mac

A Better Finder Rename 11是一款功能强大的文件重命名工具&#xff0c;可在Mac操作系统上使用。它提供了简单而直观的界面&#xff0c;帮助用户快速批量重命名文件和文件夹&#xff0c;提高文件管理和组织效率。 以下是A Better Finder Rename 11可能提供的一些主要功能和特点…

设计模式 - 结构型模式考点篇:适配器模式(类适配器、对象适配器、接口适配器)

目录 一、适配器模式 一句话概括结构式模式 1.1、适配器模式概述 1.2、案例 1.2.1、类适配器模式实现案例 1.2.2、对象适配器 1.2.3、接口适配器 1.3、优缺点&#xff08;对象适配器模式&#xff09; 1.4、应用场景 一、适配器模式 一句话概括结构式模式 教你将类和对…