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

news2025/1/17 3:08:52

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

过滤器

拦截器

作用

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

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

工作级别

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 {
    @Override
    public 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.coloradmin.cn/o/1534109.html

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

相关文章

Cannot run program “C:\Program Files\Java\jdk-17\bin\java.exe“

错误提示:Cannot run program “C:\Program Files\Java\jdk-17\bin\java.exe” 解决办法: 检查环境变量是否配置是否正确检查项目环境是否正确,可能会出现多个JDK版本,将不需要的删除

Flume入门概述及安装部署

目录 一、Flume概述1.1 Flume定义1.2 Flume基础架构 二、Flume安装部署 一、Flume概述 1.1 Flume定义 Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统。Flume基于流式架构,灵活简单。 1.2 Flume基础…

Nebula Graph-03-NebulaGraph Studio-可视化web工具安装和使用

前言 如果未安装NebulaGraph,可以去看Nebula Graph-01-Nebula Graph简介和安装以及客户端连接 NebulaGraph Studio-可视化web工具安装 1:什么是 NebulaGraph Studio NebulaGraph Studio(简称 Studio)是一款可以通过 Web 访问的…

一篇文章教会你如何用 Axure 画原型图

原型图对于做出更好的 UI 设计决策非常重要。然而,选择合适的原型工具并不容易。我们需要仔细考虑成本、功能、与其他设计工具的集成、学习曲线、协作功能和用户测试方法,本文将分析 Axure 的原型设计工具。 1、为何使用 Axure 绘制原型图? …

【喜讯】同邦集团正式成为广州数据交易所会员!高效开展数据管理。

近日,同邦信息科技顺利通过广州数据交易所数商会员资格审查,正式加入广州数据交易所数商生态。 据悉,2022年9月,广州数据交易所正式挂牌成立。广州数据交易所采用“一所多基地多平台”的体系架构进行运营,探索在条件成…

CSA发布| 科技创新和云计算趋势中的网络安全因素

关注国际云安全联盟公众号,回复关键词 “云安全”,即可获取报告完整版 随着云计算的高速发展,如何在云环境中保障数据和应用的安全性日益成为企业共同的关注点,企业也正在考虑多云和混合云策略。云原生技术如容器、微服务和无服务…

Docker 中 Nginx 反向代理

本文主角:Nginx Proxy Manager 。 使用docker安装Nginx Proxy Manager。 1、找到C:\Windows\System32\drivers\etc下的hosts文件,添加 “域名 IP"即可。 使用vscode编辑文件,保存时会提示用管理员权限保存即可。 2、Nginx Proxy Mana…

jupyter | jupyter C++开发环境构建

搭建环境 按照 https://root.cern.ch/cling-build-instructions 官网的提示,手动编译Cling编译器,分别检查llvm,clang和cling: mkdir /path/to/cling cd /path/to/cling git clone http://root.cern.ch/git/llvm.gitcd llvm git checkout c…

金蝶云星空——单据附件上传

文章目录 概要技术要点代码实现小结 概要 单据附件上传 技术要点 单据附件上传金蝶是有提供标准的上传接口: http://[IP]/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.AttachmentUpLoad.common.kdsvc 参数说明 参数类型必填说明FileName字符是…

spring boot 输出日志保存到文件

spring boot 和 spring cloud 的模块,都已经引入了Logback作为其日志框架. 只需要配置 logback.xml 文件就可以实现保存日志到文件 文件内容为 <?xml version"1.0" encoding"UTF-8"?> <configuration scan"true" scanPeriod"6…

关于javascript数字精度丢失的解决办法

分析原因 众所周知&#xff0c;在JavaScript中计算两个十进制数的和&#xff0c;有时候会出现令人惊讶的结果&#xff0c;主要原因是计算机将数据存储为二进制所引起的&#xff0c;所以这并不是javascript存在的缺陷&#xff0c;而在其他语言中也有类似的问题。 例如下面的例子…

2024-03-20 作业

作业要求&#xff1a; 1> 创建一个工人信息库&#xff0c;包含工号&#xff08;主键&#xff09;、姓名、年龄、薪资。 2> 添加三条工人信息&#xff08;可以完整信息&#xff0c;也可以非完整信息&#xff09; 3> 修改某一个工人的薪资&#xff08;确定的一个&#x…

python毕业设计基于flask应急救援调度系统django

此系统设计主要采用的是python语言来进行开发&#xff0c;采用flask框架技术&#xff0c;框架分为三层&#xff0c;分别是控制层Controller&#xff0c;业务处理层Service&#xff0c;持久层dao&#xff0c;能够采用多层次管理开发&#xff0c;对于各个模块设计制作有一定的安全…

Git进阶命令-reset

一、reset命令使用场景 有时候我们提交了一些错误的或者不完善的代码&#xff0c;需要回退到之前的某个稳定的版本,面对这种情况有两种解决方法: 解决方法1&#xff1a;修改错误内容&#xff0c;再次commit一次 解决方法2&#xff1a;使用git reset 命令撤销这一次错误的com…

Cinema 4D 2024 for mac/Win:开启三维动画与建模新纪元

在数字化时代&#xff0c;三维动画与建模已成为影视、游戏、广告等多个领域不可或缺的创作工具。而Cinema 4D&#xff0c;作为这一领域的佼佼者&#xff0c;始终以其卓越的性能和创新的功能引领着行业的发展。如今&#xff0c;Cinema 4D 2024的发布&#xff0c;更是为我们带来了…

浅谈RPC的理解

浅谈RPC的理解 前言RPC体系Dubbo架构最后 前言 本文中部分知识涉及Dubbo&#xff0c;需要对Dubbo有一定的理解&#xff0c;且对源码有一定了解 如果不了解&#xff0c;可以参考学习我之前的文章&#xff1a; 浅谈Spring整合Dubbo源码&#xff08;Service和Reference注解部分&am…

【极简无废话】open3d可视化torch、numpy点云

建议直接看文档&#xff0c;很多都代码老了&#xff0c;注意把代码版本调整到你使用的open3d的版本&#xff1a; https://www.open3d.org/docs/release/tutorial/visualization/visualization.html 请注意open3d应该已经不支持centos了&#xff01; 从其他格式转换成open3d…

桌面日程安排软件,笔记本电脑常用软件有哪些?

在如今快节奏的社会环境中&#xff0c;时间仿佛成了比金子还要珍贵的资源。我们每个人都像是一名指挥官&#xff0c;需调度好每一刻光阴&#xff0c;使其发挥最大效益。而在这场与时间的较量中&#xff0c;一款优秀的桌面日程安排软件就像您的私人助理&#xff0c;帮您精准规划…

[BT]BUUCTF刷题第3天(3.21)

第3天&#xff08;共3题&#xff09; Web [极客大挑战 2019]LoveSQL Payload&#xff1a;/check.php?username1 union select 1,(select group_concat(password) from l0ve1ysq1),3%23&password1 看到登录页面&#xff0c;先尝试万能密码&#xff1a; 用户名&#xff…

51单片机学习9 串口通讯

51单片机学习9 串口通讯 一、串口通讯简介UARTSTC89C51RC/RD的串口资源 二、51单片机串口介绍1. 内部结构2. 寄存器&#xff08;1&#xff09;串口控制寄存器SCON&#xff08;2&#xff09;电源控制寄存器PCON 3. 计算波特率4. 串口配置步骤 三、 开发示例1. 硬件电路2. 代码实…