Spring 中 HttpServletRequest 作为成员变量是安全的吗?

        在使用spring框架开发的时候,经常会在controller类中看到 HttpServletRequest 对象参数,一般我们都是直接使用,但是它是何时、怎么注入到 spring 容器的呢 ?另外以成员变量注入的 request 是线程安全的吗 ?

@Controller
public class SomeController {@Resourceprivate HttpServletRequest request1;@RequestMapping("/test")public String test2(HttpServletRequest request2) {System.out.println(request1.getQueryString());System.out.println(request2.getQueryString());return "";}}

 1、request 成员变量是否线程安全 ?

       先说结论:注入request这个成员变量是线程安全的,来看下 spring 是如何做到的,先 debug 看下两种做法真实注入类的区别

      可以看出成员变量注入的是代理对象AutowireUtils.ObjectFactoryDelegatingInvocationHandler ,而作为方法参数注入的就是我们一般使用的Request对象,先看下 AutowireUtils 的内部类ObjectFactoryDelegatingInvocationHandler

/*** Reflective InvocationHandler for lazy access to the current target object.*/
@SuppressWarnings("serial")
private static class ObjectFactoryDelegatingInvocationHandler implements InvocationHandler, Serializable {private final ObjectFactory<?> objectFactory;public ObjectFactoryDelegatingInvocationHandler(ObjectFactory<?> objectFactory) {this.objectFactory = objectFactory;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String methodName = method.getName();if (methodName.equals("equals")) {// Only consider equal when proxies are identical.return (proxy == args[0]);} else if (methodName.equals("hashCode")) {// Use hashCode of proxy.return System.identityHashCode(proxy);} else if (methodName.equals("toString")) {return this.objectFactory.toString();}try {return method.invoke(this.objectFactory.getObject(), args);}catch (InvocationTargetException ex) {throw ex.getTargetException();}}
}   

        当代理对象的方法被调用时,除去少数几个方法,大部分的情况都是通过this.objectFactory.getObject() 获取被代理对象,再调用被代理对象的相应方法

        进一步 debug,终于看到了熟悉的Request类,可以看到它是从 requestAttributesHolder 中取到的,那么requestAttributesHolder又是什么?

        RequestContextHolder的ThreadLocal成员变量就是实现的关键所在,它存放了每个线程对应的Request对象,因此在@Controller中调用作为成员变量注入的代理类的方法时,最终可以取到当前线程相对应的Request对象,并调用Request对应的方法,这样@Controller中的成员变量不需要重复注入(它一直都是最初bean初始化时注入的代理类),也避免了线程不安全的问题。

2、spring是何时将Request放入这个ThreadLocal之中的 ?      

        同样先说结论:在 Springmvc 的 dispatcherServlet 的父类 FrameworkServlet 里完成的,分析代码实现

        所有的请求调用到 Servlet 的doGet、dePost 时,最终都会通过 processRequest(request, response) 进行处理

        processRequest 方法在调用了 initContextHolders(request, localeContext, requestAttributes) 时会将Request放入ThreadLocal,方便后续线程安全的获取

3、总结

        1、在bean中注入成员变量 HttpServletRequest 时,实际注入的是 spring 框架生成的代理对象 ObjectFactoryDelegatingInvocationHandler 的实例。在我们实际调用这个成员变量的方法时,会调用 objectFactory 的 getObject() 对象对应的方法(objectFactory 是RequestObjectFactory 这个类的对象)

        2、RequestObjectFactory 的 getObject 方法是从RequestContextHolderthreadlocal 中去取值的。

