Spring MVC(二)-过滤器与拦截器

 过滤器和拦截器在职责和使用场景上存在一些差异。

过滤器

拦截器

作用

对请求进行预处理和后处理。例如过滤请求参数、设置字符编码。

拦截用户请求并进行相应处理。例如权限验证、用户登陆检查等。

工作级别

Servlet容器级别,是Tomcat服务器创建的对象。可以拦截任何资源。

是Spring MVC容器的对象。只会对控制器中的方法进行拦截。

执行时机

在请求到达DispatcherServlet之前就开始执行,可以在请求被任何Spring MVC组件处理之前对请求进行修改或处理。

请求处理前、请求处理后,视图渲染前、整个请求完成后

使用场景

通常用于跨多个Controller的通用逻辑处理或者全局性的处理。例如日志记录、请求参数校验等。

用于对特定的Controller或者请求进行拦截,执行一些全局性的逻辑处理。例如权限验证。

表 过滤器与拦截器的对比

1 过滤器

图 javax.servlet.Filter 的UML

init 在Servlet容器启动时执行,destory在Servlet容器关闭时执行。

@WebFilter(urlPatterns = "/user/*")
public class UserInfoFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("filter doFilter 1"); // 处理器之前执行chain.doFilter(request,response); // 没有这条语句,则请求不会到处理器System.out.println("filter doFilter 2"); // 处理器之后执行}
}

OncePerRequestFilter 是Spring提供的一个常用的过滤器,其作用是确保一次HTTP请求期间只执行一次特定的过滤器逻辑,避免过滤器逻辑重复执行,提高系统的性能和效率。

图 OncePerRequestFilter 的doFilter方法

spring-web 定义了一些继承于OncePerRequestFilter的过滤器。

1.1 HttpPutFormContentFilter

主要作用是自动封装前端传递过来的PUT请求参数。在Spring MVC中,默认只有POST请求的表单数据(content-type为application/x-www-form-urlencoded)会被解析,而PUT、PATCH和DELETE请求的表单数据则不会被解析。配置了HttpPutFormContentFilter后,这三种类型的请求表单数据可以被正确解析。

(Spring 5.1开始,其被FormContentFilter 所取代,不仅支持PUT请求,还支持POST、PATCH和DELETE等表单数据解析)

图 HttpPutFormContentFilter的doFilterInternal方法

1.2 ForwardedHeaderFilter

检查请求中是否存在转发头,如果存在,则解析这个字段并提取信息。然后,使用这些信息来修改请求的主机、端口和方案,以便后续的请求处理能够基于更准确的源信息。

然后,使用转发头需要注意安全问题,因为程序无法确定这些头字段是由预期的代理服务器添加还是被恶意的客户端伪造。因此,通常建议配置信任的代理服务器来添加或删除这些不信任的外部头字段。此外也可以将其配置为只删除而不使用这些标头。

1.3 ShallowEtagHeaderFilter

是一个支持ETag的过滤器。ETag是指被请求变量的实体值,是一个可以与Web资源关联的记号,Web资源可以是一个Web页,也可以是JSON或XML文档。服务器负责判断记号是什么,并在HTTP响应头中将其传送到客户端。

过滤器的主要作用是根据响应中缓存的内容创建Shallow ETag并计算MD5,当客户端下一次发送请求时,会执行相同操作,并将计算的值与if-None-Match请求头进行比较,如果相等,则返回304(表示资源没有发送变化)。

该过滤器只能节省带宽,并不能提高服务器性能,因为它必须为每个请求计算完整的响应。

2 拦截器

图 Spring的HandlerInterceptor UML

preHandle: 在处理器方法被调用之前执行,如果返回false,则拦截链下的其他拦截器将不会被执行,处理器也不会被执行。

postHandle: 在处理器方法执行完后、视图渲染前执行。

afterCompletion: 在请求完全执行完后执行。通常用于清理工作。

2.1 拦截器原理

拦截器是基于AOP思想实现,但在实现细节上并不是直接通过Spring AOP的代理机制来完成。而是通过Spring MVC的内部机制来实现。在DispatcherServlet的请求处理中被集成及调用。

HandlerInterceptorRegistry

注册和管理拦截器。

HandlerMapping

根据请求找到对应的处理器,在其实现类中,会考虑将已注册的拦截器和处理器一起封装成一个HandlerExecutionChain对象。

HandlerAdapter

负责调用处理器(Controller方法)。在调用处理器之前和之后,会与拦截器进行交互,确保拦截器的preHandle、postHandle等方法在正确时机被调用。

DispatcherServlet

