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

这篇具有很好参考价值的文章主要介绍了Spring 中 HttpServletRequest 作为成员变量是安全的吗?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

@Controller
public class SomeController {
    
    @Resource
    private 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 看下两种做法真实注入类的区别

Spring 中 HttpServletRequest 作为成员变量是安全的吗?,Spring,spring,java,后端

      可以看出成员变量注入的是代理对象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;
    }

    @Override
    public 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() 获取被代理对象,再调用被代理对象的相应方法

Spring 中 HttpServletRequest 作为成员变量是安全的吗?,Spring,spring,java,后端

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

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

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

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

Spring 中 HttpServletRequest 作为成员变量是安全的吗?,Spring,spring,java,后端

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

Spring 中 HttpServletRequest 作为成员变量是安全的吗?,Spring,spring,java,后端

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

Spring 中 HttpServletRequest 作为成员变量是安全的吗?,Spring,spring,java,后端

3、总结

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

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

        3、请求刚进入 springmvc 的 dispatcherServlet 时,会把 request 相关对象设置到RequestContextHolder 的 threadlocal 中去,方便后续线程安全的获取文章来源地址https://www.toymoban.com/news/detail-801049.html

到了这里,关于Spring 中 HttpServletRequest 作为成员变量是安全的吗?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 你知道Spring是如何整合MyBatis的吗?

    Spring 和 MyBatis 是两个在 Java 开发中广泛应用的优秀框架。Spring 提供了强大的容器和一系列的特性,可以方便地进行依赖注入、AOP 编程等操作。MyBatis 是一个轻量级的持久层框架,它提供了灵活的 SQL 映射和数据库访问功能。在实际项目中,将 Spring 和 MyBatis 整合在一起使用,

    2024年02月06日
    浏览(28)
  • Spring BOOT:javax.servlet.http.HttpServletRequest异常

     Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.IllegalStateException: No primary or single unique constructor found for interface javax.servlet.http.HttpServletRequest] with root cause                  用SpringBoot做验证码的时候,需要用HttpServletReque

    2024年02月11日
    浏览(33)
  • 你知道Spring中BeanFactoryPostProcessors是如何执行的吗?

    Spring中的BeanFactoryPostProcessor是在Spring容器实例化Bean之后,初始化之前执行的一个扩展机制。它允许开发者在Bean的实例化和初始化之前对BeanDefinition进行修改和处理,从而对Bean的创建过程进行干预和定制化。 BeanFactoryPostProcessor接口定义了一个方法:postProcessBeanFactory( Configura

    2024年02月05日
    浏览(39)
  • spring boot3.x集成swagger出现Type javax.servlet.http.HttpServletRequest not present

    spring boot3.x版本依赖于jakarta依赖包,但是swagger依赖底层应用的javax依赖包,所以只要一启动就会报错。 移除 swagger2依赖 添加 新依赖 @Api(tags = “”) → @Tag(name = “”) @ApiModel(value=“”, description=“”) → @Schema(name=“”, description=“”) @ApiModelProperty(value = “”, required = true) →

    2024年02月09日
    浏览(30)
  • Spring Cloud集成Nacos作为配置中心

    Nacos的安装与配置 Spring Cloud集成Nacos作为注册中心 LoadBalacer集成Nacos实现负载均衡 常见的负载均衡策略分析 Spring Cloud集成Dubbo实现RPC调用 前面我们已经介绍了 Nacos 的安装与配置, Spring Cloud 集成 Nacos 作为服务的注册中心,集成 Nacos 实现服务的负载均衡和一些常见的负载均衡

    2024年02月15日
    浏览(36)
  • Spring Cloud Gateway集成Nacos作为注册中心和配置中心

    本篇文章将介绍Spring Cloud Alibaba体系下Spring Cloud Gateway的搭建,服务注册中心和分布式配置中心使用Nacos,后续将会持续更新,介绍集成Sentinel,如何做日志链路追踪,如何做全链路灰度发布设计,以及Spring Cloud Gateway的扩展等。 ​ Spring Boot,Spring Cloud,Discovery,Config等基础依

    2024年02月11日
    浏览(32)
  • Spring Boot 别再用 Date 作为入参了,LocalDateTime、LocalDate 真香!

    作者:TinyThing 链接:https://www.jianshu.com/p/b52db905f020 项目中使用LocalDateTime系列作为dto中时间的类型,但是spring收到参数后总报错,为了全局配置时间类型转换,尝试了如下3中方法。 注:本文基于Springboot2.0测试,如果无法生效可能是spring版本较低导致的。PS:如果你的Controll

    2024年02月11日
    浏览(29)
  • Spring Cloud 使用 k8s 作为注册中心 开发环境 和 生产环境

    因为 k8s 本身就有拥有注册中心,和配置中心的功能。如果还是用 Nacos、Eureka、Consul 之类的注册中心组件,就有点冗余了。当然这些组件还是可以继续用的。 所以,本教程,教授 Spring Cloud 使用 k8s 的注册中心。在开发环境和生产环境 的教程! 下面以一个最简单的 服务消费

    2024年02月15日
    浏览(38)
  • 【Spring boot 读取系统环境变量】

    Spring boot 读取系统环境变量 凡是被 Spring 管理的类,实现接口 EnvironmentAware 重写方法 setEnvironment 可以在工程启动时,获取到 系统环境变量和 application 配置文件中的变量。 com.hpit.sb.environment.MyEnvironment import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Value; impor

    2024年02月06日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包