一、概述

在使用Spring MVC开发Web系统时,经常需要在处理请求时使用request对象,比如获取客户端IP地址、请求的URL、header中的属性(如cookie、授权信息)、body中的数据等。由于在Spring MVC中,处理请求的Controller、Service等对象都是单例的,因此获取request对象时最需要注意的问题,便是request对象是否是线程安全的:当有大量并发请求时,能否保证不同请求/线程中使用不同的request对象。

这里还有一个问题需要注意:前面所说的“在处理请求时”使用request对象,究竟是在哪里使用呢?考虑到获取request对象的方法有微小的不同,大体可以分为两类:

1、在Spring的Bean中使用request对象:既包括Controller、Service、Repository等MVC的Bean,也包括了Component等普通的Spring Bean。为了方便说明,后文中Spring中的Bean一律简称为Bean。

2、在非Bean中使用request对象:如普通的Java对象的方法中使用,或在类的静态方法中使用。

此外,本文讨论是围绕代表请求的request对象展开的,但所用方法同样适用于response对象、InputStream/Reader、OutputStream/ Writer等;其中InputStream/Reader可以读取请求中的数据,OutputStream/Writer可以向响应写入数据。

二、获取request方法

1、controller中加参数

该方法实现的原理是,在Controller方法开始处理请求时,Spring会将request对象赋值到方法参数中。除了request对象,可以通过这种方法获取的参数还有很多,比如response。Controller中获取request对象后,如果要在其他方法中(如service方法、工具类方法等)使用request对象,需要在调用这些方法时将request对象作为参数传入。

安全性:此时request对象是方法参数,相当于局部变量,毫无疑问是线程安全的

优缺点:(1)如果多个controller方法中都需要request对象,那么在每个方法中都需要添加一遍request参数,冗余太多

(2)request对象的获取只能从controller开始,如果使用request对象的地方在函数调用层级比较深的地方,那么整个调用链上的所有方法都需要添加request参数。实际上,在整个请求处理的过程中,request对象是贯穿始终的;也就是说,除了定时器等特殊情况,request对象相当于线程内部的一个全局变量。而该方法,相当于将这个全局变量,传来传去。

2、自动注入方式

@Autowired

private HttpServletRequest request;

安全性:Controller的scope是singleton(单例),也就是说在整个web系统中,只有一个Controller;但是其中注入的request却是线程安全的。

优缺点:(1)注入不局限于Controller中:在方法1中,只能在Controller中加入request参数。而对于方法2,不仅可以在     Controller中注入,还可以在任何Bean中注入,包括Service、Repository及普通的Bean。

(2)注入的对象不限于request:除了注入request对象,该方法还可以注入其他scope为request或session的对象,如response对象、session对象等;并保证线程安全。

(3)减少代码冗余:只需要在需要request对象的Bean中注入request对象,便可以在该Bean的各个方法中使用,与方法1相比大大减少了代码冗余。

但是,该方法也会存在代码冗余。考虑这样的场景:web系统中有很多controller,每个controller中都会使用request对象(这种场景实际上非常频繁),这时就需要写很多次注入request的代码;如果还需要注入response,代码就更繁琐了。下面说明自动注入方法的改进方法,并分析其线程安全性及优缺点。

3、基类中自动注入,与方法2相比,将注入部分代码放入到了基类中。

优缺点:与方法2相比,避免了在不同的Controller中重复注入request;但是考虑到java只允许继承一个基类,所以如果Controller需要继承其他类时,该方法便不再好用。

无论是方法2和方法3,都只能在Bean中注入request;如果其他方法(如工具类中static方法)需要使用request对象,则需要在调用这些方法时将request参数传递进去。下面介绍的方法4,则可以直接在诸如工具类中的static方法中使用request对象(当然在各种Bean中也可以使用)。

4、手动调用

优缺点:优点:可以在非Bean中直接获取。缺点:如果使用的地方较多,代码非常繁琐;因此可以与其他方法配合使用

5、@ModelAttribute方法

分析:@ModelAttribute注解用在Controller中修饰方法时,其作用是Controller中的每个@RequestMapping方法执行前,该方法都会执行。因此在本例中,bindRequest()的作用是Controller中方法执行前为request对象赋值。虽然bindRequest()中的参数request本身是线程安全的,但由于Controller是单例的,request作为Controller的一个域,无法保证线程安全。

三、总结

综上所述,Controller中加参数(方法1)、自动注入(方法2和方法3)、手动调用(方法4)都是线程安全的,都可以用来获取request对象。如果系统中request对象使用较少,则使用哪种方式均可;如果使用较多,建议使用自动注入(方法2 和方法3)来减少代码冗余。如果需要在非Bean中使用request对象,既可以在上层调用时通过参数传入,也可以直接在方法中通过手动调用(方法4)获得。

