当前位置: 首页 > news >正文

第三十六章 Spring之假如让你来写MVC——拦截器篇

Spring源码阅读目录

第一部分——IOC篇

第一章 Spring之最熟悉的陌生人——IOC
第二章 Spring之假如让你来写IOC容器——加载资源篇
第三章 Spring之假如让你来写IOC容器——解析配置文件篇
第四章 Spring之假如让你来写IOC容器——XML配置文件篇
第五章 Spring之假如让你来写IOC容器——BeanFactory和FactoryBean
第六章 Spring之假如让你来写IOC容器——Scope和属性填充
第七章 Spring之假如让你来写IOC容器——属性填充特别篇:SpEL表达式
第八章 Spring之假如让你来写IOC容器——拓展篇
第九章 Spring之源码阅读——环境搭建篇
第十章 Spring之源码阅读——IOC篇

第二部分——AOP篇

第十一章 Spring之不太熟的熟人——AOP
第十二章 Spring之不得不了解的内容——概念篇
第十三章 Spring之假如让你来写AOP——AOP联盟篇
第十四章 Spring之假如让你来写AOP——雏形篇
第十五章 Spring之假如让你来写AOP——Joinpoint(连接点)篇
第十六章 Spring之假如让你来写AOP——Pointcut(切点)篇
第十七章 Spring之假如让你来写AOP——Advice(通知)上篇
第十八章 Spring之假如让你来写AOP——Advice(通知)下篇
第十九章 Spring之假如让你来写AOP——番外篇:Spring早期设计
第二十章 Spring之假如让你来写AOP——Aspect(切面)篇
第二十一章 Spring之假如让你来写AOP——Weaver(织入器)篇
第二十二章 Spring之假如让你来写AOP——Target Object(目标对象)篇
第二十三章 Spring之假如让你来写AOP——融入IOC容器篇
第二十四章 Spring之源码阅读——AOP篇

第三部分——事务篇

第二十五章 Spring之曾经的老朋友——事务
第二十六章 Spring之假如让你来写事务——初稿篇
第二十七章 Spring之假如让你来写事务——铁三角篇
第二十八章 Spring之假如让你来写事务——属性篇
第二十九章 Spring之假如让你来写事务——状态篇
第三十章 Spring之假如让你来写事务——管理篇
第三十一章 Spring之假如让你来写事务——融入IOC容器篇
第三十二章 Spring之源码阅读——事务篇

第四部分——MVC篇

第三十三章 Spring之梦开始的地方——MVC
第三十四章 Spring之假如让你来写MVC——草图篇
第三十五章 Spring之假如让你来写MVC——映射器篇
第三十六章 Spring之假如让你来写MVC——拦截器篇
第三十七章 Spring之假如让你来写MVC——控制器篇
第三十八章 Spring之假如让你来写MVC——适配器篇
第三十九章 Spring之假如让你来写MVC——番外篇:类型转换
第四十章 Spring之假如让你来写MVC——ModelAndView篇
第四十一章 Spring之假如让你来写MVC——番外篇:数据绑定
第四十二章 Spring之假如让你来写MVC——视图篇
第四十三章 Spring之假如让你来写MVC——上传文件篇
第四十四章 Spring之假如让你来写MVC——异常处理器篇
第四十五章 Spring之假如让你来写MVC——国际化篇
第四十六章 Spring之假如让你来写MVC——主题解析器篇
第四十七章 Spring之假如让你来写MVC——闪存管理器篇
第四十八章 Spring之假如让你来写MVC——请求映射视图篇
第四十九章 Spring之假如让你来写MVC——番外篇:属性操作
第五十章 Spring之假如让你来写MVC——融入IOC容器篇
第五十一章 Spring之源码阅读——MVC篇


文章目录

  • Spring源码阅读目录
    • 第一部分——IOC篇
    • 第二部分——AOP篇
    • 第三部分——事务篇
    • 第四部分——MVC篇
  • 前言
  • 尝试动手写IOC容器
      • 第三十二版 拦截器
        • 拦截器接口
        • 改造映射器
        • 改造`DispatcherServlet`
        • 测试
  • 总结