负责处理所有的请求。在请求处理流程中,会根据HandlerMapping 找到HandlerExecutionChain,然后依次调用链中拦截器的preHandle方法。处理器执行完毕后,会调用postHandle方法,最后调用afterCompletion方法。

表 跟拦截器有关的类与接口

图 DispatcherServlet 的doDisspatch方法部分代码

2.1.1 HandlerMapping

用于定义请求与处理器之间的映射。

图 HandlerMapping UML

在Spring MVC 的WebApplicationContext 容器被启动时,会执行DispatcherServlet 的初始化方法,其会查找容器中所有被注册为bean的HandlerMapping。

图 DispatcherServlet 的 initStrategies方法

每次执行DispatcherServlet 的doDispatch方法(处理请求)时,会轮询每一个handlerMapping实例,并调用其getHanler方法,来查找该请求的请求链。

图DispatcherServlet 的getHandler方法

HanlerMapping 的getHandler 方法会查找该请求对应的处理器,如果没找到,则返回null,否则将处理器实例与请求对应的拦截器一起封装为一个请求链。

图 HandlerMapping 默认实现AbstractHandlerMapping 的getHandler方法

图 HandlerMapping 默认实现AbstractHandlerMapping 的getHandlerExecutionChain方法

 2.1.2 HandlerMapping 与 @RequestMapping

Spring 会扫描带有@RequestMapping注解的方法与类,并把它们注册为HandlerMapping类型的bean。这个工作主要是由RequestMappingHandlerMapping来完成。

图 RequestMappingHandlerMapping UML

其同时实现了HandlerMapping及InitializingBean(当IoC容器中bean的所有属性被初始化之后,会调用其afterPropertiesSet()方法)接口。

图 RequestMappingHandlerMapping的父类的afterPropertiesSet方法

RequestMappingHandlerMapping 实例是在何时被注册成bean的呢?

在DispatcherServlet初始化时,会初始化HandlerMapping.

图  DispatcherServlet的initHandlerMappings方法

而默认的DispatcherServlet 类在Spring-webmvc的DispatcherServlet.properties文件中配置。

图 DispatcherServlet.properties 文件

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

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

相关文章

2024-3-21 市场情绪,嘿嘿嘿

市场的预期终于来到了今天,艾艾精工 13追平了 克来机电 13 ,永悦科技8 追平了 睿能科技 8,那么早盘kimi概念卡了1个钟的流动性感觉强度一般般,唯一亮点就是 中广天泽 竞价抢筹;kimi概念本身没有什么大的预期&#xf…

2024 Java开发跳槽、面试心得体会

前言 由于个人发展的原因和工作上的变动,产生了想出来看看机会的想法,在决定要换工作后就开始复习准备。从年前就开始看面经,系统复习自己使用的技术栈,把自己项目中的技术梳理清楚。3月初开始在招聘网站上投简历,到三…

Java小项目--满汉楼

Java小项目–满汉楼 项目需求 项目实现 1.实现对工具包的编写 先创建libs包完成对jar包的拷贝和添加入库 德鲁伊工具包 package com.wantian.mhl.utils;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource; import java.io.FileInputStream…

NC249989 猫猫与主人 (双指针,排序)

本题限制时间1s,而数据范围2e5,也就是说时间复杂度顶多 O ( n l o g n ) O(nlogn) O(nlogn)了,那就不能直接暴力枚举,可以使用双指针。 在使用双指针时要思考主要指针指向什么,在什么条件下能够更新另一个指针。 在本…

【Linux】进程控制 -- 详解

一、进程创建 目前学习到的进程创建的两种方式: 命令行启动命令(程序、指令等) 。通过程序自身,调用 fork 函数创建出子进程。 1、fork 函数初识 在 Linux 中的系统接口 fork 函数是非常重要的函数,它从已存在进程中…

js 输出一个相加后的整数。