Spring MVC中获取Request的方法及分析相关推荐

  1. spring MVC中获取request和response

    spring MVC中获取request和response: Java代码   HttpServletRequest request = ((ServletRequestAttributes) Req ...

  2. Spring MVC中获取当前项目的路径

    Spring MVC中获取当前项目的路径 在web.xml中加入以下内容 <!--获取项目路径--><context-param><param-name>webAp ...

  3. Spring中获取request的方法及其线程安全性分析

    在使用Spring MVC开发Web系统时,经常需要在处理请求时使用request对象,比如获取客户端ip地址.请求的url.header中的属性(如cookie.授权信息).body中的数据等.由于 ...

  4. Spring MVC中处理Request和Response的策略

    前沿技术早知道,弯道超车有希望 积累超车资本,从关注DD开始 作者:码农小胖哥, 图文编辑:xj 来源:https://mp.weixin.qq.com/s/3eFygsiVl8dC2nRy8_8n5 ...

  5. java在spring mvc中的图片接收与发送处理

    1.作为client发送和获取图片 1.1.发送图片 作为client时发送图片通常是通过from-data的multipart形式来发送的,这时我们就在模拟浏览器的form文件表单来提交请求,mul ...

  6. Spring 中获取 request 的几种方法,及其线程安全性分析

    概述 在使用Spring MVC开发Web系统时,经常需要在处理请求时使用request对象,比如获取客户端ip地址.请求的url.header中的属性(如cookie.授权信息).body中的数据等 ...

  7. SpringMvc4中获取request、response对象的方法

    springMVC4中获取request和response对象有以下两种简单易用的方法: 1.在control层获取 在control层中获取HttpServletRequest和HttpServle ...

  8. Spring 2.5:Spring MVC中的新特性

    转载说明:infoQ就是牛人多,看人家去年就把Spring2.5注视驱动的MVC写出来了,还是这么详细,我真是自叹不如,今天偶尔看到这篇文章非常认真的拜读了2遍,简直是茅厕顿开啊....\(^o^)/ ...

  9. spring mvc 异步_DeferredResult – Spring MVC中的异步处理

    spring mvc 异步 DeferredResult是一个可能尚未完成的计算的容器,它将在将来提供. Spring MVC使用它来表示异步计算,并利用Servlet 3.0 AsyncContex ...

最新文章

  1. This Gradle plugin requires a newer IDE able to request IDE model level 3.For Android Studio this
  2. 声音分析+android,声音分析仪Sound Analyzer-声音分析仪 Sound Analyzer2.1安卓版-蜻蜓手游网...
  3. c++获得总和S所需的最小硬币数量的函数(附完整源码)
  4. Go Timer使用方法
  5. Linux系统下,虚拟终端开启256色_虚拟终端类型xterm开启256色
  6. mac html编辑器 免费,Mac下 10 款最棒的编辑器
  7. 富士康将把部分iPad和MacBook生产线从中国转移到越南
  8. Paravirtualization (半虚拟化PV) - Xen
  9. “意念打字”终成真!准确率超 99%,还登上了《Nature》封面!
  10. web基础、tomcat搭建
  11. 获取软件的apk包名、查看手机设备名称等
  12. pycharm如何添加桌面图标_桌面图标全变成pycharm了怎么办?
  13. jmete-jp@gc - Throughput Shaping Timer的使用
  14. 英国一名28岁女子晋升曾祖母
  15. 如何提升程序员的非技术才能
  16. 微信小程序使用mock.js
  17. 为什么“总结经验”反而把你带进沟里?
  18. TMS320C6748开发视频教程笔记 第6章 GEL 文件
  19. 华为三星非洲智能手机大战 低价为王
  20. 仙剑奇侠传三Unity开源实现

热门文章

  1. 后端小白程序员的Vue学习笔记
  2. matlab如何输出总位移,加速度转换成位移的matlab代码及说明
  3. C语言输出所有的水仙花数
  4. html的访问路径,对路径的访问被拒绝
  5. PCA降维算法总结以及matlab实现PCA(个人的一点理解)
  6. [附源码]SSM计算机毕业设计个人网站JAVA
  7. 武汉大专计算机专业分数线,武汉专科大学有哪些?武汉专科大学排名及分数线...
  8. 华为通用软件开发实习生面试题
  9. Virtual host / experienced an error on node rabbit@wohu-rabbit and may be inaccessible
  10. 项目之显示问题和回答问题(12)