前言

    对于Spring一直都是既熟悉又陌生,说对它熟悉吧,平时用用没啥问题,但面试的时候被问的一脸懵逼,就很尴尬,都不好意思在简历上写着熟悉Spring了
在这里插入图片描述

    所以决定花点时间研究研究Spring的源码。主要参考的书籍是:《Spring源码深度解析(第2版)》、《Spring揭秘》、《Spring技术内幕:深入解析Spring架构与设计原理(第2版)》


     书接上回,在上篇 第三十五章 Spring之假如让你来写MVC——映射器篇 中,A君 已经实现了 映射器 部分的功能了。接下来看看 A君 会有什么骚操作吧

尝试动手写IOC容器

    出场人物:A君(苦逼的开发)、老大(项目经理)

    背景:老大 要求 A君在一周内开发个简单的 IOC容器

    前情提要:A君 已经实现了 映射器 部分的功能了 。。。

第三十二版 拦截器

    今天,刚一上班,A君 就屁颠屁颠的跑到 老大 的办公室去,炫耀自己的成果

    “嗯。做的不错。不过还需要加点料?” 老大 看着满脸兴奋的 A君 。悠悠说道

    “加点料,要加什么??” A君 兴奋地逐渐消失,一脸懵逼的问到

    “你听说过 过滤器 吗?” 老大 微笑着问道

    “听说过,过滤器Servlet 规范中的一部分,所有 Servlet容器 都必须实现。请求在到达 Servlet 之前,或者响应返回客户端之前,都会经过 过滤器 进行处理。如果 过滤器 处理不通过,它可以阻止请求继续往下处理!” A君 回答道

    “不错,现在要加的料和 过滤器 效果差不多,只是是框架层面的。叫做 拦截器。” 老大 说到

    “为什么有 过滤器 之后还需要 拦截器 呢?” A君 提出疑问

    “问得好!原因其实也很简单。过滤器Servlet容器 的行为,发生在 Servlet 之前,那么就以为这它无法获取框架中的内容,无法进行更细致的拦截。” 老大 笑着说道

    “原来如此!” A君 恍然,之前一直存在的疑问,被 老大 三言两语就解开了

    “去吧!这东西并不难,我希望今天就能看到成果!” 老大 大手一挥,开始下逐客令

拦截器接口

    “OK!” A君 也爽快的回答道,离开办公室,回到自己的工位上。A君 想都没想,就开始撸代码,因为像这种提供拓展的功能,A君 只需要提供接口就行,具体内容由用户实现即可。A君 新增 HandlerInterceptor接口,代码如下:

/*** 拦截器接口*/
public interface HandlerInterceptor {/*** 方法执行前调用** @param request* @param response* @param handler* @return* @throws Exception*/default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {return true;}/*** 方法执行后调用** @param request* @param response* @param handler* @throws Exception*/default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {}/*** 请求完成时调用,不管成功还是失败** @param request* @param response* @param handler* @param ex* @throws Exception*/default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}

好了,接口定义了完成了。不过要如何执行它的实现呢?老大 之前提到和 过滤器 类似,说起 过滤器A君 其实并不算陌生,之前有折腾过 Tomcat,知道其大致的运行流程。这里又得涉及到一个设计模式——责任链。这个模式也好理解,就像 A君 平时想请个假,OA上需要经过层层审批,层层回复一样:

请假
同意
同意
同意
回复
回复
回复
回复
A君
项目经理
部门经理
技术总监
结束

每一层都得同意,这个假才算请成功,但凡有一个不同意,这个假就算是请失败了。值得注意的是:请假流程申请的时候是从前往后,而回复的时候却是从后往前的责任链 与之类似,既然如此,那么 拦截器 也就好办了:只要把 拦截器 整合成一个链表就可以了。A君 添加HandlerExecutionChain类,代码如下:

/*** 请求处理链*/
@Getter
public class HandlerExecutionChain {/*** 控制器*/private final Object handler;/*** 拦截器集合*/private final List<HandlerInterceptor> interceptorList = new ArrayList<>();private int interceptorIndex = -1;/*** 正向处理,类似与请假申请流程** @param request* @param response* @return* @throws Exception*/boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {for (int i = 0; i < this.interceptorList.size(); i++) {HandlerInterceptor interceptor = this.interceptorList.get(i);if (!interceptor.preHandle(request, response, this.handler)) {//返回false,直接调用完成方法triggerAfterCompletion(request, response, null);return false;}this.interceptorIndex = i;}return true;}/*** 反向处理,类似与请假回复流程** @param request* @param response* @throws Exception*/void applyPostHandle(HttpServletRequest request, HttpServletResponse response)throws Exception {for (int i = this.interceptorList.size() - 1; i >= 0; i--) {HandlerInterceptor interceptor = this.interceptorList.get(i);interceptor.postHandle(request, response, this.handler);}}/*** 反向处理,类似与请假回复流程** @param request* @param response* @throws Exception*/void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) {for (int i = this.interceptorIndex; i >= 0; i--) {HandlerInterceptor interceptor = this.interceptorList.get(i);try {interceptor.afterCompletion(request, response, this.handler, ex);} catch (Throwable ex2) {ex2.printStackTrace();}}}//其他方法省略
}
改造映射器

确实如 老大 所说,拦截器 就这么点东西,没啥难度的。现在还需要改下 映射器 的返回值了,之前是直接返回HandlerMethod,现在得返回HandlerExecutionChain了,改动如下:

在这里插入图片描述
AbstractHandlerMapping也做个简单的改动,需要把配置的 拦截器 添加到HandlerExecutionChain中,如下:

在这里插入图片描述

改造DispatcherServlet

现在基本改造完了,还需要个添加 拦截器 的入口,只需要扫描类是否实现了对应接口就行了。DispatcherServlet改动如下:

在这里插入图片描述

测试

    好嘞,现在一切都准备就绪了。可以开始准备测试了,其他内容还是不需要改动。只需要新增一个 拦截器 即可,A君 新增MyInterceptor。代码如下:

public class MyInterceptor implements HandlerInterceptor {// 在请求处理前执行@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("Pre-handle: " + request.getRequestURI());request.setAttribute("message", "Add Interceptor");return true;}// 在请求处理后,视图渲染前执行@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("Post-handle: " + request.getRequestURI());}// 在请求完全处理完后执行@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex) throws Exception {System.out.println("After completion: " + request.getRequestURI());}
}

添加测试代码如下:

	 @Testpublic void v32() throws Throwable {System.out.println("############# 第三十二版: 拦截器篇 #############");Tomcat tomcat = new Tomcat();//设置端口tomcat.setPort(8082);//设置静态资源路径String webApp = new File("src/main/resources/v32").getAbsolutePath();tomcat.addWebapp("/test/", webApp);tomcat.start();//挂起tomcat.getServer().await();}

测试结果如下:

在这里插入图片描述

在这里插入图片描述

前台成功返回,后台也成功打印。拦截器 也就这么完成啦。OK!起码今天可以交差了,看看 老大 明天还有什么想法吧

在这里插入图片描述


总结

    正所谓树欲静而风不止,欲知后事如何,请看下回分解(✪ω✪)

相关文章:

第三十六章 Spring之假如让你来写MVC——拦截器篇

Spring源码阅读目录 第一部分——IOC篇 第一章 Spring之最熟悉的陌生人——IOC 第二章 Spring之假如让你来写IOC容器——加载资源篇 第三章 Spring之假如让你来写IOC容器——解析配置文件篇 第四章 Spring之假如让你来写IOC容器——XML配置文件篇 第五章 Spring之假如让你来写…...

TypeScript语言的学习路线

TypeScript语言的学习路线 TypeScript&#xff08;TS&#xff09;是由Microsoft开发的一种开源编程语言&#xff0c;是JavaScript的超集&#xff0c;提供了严格的类型检查和基于类的面向对象编程特性。随着前端开发的不断进步&#xff0c;TypeScript逐渐成为了现代前端开发的主…...

Python爬虫-汽车之家各车系周销量榜数据

前言 本文是该专栏的第43篇,后面会持续分享python爬虫干货知识,记得关注。 在本专栏之前,笔者在文章《Python爬虫-汽车之家各车系月销量榜数据》中,有详细介绍,如何爬取“各车系车型的月销量榜单数据”的方法以及完整代码教学教程。 而本文,笔者同样以汽车之家平台为例,…...

C#格式化输出

上一期&#xff1a; C#格式化输出-CSDN博客 字符串插值 字符串插入功能&#xff0c;使得我们可以更直观地嵌入表达式到字符串中&#xff0c;只需要在字符串前加上$符号即可实现这一点。着中国方法不仅提高了代码的可读性&#xff0c;而且简化了字符串构造的过程。 使用Inse…...

Open FPV VTX开源之默认MAVLink设置

Open FPV VTX开源之默认MAVLink设置 1. 源由2. 准备3. 连接4. 安装5. 配置6. 测试6.1 启动wfb-ng服务6.2 启动wfb-ng监测6.3 启动QGroundControl6.4 观察测试结果 7. 总结8. 参考资料9. 补充9.1 telemetry_tx异常9.2 DEBUG串口部分乱码9.3 PixelPilot软件问题 1. 源由 飞控图传…...

【初识扫盲】逆概率加权

我们正在处理一个存在缺失数据的回归模型&#xff0c;并且希望采用一种非参数的逆概率加权方法来调整估计&#xff0c;以应对这种缺失数据的情况。 首先&#xff0c;我们需要明确问题的背景。我们有样本 { ( Y i , X i , r i ) : i 1 , … , n } \left\{\left(Y_i, \boldsym…...

Ubuntu中双击自动运行shell脚本

方法1: 修改文件双击反应 参考: https://blog.csdn.net/miffywm/article/details/103382405 chmod x test.sh鼠标选中待执行文件&#xff0c;在窗口左上角edit菜单中选择preference设计双击执行快捷键&#xff0c;如下图&#xff1a; 方法2: 设置一个应用 参考: https://blo…...

理解AJAX与Axios:异步编程的世界

理解AJAX与Axios&#xff1a;异步编程的世界 在现代Web开发中&#xff0c;异步编程作为一种处理复杂操作的方式&#xff0c;已经成为不可或缺的一部分。AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;和Axios是两种实现异步请求的流行技术。本文将深入探讨这两…...

分组通道自注意力G-CSA详解及代码复现

G-CSA定义 G-CSA (Grouped Channel Self-Attention) 是一种创新性的视觉注意力机制,巧妙地结合了卷积和自注意力的优势。通过将输入特征图划分为多个独立的通道组,在每个组内执行自注意力操作,G-CSA实现了高效的全局信息交互,同时保留了局部特征细节。这种方法不仅提高了模…...

汽车基础软件AutoSAR自学攻略(四)-AutoSAR CP分层架构(3) (万字长文-配21张彩图)

汽车基础软件AutoSAR自学攻略(四)-AutoSAR CP分层架构(3) (万字长文-配21张彩图) 前面的两篇博文简述了AutoSAR CP分层架构的概念&#xff0c;下面我们来具体到每一层的具体内容进行讲解&#xff0c;每一层的每一个功能块力求用一个总览图&#xff0c;外加一个例子的图给大家进…...

玩转大语言模型——langchain调用ollama视觉多模态语言模型

系列文章目录 玩转大语言模型——ollama导入huggingface下载的模型 玩转大语言模型——langchain调用ollama视觉多模态语言模型 langchain调用ollama视觉多模态语言模型 系列文章目录前言使用Ollama下载模型查找模型下载模型 测试模型ollama测试langchain测试加载图片加载模型…...

Github 2025-01-11 Rust开源项目日报 Top10

根据Github Trendings的统计,今日(2025-01-11统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10C项目1Swift项目1Yazi - 快速终端文件管理器 创建周期:210 天开发语言:Rust协议类型:MIT LicenseStar数量:5668 个Fork数量:122…...

【学习】【记录】【分享】微型响应系统

前言 本篇博客源于对Vue和React框架中响应式系统的好奇与探索。若文中存在任何错误或有更优的解决方案&#xff0c;欢迎各位读者不吝指正&#xff0c;让我们一起学习&#xff0c;共同进步。 1. 什么是响应式系统 响应式系统是一种编程范式&#xff0c;它允许数据的变化自动地…...

vue城市道路交通流量预测可视化系统

文章结尾部分有CSDN官方提供的学长 联系方式名片 文章结尾部分有CSDN官方提供的学长 联系方式名片 关注B站、收藏、不迷路&#xff01; 项目亮点 编号&#xff1a;R09 &#x1f687; 网站大屏管理三大前端、vuespringbootmysql、前后端分离架构 &#x1f687; 流量预测道路查询…...

Windows7 Emacs设置及中文乱码解决

个人博客地址&#xff1a;Windows7 Emacs设置及中文乱码解决 | 一张假钞的真实世界 环境说明 Windows7GNU Emacs 25.1.1安装路径&#xff1a;D:/apps/emacs/ 配置Emacs 在Windows7下安装完Emacs后&#xff0c;默认情况下Emacs不会在一启动的时候就生成.emacs配置文件和.ema…...

Python AI教程之十五:监督学习之决策树(6)高级算法C5.0决策树算法介绍

C5.0决策树算法 C5 算法由 J. Ross Quinlan 创建,是 ID3 决策树方法的扩展。它通过根据信息增益(衡量通过按特定属性进行划分而实现的熵减少量)递归地划分数据来构建决策树。 对于分类问题,C5.0 方法是一种决策树算法。它构建规则集或决策树,这是对 C4.5 方法的改进。根…...

MOS管为什么会有夹断,夹断后为什么会有电流?该电流为什么是恒定的?

以下是对MOS管MOS管为什么会有夹断&#xff0c;夹断后为什么还会有电流&#xff1f;该电流为什么是恒定的&#xff1f;的一些心得体会。 1. MOS管为什么会有夹断&#xff1f; 可以认为D极加压使得D极的耗尽层增大(原因是N极接正极&#xff0c;P极接负极&#xff0c;电子被吸引…...

网络安全-RSA非对称加密算法、数字签名

数字签名非常普遍&#xff1a; 了解数字签名前先了解一下SHA-1摘要&#xff0c;RSA非对称加密算法。然后再了解数字签名。 SHA-1 SHA-1&#xff08;secure hash Algorithm &#xff09;是一种 数据加密算法。该算法的思想是接收一段明文&#xff0c;然后以一种不可逆的方式将…...

【AI日记】25.01.13

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】【读书与思考】 AI kaggle 比赛&#xff1a;Forecasting Sticker Sales 读书 书名&#xff1a;罗素论幸福 律己 AI&#xff1a; 8 小时&#xff0c;良作息&#xff1a;1:00-9:00&#xff0c; 良短视频&…...

Mysql--运维篇--空间管理(表空间,索引空间,临时表空间,二进制日志,数据归档等)

MySQL的空间管理是指对数据库存储资源的管理和优化。确保数据库能够高效地使用磁盘空间、内存和其他系统资源。良好的空间管理不仅有助于提高数据库的性能&#xff0c;还能减少存储成本并防止因磁盘空间不足导致的服务中断。MySQL的空间管理涉及多个方面&#xff0c;包括表空间…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...