        3、请求刚进入 springmvc 的 dispatcherServlet 时,会把 request 相关对象设置到RequestContextHolder 的 threadlocal 中去,方便后续线程安全的获取

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

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

相关文章

react umi/max 封装页签组件

1. models/tabs // 全局共享数据示例 import { useState } from react;const useUser () > {const [items, setItems] useState<any[]>([]); // 页签的全局Item数据const [key, setKey] useState<string>(/home); // 页签的高亮Keyreturn {items,setItems…

【协议】HTTP、HTTPS和HTTP2.0学习总结

1. TCP/IP四层协议 记得大学学网络课程的时候&#xff0c;学的都是OSI/RM七层协议&#xff0c;应用层 -> 表示层 -> 会话层 -> 传输层->网络层->数据链路层->物理层&#xff0c;当时学的时候&#xff0c;感觉太抽象了&#xff0c;学得个一知半解。大脑在接收…

Unity3D和three.js的比较

一、Unity3D和three.js简介 Unity3D是一款跨平台的游戏引擎,可以用于开发2D和3D游戏。它提供了一个可视化的开发环境,包含了强大的编辑器和工具,使开发者可以方便地创建游戏场景、添加物体、设置物理效果、编写脚本等。Unity3D支持多种平台,包括PC、移动设备、主机等,可以…

新版AndroidStudio配置maven阿里云镜像

project下的build.gradle&#xff1a; // Top-level build file where you can add configuration options common to all sub-projects/modules. // 注意jdk版本需要17以上&#xff0c;因为8.1.3的gradle需要jdk17以上 //plugins { // id com.android.application version…

解析exe文件

概述&#xff1a;上次用java生成exe文件。那如何解析exe文件呢&#xff1f;0.0 首先我们要了解exe文件里面有什么。用360压缩解压一下。 .data&#xff1a; 存储程序中的初始化的全局和静态变量。在程序运行之前&#xff0c;这些变量会被赋予特定的初始值。 .pdata (Procedu…

销售方法用得好,业绩蹭蹭蹭!

新零售模式是随着科技的发展而崭露头角的零售业态&#xff0c;它融合了传统零售与先进技术&#xff0c;为消费者带来了更便捷、智能的购物体验。 其中&#xff0c;自动售货机作为新零售的一种代表形式&#xff0c;通过高度自动化和数字化的手段&#xff0c;为消费者提供更加便利…

【RT-DETR有效改进】移动设备网络ShuffleNetV1(超轻量化网络主干)

前言 大家好&#xff0c;这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进&#xff0c;内容持续更新&#xff0c;每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本&#xff0c;同时修改内容也支持ResNet32、ResNet101和PP…

计算机网络-计算机网络的概念 功能 发展阶段 组成 分类

文章目录 计算机网络的概念 功能 发展阶段总览计算机网络的概念计算机网络的功能计算机网络的发展计算机网络的发展-第一阶段计算机网络的发展-第二阶段-第三阶段计算机网络的发展-第三阶段-多层次ISP结构 小结 计算机网络的组成与分类计算机网络的组成计算机网络的分类小结 计…

【史上最全】前端页面深入浅出浏览器渲染原理

前言 浏览器的核心组件&#xff0c;即通常所说的浏览器内核&#xff0c;是支撑整个浏览器运行的关键性底层软件架构&#xff0c;它由两个关键组成部分构成&#xff1a;一个是负责网页内容解析和渲染的渲染引擎&#xff0c;另一个则是用于执行JavaScript代码的JS引擎。各浏览器厂…

双向搜索的理解和板子

"互相奔赴&#xff0c;各司其职。“ ——双向搜索 双搜的要求&#xff1a; 当我们发现&#xff0c;要从一种状态开始&#xff0c;经过很多次操作&#xff0c;来得到一种给定的状态。 这时候&#xff0c;我们就可以考虑用双向搜索。 从起点和终点开始搜。当二者相遇&…

【React】组件性能优化、高阶组件

文章目录 React性能优化SCUReact更新机制keys的优化render函数被调用shouldComponentUpdatePureComponentshallowEqual方法高阶组件memo 获取DOM方式refs如何使用refref的类型 受控和非受控组件认识受控组件非受控组件 React的高阶组件认识高阶函数高阶组件的定义应用一 – pro…

如何用Python进行数据分析(保姆级教程)

有小伙伴在学Python新手教程的时候说学Python比较复杂的地方就是资料太多了&#xff0c;比较复杂。 很多网上的资料都是从语法教起的&#xff0c;花了很多时间还是云里雾里&#xff0c;摸不清方向。今天就给大家来捋一捋思路&#xff01;帮助大家提高学习效率&#xff01; Pyt…

mysql 自动生成随机数

在MySQL中&#xff0c;生成随机数可以使用RAND()函数。以下是一些基本用法&#xff1a; 1. **生成0到1之间的随机浮点数**&#xff1a; sql SELECT RAND(); 2. **生成指定范围内的随机整数**&#xff08;例如&#xff0c;生成1到100之间的随机整数&#xff09;&…

QT网络通信-TCP、UDP通信

时间记录&#xff1a;2024/1/17 pro文件添加模块network 一、TCP服务端 &#xff08;1&#xff09;创建TCP服务器对象QTcpServer &#xff08;2&#xff09;为QTcpServer对象的newConnection信号绑定槽&#xff0c;用来监听TCP客户端的新连接&#xff0c;有新的客户端连接便会…

ArrayList 可以添加 null 值吗?

如果你现在需要准备面试&#xff0c;可以关注我的公众号&#xff1a;”Tom聊架构“&#xff0c;回复暗号&#xff1a;”578“&#xff0c;领取一份我整理的50W字面试宝典&#xff0c;可以帮助你提高80%的面试通过率&#xff0c;价值很高&#xff01;&#xff01; ArrayList 中可…

Markdown 类图绘制详解

✍️作者简介&#xff1a;小北编程&#xff08;专注于HarmonyOS、Android、Java、Web、TCP/IP等技术方向&#xff09; &#x1f433;博客主页&#xff1a; 开源中国、稀土掘金、51cto博客、博客园、知乎、简书、慕课网、CSDN &#x1f514;如果文章对您有一定的帮助请&#x1f…

水电站智能监测泄洪预警系统介绍

一、背景 近年来由于危险河道管理措施不到位&#xff0c;调峰电站泄水风险长期存在&#xff0c;信息通报制度缺失以及民众安全警觉性不高等因素导致的水电站在泄洪时冲走下游河道游客以及人民财产的事故频发。 二、系统介绍 水电站智能监测泄洪预警系统是一种集成了物联网、云…

Java SE入门及基础(20)

目录 类和对象 1. 类的由来 2. 如何定义类 语法 示例 3. 类图 4. 类和对象的关系 解释说明 语法 示例 示例 结论 Java SE文章参考:Java SE入门及基础知识合集-CSDN博客 类和对象 1. 类的由来 人们在日常生活中&#xff0c;经常会将具有相同特征或者相同行为的事…

ElasticSearch的常用增删改查DSL和代码

es增删改查常用语法 我们日常开发中&#xff0c;操作数据库写sql倒是不可能忘记&#xff0c;但是操作es的dsl语句有时候很容易忘记&#xff0c;特地记录一下方便查找。 DSL语句 1、创建索引 -- 创建索引 PUT /my_index {"mappings": {"properties": {&…

AWS Cognito 实战指南

Amazon Cognito 是 AWS 提供的一项身份验证和访问控制服务,适用于构建安全的用户身份验证和访问控制功能。本指南将介绍如何使用 AWS Cognito 创建用户池和身份池,并在 Java 、 Python 和JavaScript应用程序中实现用户注册和登录功能。 步骤 1: 创建用户池 登录 AWS 控制台。…