Spring Boot统一功能处理(一)

news2025/6/22 14:13:08

本篇主要介绍Spring Boot的统一功能处理中的拦截器。

目录

一、拦截器的基本使用

二、拦截器实操

三、浅尝源码

初始化DispatcherServerlet

处理请求(doDispatch)

四、适配器模式


一、拦截器的基本使用

在一般的学校或者社区门口,通常会安排几个保安大爷来进行身份验证,只有身份符合要求的人才会被放行,否则则会被大爷拦住,而拦截器就像我们程序的保安大爷,只有通过我们自己定义的拦截规则,请求才能被放行到目标接口上。

下面我们来看看如何在Spring Boot中使用拦截器 

 在项目中设置拦截,我们需要先自己定义一些拦截器,里面包含一些具体的拦截规则,定义拦截器的代码如下:

(1)首先创建一个拦截类,通常以“Interceptor”作为类名的后半部分,这里我们定义一个LoginInterceptor类,意为与登录相关的拦截器,然后让该类实现一个HandlerInterceptor接口,具体如下:

@Component
public class LoginInterceptor implements HandlerInterceptor {

}

(2)重写三个方法:

 @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
       
    }

其中preHandle为在目标方法执行前要执行的方法,其返回值如果为true,则会被放行去执行目标方法,为false则拦截,我们可以在这个方法里根据需求定义拦截规则。postHandle为目标方法执行后要执行的方法。afterCompletion为最后视图渲染完后最后执行的方法(由于现在都是前后端分离了,后端一般不处理视图,因此这个方法不需要过多了解)。

定义好拦截器后我们还需要配置拦截器,具体配置流程如下:

(1)创建配置类(一般以Config结尾,这里以为WebConfig),实现WebMvcConfigurer接口:

public class WebConfig implements WebMvcConfigurer {
}

(2)然后重写addInterceptor方法

@Override
    public void addInterceptors(InterceptorRegistry registry) {
        
    }

(3)然后我们在里面添加我们需要配置的拦截器,具体如下:

这里我们可以通过@Autowired注入一个LoginInterceptor对象,也可以直接在参数里new一个,只要是传入一个实现前面的HandlerInterceptor接口的类的对象即可。