等差数列 2,5,8,11,14。。。。 (从 2 开始的 3 为公差的等差数列) 输出求等差数列前n项和 输入:275 输出:113575const rl require("readline").createInterface({ input…

JavaSE:数据类型与变量

目录 一、前言 二、数据类型与变量 (一)字面常量 (二)数据类型 (三)变量 1.变量概念 2.语法格式 3.整型变量 3.1整型变量 3.2长整型变量 3.3短整型变量 3.4字节型变量 4.浮点型变量 4.1双精…

Linux--gdb调试

一.安装gdb sudo apt install gdb 二.使用gdb 三.gdb的相关操作 gdb 可执行文件名 显示代码: l 加断点: b 行号 启动程序:r(运行之前一定要加断点) 查看断点信息: info break/info b 删除断点信息:delete 断点编号 单步执行:n 打印 :p 显示:display 变量名: 退出:q …

C语言 自定义类型:联合和枚举

目录 前言 一、联合体 1.1 联合体的特点 1.2 联合体与结构体的区别 1.3 联合体的大小计算 1.4 联合体例子 1.5 联合体判断大小端 二、枚举 2.1 枚举类型定义 2.2 枚举类型的优点 2.3 枚举类型的使用 总结 前言 之前我们讲了C语言其中一个自定义类型结构体&#xff…

微信小程序外卖跑腿点餐(订餐)系统(uni-app+SpringBoot后端+Vue管理端技术实现)

项目介绍 自从计算机发展开始,计算机软硬件相关技术的发展速度越来越快,在信息化高速发展的今天,计算机应用技术似乎已经应用到了各个领域。 在餐饮行业,除了外卖以外就是到店里就餐,在店里就餐如果需要等待点餐的话…

Java基础--集合

集合 1.可以动态的保存任意多个对象,使用比较方便。 2.提供了一系列方便的操作对象的方法:add,remove,set,get等。 3.使用集合添加,删除新元素的示意代码,简介明了。 集合主要是两种&#xff0…

罗技G29游戏方向盘试玩拆解,带震动力反馈

1.正好有时间记录下 自己的爱好 一千多的罗技G29游戏方向盘试玩拆解,带震动力反馈,值这个价吗_哔哩哔哩_bilibili 一千多的罗技G29游戏方向盘试玩拆解,带震动力反馈,值这个价吗_哔哩哔哩_bilibili 2.拆解 3.2个大电机 4.主控芯…

全新体验|德克萨斯州奥斯汀市登陆 The Sandbox

以前所未有的方式探索德克萨斯州奥斯汀——The Sandbox迎来虚拟旅游,新体验由Smobler工作室打造。 我们的使命是为虚拟旅游创造新机遇,让每个人都能更方便地游览城市和国家。我们非常兴奋地宣布:Cobbleland:Austin,这款…

城市排涝与海绵城市规划设计中的水文水动力模拟技术

原文链接:城市排涝与海绵城市规划设计中的水文水动力模拟技术https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247598401&idx3&sn0c4c86b3a5d09a75b8f07e6fad81aa9c&chksmfa8200a6cdf589b0970a6854869e8e3a9f132fe40a19977863c091cbcf6d9786f…

赋能 DevOps:平台工程的关键作用

在当今快节奏的数字环境中,DevOps 已成为寻求简化软件开发和交付流程的组织的关键方法。DevOps 的核心在于开发和运营团队之间协作的概念,通过一组旨在自动化和提高软件交付生命周期效率的实践和工具来实现。 DevOps 实践的关键推动因素之一是平台工程。…

c语言(自定义类型——结构体)

C语⾔已经提供了内置类型,如:char、short、int、long、float、double等,但是只有这些内置类 型还是不够的,假设我想描述学⽣,描述⼀本书,这时单⼀的内置类型是不⾏的。描述⼀个学⽣需要 名字、年龄、学号、…

libVLC 元数据

libVLC是一个开源的多媒体框架,主要用于处理和播放各种类型的媒体文件,如视频、音频等。 媒体元数据(Metadata):包括媒体文件的基本信息,如标题、艺术家、专辑、持续时间、分辨率、比特率、编码格式等。 …

Docker【安装redis】【redis-desktop-manager】

文章目录 前言一、建立挂载目录二、下载运行镜像三、安装redis可视化工具redis-desktop-manager 前言 本文开始默认你已经安装了docker,如果对此还不够了解请看这篇文章:docker的安装 一、建立挂载目录 一般对应mysql、redis这种存储数据的镜像&#x…

RESNET的复现pytorch版本

RESNET的复现pytorch版本 使用的数据为Object_102_CaDataset,可以在网上下载,也可以在评论区问。 RESNET模型的亮点 1.提出了残差模块。 2.使用Batch Normalization加速训练 3.残差网络:易于收敛,很好的解决了退化问题&#…

【C++】狗屁不通文章生成器2.0

【C】狗屁不通文章生成器2.0 1 前言2 改进2.1 字词的前后关系2.2 文章生成系统 3 实现(部分)3.1 class wordpair3.1.1 转化为 json3.1.2 添加后缀词3.1.3 选择后缀词 3.2 class createArticle3.2.1文本分割3.2.2生成文章 4演示4.1 wordpair(3x2), 启动词(春天)4.2 wordpair(2x1…