(4)然后在配置我们需要拦截的路径(即请求url中ip地址端口号的后面的部分):

 这里的”/**"表示任意路径,例如“/user/book、/user”等,另外还有“/*"他只能表示一级路径,例如:

”/user,/book"等。

(4)由于通常我们并不需要所有路径都进行拦截(例如登录请求),因此我们还需要排除一些路径,让这些路径不被拦截,具体如下:

 (5)最后我们还需要把这个类放到Spring容器里,由于这里与配置相关,所有使用@Configuration。

二、拦截器实操

 接下来我们来实操一下。首先我们创建一个Controller类,在里面定义一个login方法(这里只是简单测试一下,不进行密码校验,只是给用户设置一个登录状态而已):

 然后再添加几个测试方法:

然后我们再来定义一下拦截器,再preHandle方法中设置一下拦截规则,只有处于登录状态才能放行 ,并在另外两个方法中打印日志来进行观察:

然后在注册(配置)一下拦截器(不拦截login方法,其他全部拦截) :

最后我们通过postMan构造请求来访问一下这些方法.

先访问一下test01 

可以发现返回的响应为空,也就是说请求被拦截器拦截到了。

然后我们再来访问一下login

可以发现响应有数据了,但由于我们请求中没有传值,导致接口中的两个参数为空,所以返回了false。接下来我们补上这两个值再访问一下

 可以发现响应中返回true了,同时这也意味着我们现在已经给用户设置成登录状态了,此时我们再来访问test01

可以发现响应已经有数据了。这也就意味着这个请求已经被拦截器放行了。

最后我们再来看一下 控制台的日志:

可以发现,拦截器是严格按照顺序执行相关方法的 ,如果请求被拦截了,则只会执行postHandle方法就返回了,如果请求被放行则会按顺序执行完拦截器中的三个方法。并且对于配置中没有涉及到的路径,和被排除的路径,则根本不会进入到拦截器。

三、浅尝源码

接下来,我们来浅浅阅读一下与拦截器相关的部分源码。

初始化DispatcherServerlet

仔细观察日志可以发现,当我们的服务器接收到第一个来自前端的请求时,会初始化一个dispatcherServerlet类。

它的初始化方法为init(),具体实现是在其父类HttpServerletBean中实现的

init方法首先创建了一个PropertyValues类,这个类我并不知道是干嘛的,但根据其名称可以大体猜出来应该是去读一些配置,并且下面的if语句 判断这个对象是否为空,不为空才去执行相关逻辑,因此可以推测出if语句里应该是去根据读到的配置去进行一些设置。在init方法最后执行了一个initServerletBean方法,,我们来具体看一下这个方法,

转到定义可以发现HttpServerletBean中并未实现这个方法,接下来我们去其子类看一下 

 

 可以发现其子类FrameworkServerlet重写了这个方法,并具体进行了实现。仔细观察可以发现这个方法主要是在打印日志,日志的内容就是我们在前面控制台所看到的

 

并且 这里还进行了计时,并打印在了日志里。除去日志的部分可以发现这个方法就只剩下try-catch中的内容了:

接下来我们继续进入到其中的initWebAppliactionContext ()来看一下,

根据名字可以发现这个方法应该是用来 初始化WebApplicationContext的,并且通过代码大致可以发现这个方法会先去从类的成员属性中获取WebAppliactionContext,如果成员属性不为空,则会直接用成员属性的,如果为空,则调用findWebApplication去寻找一个并使用,如果没找到,则去创建一个。执行完上面第一个红框里的内容后,wac应该是已经不再为空了的,接下来调用onRefresh方法,可以发现这里加了锁来防止线程安全问题。接下来我们进到onRefresh方法来看一下:

可以发现FrameWorkServerlet中并未进行实现,我们再进到其子类看一下:

 可以发现子类进行了实现,并且此时这个子类就是我们要初始化的DispatchServerlet。然后我们再看看这个方法里使用的initStrategies()方法:

通过方法名称可以发现这个方法是在进行一些初始化,然后再通过具体代码可以发现这个方法初始化了九个组件,这些组件就是Spring的九大组件,其名称如下:

  • MultipartResolver:文件上传解析器
  • LocaleResolver:区域解析器
  • ThemeResolver:主题解析器
  • HandlerMappings:处理器映射器
  • HandlerAdapters:处理器适配器
  • HandlerExceptionResolvers:异常处理器解析器
  • RequestToviewNameTranslator:视图名称转换器
  • ViewResolvers:视图解析器
  • FlashMapManager:FlashMap管理器

初始化这些组件后,DispatchServerlet就初始化完了。

处理请求(doDispatch)

初始化完成后,DispatchServerlet就能进行请求的处理了,处理请求,主要通过DispatchServerlet类的doDispatch方法来对请求调度给Controller来执行,下面我们来详细看一下这个方法:

首先它会去获取一个与请求对应的处理器,然后再根据处理器去获取一个能够使用的适配器

然后再根据适配器来顺序执行拦截器的相关方法以及目标方法 然后处理视图,并执行最后的afterCompletion方法

四、适配器模式

在前面浅尝源码时,提到了适配器这个概念,适配器使用到了一种设计模式 --- 适配器模式。适配器模式能将一个类的接口,转换成符合客户期待的接口,从而使原本并不能兼容使用的接口也能使用了。简单来说,就是有一个接口,由于兼容问题并不能直接使用,需要在中间加上一个适配器才能够使用这个接口。例如我们生活中的转接头,当我们的手机是Type_c的充电口,而我们却只有苹果的数据线时,这根苹果的数据线自然是冲不了我们的手机的,此时就需要一个转接头了,通过转接头,我们就可以给手机充电了。此处转接头就相当于我们的的适配器,而转接头的设计就相当于是是适配器模式这种设计思想

可能有人会说为什么 不在一开始就设计成兼容的接口呢,这样就没必要大费周章弄一个适配器了,这样固然好,但人并不是万能的,总会有我们意想不到的情况出现,面面俱到几乎是不可能的,就像使用Type-c接口的手机厂商肯定不会想到有人会用苹果的数据线来充电,但既然这个需求是存在的,也就不能不去实现了,重新设计的话,成本又太高,因此,就只能使用适配器这一无奈之举了。

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

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

相关文章

【C++学习】C++11新特性(第一节)

文章目录 ♫一.文章前言♫二.C11新特性♫一.统一的列表初始化♫二.std::initializer_list♫三.声明♫四.decltype关键字♫五.nullptr♫六.新增加容器---静态数组array、forward_list以及unordered系列♫6.1unordered_map与unoredered_set♫6.2array♫6.3 forward_list&#xff…

Leetcode算法训练日记 | day18

一、找树左下角的值 1.题目 Leetcode:第 513 题 给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: root [2,1,3] 输出: 1示例 2: 输入: [1,2,3,4,null,5,6,null,null,7] 输出:…

nandgame中的Memory(内存操作):栈、堆、静态区

Push Memory Push Memory 将内存中的值push到栈内堆栈顶部的值是一个内存地址。从堆栈中弹出地址。获取内存地址的当前内容,并将其推送到堆栈上。POP_A //堆栈顶部的值是一个内存地址。从堆栈中弹出地址。 D *A //获取内存地址的当前内容 PUSH_D //将其推送到…

JVM性能调优——运行时参数

文章目录 1、JVM参数选项类型1.1、标准参数选项1.2、非标准参数选项1.3、非稳定参数选项 2、添加JVM参数的方式3、常用JVM参数选项4、通过Java代码获取JVM参数5、小结 熟悉JVM参数对于系统调优是非常重要的。比如一个高流量的延迟的电子交易平台,它要求的响应时间都…

ROS机器人未知环境自主探索功能包explore_lite最全源码详细解析(五)

本系列文章主要针对ROS机器人常使用的未知环境自主探索功能包explore_lite展开全源码的详细解析,并进行概括总结。 本系列文章共包含六篇文章,前五篇文章主要介绍explore_lite功能包中 explore.cpp、costmap_tools.h、frontier_search.cpp、costmap_clie…

MySQL:关于数据库的一些练习题

文章目录 前面的内容已经把数据库的一些必要知识已经储备好了,因此下面就对于这些语句进行一些练习: 批量插入数据 insert into actor values (1, PENELOPE, GUINESS, 2006-02-15 12:34:33), (2, NICK, WAHLBERG, 2006-02-15 12:34:33);SQL202 找出所有…

C/S医学检验LIS实验室信息管理系统源码 医院LIS源码

LIS系统即实验室信息管理系统。LIS系统能实现临床检验信息化,检验科信息管理自动化。其主要功能是将检验科的实验仪器传出的检验数据经数据分析后,自动生成打印报告,通过网络存储在数据库中,使医生能够通过医生工作站方便、及时地…

一起学习python——基础篇(14)

今天讲一下python的json解析方式。 上一篇文章讲述了将传参数据转换为json格式的数据传给后台,如果后端返回的json格式数据,我们该如何解析呢? 例子一:简单的json数据格式 如果后端返回的json数据如下, { "na…

【leetcode面试经典150题】34.有效的数独(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主,题解使用C语言。(若有使用其他语言的同学也可了解题解思路,本质上语法内容一致&…

Docker Compose 一键安装

文章目录 一、场景说明二、脚本职责三、参数说明四、操作示例五、注意事项 一、场景说明 本自动化脚本旨在为提高研发、测试、运维快速部署应用环境而编写。 脚本遵循拿来即用的原则快速完成 CentOS 系统各应用环境部署工作。 统一研发、测试、生产环境的部署模式、部署结构、…

【C++学习】C++11新特性(第二节)—— 右值引用与移动语义超详解

文章目录 文章简介二.右值引用1.什么是左值,什么是右值?什么是左值引用,什么是右值引用?2.左值引用与右值引用比较 三.右值引用使用场景和意义1.左值引用的使用场景:2.左值引用的短板:3.右值引用与移动构造…

2024大模型落地应用案例集(免费下载)

【1】扫码关注本公众号 【2】私信发送 2024大模型落地应用案例集 【3】获取本方案PDF下载链接,直接下载即可。

【Linux】环境下OpenSSH升级到 OpenSSH_9.6P1(图文教程)

漏洞描述 OpenSSH(OpenBSD Secure Shell)是加拿大OpenBSD计划组的一套用于安全访问远程计算机的连接工具。该工具是SSH协议的开源实现,支持对所有的传输进行加密,可有效阻止窃听、连接劫持以及其他网络级的攻击。OpenSSH 9.6之前…

深入浅出Golang image库:编写高效的图像处理代码

深入浅出Golang image库:编写高效的图像处理代码 引言image库概览图像处理基础概念image库的主要组成和功能image接口图像格式的支持color模型 结论 图像的基本操作创建图像新图像的创建从文件加载图像 图像的保存与导出图像的颜色和像素处理绘制基本形状和文字 高级…

无网络连接 请检查你的网络设置 然后重试 [2604] 彻底解决方案

错误提示:无网络连接 请检查你的网络设置 然后重试 [2604] 彻底解决方案如下: 方案一: 打开Internet Explorer浏览器,选择"工具 > Internet 选项"。 在Internet属性窗口下,点击高级下滑到安全模块分类…

[漏洞复现]D-Link未授权RCE漏洞复现(CVE-2024-3273)

声明:亲爱的读者,我们诚挚地提醒您,Aniya网络安全的技术文章仅供个人研究学习参考。任何因传播或利用本实验室提供的信息而造成的直接或间接后果及损失,均由使用者自行承担责任。Aniya网络安全及作者对此概不负责。如有侵权&#…

Linux查看系统配置信息的命令【lscpu】【free】【df】【uname】【lsblk】【top】

目录 1.查看CPU信息【lscpu】 2.查看内存信息【free】 3.查看文件系统信息【df】 4.查看系统信息【uname】 知识扩展:Red Hat Enterprise Linux 和 Debian GNU/Linux 两者的发展介绍 知识扩展:Centos 和 ubuntu的区别 知识扩展:更多 …

Quanto: PyTorch 量化工具包

量化技术通过用低精度数据类型 (如 8 位整型 (int8)) 来表示深度学习模型的权重和激活,以减少传统深度学习模型使用 32 位浮点 (float32) 表示权重和激活所带来的计算和内存开销。 减少位宽意味着模型的内存占用更低,这对在消费设备上部署大语言模型至关…

Python学习从0开始——项目一day01爬虫

Python学习从0开始——项目一day01爬虫 一、导入代码二、使用的核心库三、功能测试3.1初始代码3.2新建文件3.3代码调试 四、页面元素解析4.1网页4.2修改代码4.3子页面4.4修改代码 一、导入代码 在Inscode新建一个python类型的项目,然后打开终端,粘贴以下…

高中数学:三角函数-基础知识

一、任意角 顺时针旋转是负值角 逆时针旋转式正值角 一个角对应一个终边 一个终边对应无数个角 xk*360 例题 二、弧度制 弧长与半径的比值,就是角度 常见角度与弧度的对应关系 例题 三、弧长与扇形面积公式 注意:弧度制下的扇形面积公式&#x…