转:Spring Boot 获取 HttpServletRequest 的方法

转自:

Spring Boot 获取 HttpServletRequest 的方法 - 简书本文介绍 Spring Boot 2 获取 HttpServletRequest 的方法。 目录 概述 方法Controller 方法参数属性自动注入手动方法调用借助 @Mo...https://www.jianshu.com/p/b7a7d66c4ef2


本文介绍 Spring Boot 2 获取 HttpServletRequest 的方法。


目录

  • 概述
  • 方法
    • Controller 方法参数
    • 属性自动注入
    • 手动方法调用
    • 借助 @ModelAttribute 注解
  • 总结

概述

借助 Spring MVC 开发 Web 应用的过程中经常需要使用 HttpServletRequest 对象获取 HTTP 请求相关的信息,如:客户端 IP、HTTP Header 中的属性等。
使用 HttpServletRequest 对象的场景大体分为两类:

  • 在 Spring 注入的 Bean 中使用;
  • 在非 Spring 注入的 Bean 中使用,如普通的 Java 对象或类的静态方法。

方法

【1】Controller 方法参数引入 HttpServletRequest

原理:
在 Controller 方法开始处理请求时,Spring 会将 HttpServletRequest 对象自动赋值到方法参数中。除 HttpServletRequest 对象外,还有很多其它参数可以通过此方法获取,参考:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-methods

代码示例:

@GetMapping("/method1")
public String method1(HttpServletRequest request) {System.out.println("Request URI: " + request.getRequestURI());return "Invoke HttpServletRequest by method param.";
}

线程安全性分析:
HttpServletRequest 对象作为方法参数,相当于局部变量,是 线程安全 的。

缺点:

  • 代码冗余,每个 Controller 方法中都要有 HttpServletRequest request 参数;
  • HttpServletRequest 对象的获取必须从 Controller 开始,如果使用 HttpServletRequest 对象的地方在函数调用层级比较深的地方,那么整个函数调用链上的所有方法都要有 HttpServletRequest request 参数。实际上在请求处理的全过程中,HttpServletRequest 对象始终存在,相当于线程内部的一个全局变量。

【2】HttpServletRequest 属性自动注入

代码示例:

@Autowired
private HttpServletRequest autowiredRequest;@GetMapping("/method2")
public String method2() {System.out.println("Request URI: " + autowiredRequest.getRequestURI());return "Invoke HttpServletRequest by @Autowired.";
}

线程安全性分析:
使用 @Autowired 注解时,Spring 实际注入的并非 HttpServletRequest 对象,而是一个代理 proxy(代理实现参考 AutowireUtils.ObjectFactoryDelegatingInvocationHandler),当方法中需要使用 HttpServletRequest 对象时通过此代理获取,所以虽然 Controller 是个单例类,但通过此方法使用 HttpServletRequest 对象是 线程安全 的。

优点:

  • 不局限于 Controller 中,可以在通过 @Component@Service@Repository 注解注入的其它 Bean 中使用;
  • 注入的对象不局限于 HttpServletRequest 对象,还可以注入其它 scoperequestsession 的对象,如 HttpServletResponse、HttpSession 等,并保证线程安全;
  • 相比于【Controller 方法参数】方法,减少了代码冗余,只需要在需要使用 HttpServletRequest 对象的方法所属 Bean 中注入。

缺点:

  • 如果存在很多 Bean 需要使用 HttpServletRequest 对象,则每个 Bean 都要维护一个使用 @Autowired 注解注入的 HttpServletRequest request 属性,也存在一定代码冗余,可以定义一个公共父类维护这些自动注入的属性,但是继承本身也存在一定问题。

【3】手动方法调用

代码示例:

@GetMapping("/method3")
public String method3() {HttpServletRequest request =((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();System.out.println("Request URI: " + request.getRequestURI());return "Invoke HttpServletRequest by ServletRequestAttributes.";
}

线程安全性分析:
与【属性自动注入】线程安全性分析一致,属于 线程安全

优点:

  • 可以在非 Spring 注入的 Bean 中使用,如普通 Java 对象或静态方法。

缺点:

  • 代码比较繁琐。

【4】借助 @ModelAttribute 注解

代码示例:

@Autowired
private HttpServletRequest bindRequest;@ModelAttribute
public void bindRequest(HttpServletRequest request) {this.bindRequest = request;
}@GetMapping("/method4")
public String method4() {System.out.println("Request URI: " + bindRequest.getRequestURI());return "Invoke HttpServletRequest by @ModelAttribute.";
}

线程安全性分析:
@ModelAttribute 注解修饰 Controller 方法时,作用是在 Controller 中每个处理请求的方法执行前执行,而 Controller 是单例,所以当同时处理多个请求时 HttpServletRequest 对象属性可能会被覆盖,所以是 线程不安全 的!


总结

全量代码:

package tutorial.spring.boot.mvc.controller;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;@RestController
public class DemoController {@Autowiredprivate HttpServletRequest autowiredRequest;@Autowiredprivate HttpServletRequest bindRequest;@GetMapping("/method1")public String method1(HttpServletRequest request) {System.out.println("Request URI: " + request.getRequestURI());return "Invoke HttpServletRequest by method param.";}@GetMapping("/method2")public String method2() {System.out.println("Request URI: " + autowiredRequest.getRequestURI());return "Invoke HttpServletRequest by @Autowired.";}@GetMapping("/method3")public String method3() {HttpServletRequest request =((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();System.out.println("Request URI: " + request.getRequestURI());return "Invoke HttpServletRequest by ServletRequestAttributes.";}@ModelAttributepublic void bindRequest(HttpServletRequest request) {this.bindRequest = request;}@GetMapping("/method4")public String method4() {System.out.println("Request URI: " + bindRequest.getRequestURI());return "Invoke HttpServletRequest by @ModelAttribute.";}
}


 

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

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

相关文章

前端面试常考系列四

转载自 前端面试常考系列四 一、CSS盒子模型有哪些用处 css中的盒子模型是为了理解divcss模型的定位功能,它利用盒子模型这样的布局方式代替了传统的表格布局方式。盒子模型是在学习divcss布局方式中必须要学习的一个模型,通过这个模型可以明白网页中di…

python线性加权模型_局部加权之线性回归(1) - Python实现

1 #局部加权线性回归2 #交叉验证计算泛化误差最小点345 importnumpy6 from matplotlib importpyplot as plt789 #待拟合不含噪声之目标函数10 deforiFunc(x):11 y numpy.exp(-x) * numpy.sin(10*x)12 returny13 #待拟合包含噪声之目标函数14 def traFunc(x, sigma0.03):15 y …

3分钟看完 Day2 Keynote

hey~ M姐又给大家带来了满满惊喜的 Build2016 Day 2 Keynote 干货汇总了。 如果你连昨天的都还不知道,那真心就 out 了。如果说信仰在昨天充值爆棚,今天就要充值信仰到掀翻房顶的节奏了!!! 红衣主教今天妥妥变身成为新…

latex 数学公式_技能分享——LaTeX篇I

公众号文章系列二——“小袁技能分享”上线啦,第一篇推文我们聊一聊LaTeX(音译 “拉泰赫”)Question 1什么是LaTeX?要解释LaTeX是什么,我们先要了解另外一个事物:TeX。1968年,美国著名计算机科学家、现代计算机科学的先…

转:springboot servlet使用配置

转自: springboot servlet使用配置_奔跑的蜗牛的博客-CSDN博客在spring boot中添加自己的Servlet有两种方法,代码注册Servlet和注解自动注册(Filter和Listener也是如此)。 一、代码注册通过ServletRegistrationBean 获得控制。 也…

前端面试常考系列五

转载自 前端面试常考五 一、DIV元素是什么 DIV元素是用来为HTML文档内大块(block-level)的内容提供结构和背景的元素。DIV的起始标签和结束标签之间的所有内容都是用来构成这个块的,其中所包含元素的特性由DIV标签的属性来控制,或…

从业十余年谈谈对dotnet看法与坚持

前言 园子经常在讨论关于.Net发展的问题,我也这些年在工作乃至创业过程中使用.Net碰到的一些问题和看法。个人擅长的技术面,C/C/MFC/STL、ASM、JAVA、VB、Javascript/Typescript、C#/WebForm/MVC、Android/MonoDroid,Linux/Windows,还有没有可…

kali安装python3.7_Debian服务器之安装Python3.7

1、系统环境介绍1.1 系统版本debian-9.6.0-amd64-netinst1.2 系统内核Linux lnnkee 4.9.0-8-amd64 #1 SMP Debian 4.9.130-2 (2018-10-27) x86_64 GNU/Linux2、下载安装包https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tar.xz3、配置安装环境apt install libffi-dev …

org.apache.kafka.common.errors.TimeoutException: Topic not present in metadata 解决方法

【README】 本文po出了 topic not present in metadata 的解决方法; 很多博文说是 因为 jackson-databind 没有引入,但是我重新引入后,还是没有解决问题; 最后,原因在于我要发送消息的分区,topic 没有对…

前端面试常考系列六

转载自 前端面试常考系列六 一、为什么重置浏览器默认样式,如何重置 每种浏览器都有一套默认的样式表,即user agent stylesheet,网页在没有指定的样式时,按浏览器内置的样式表来渲染。这是合理的,像word中也有一些预留…

Microsoft将Linux带至桌面操作系统

在今天的Build大会上Microsoft宣布:今年的Windows 10年度更新将使得Windows 10系统能够无缝运行Linux二进制程序。多年来,专家与开发者都在猜测,Linux如何以及何时才能在普通PC用户的桌面系统中更加流行。从今天的新闻来看,似乎Mi…

kafka控制器,复制与存储小结

【README】 1,本文主要总结kafka复制,存储细节;2,本文的kafka集群版本是3.0.0, 有3个broker,分别是 centos201, centos202, centos203 对应的brokerid为 1, 2, 3 ;【1】kafka内部原…

python开发stm32软件_ADB+Python+STM32 实现 微信跳一跳辅助

说明:安卓手机开启USB调试模式,具体如何开启,百度自己手机即可安装ADB工具安装python2.7步骤:1、安装adb工具下载地址:https://download.csdn.net/download/qq_29769263/10420731下载后解压到便于记忆的地方即可,以解压…

不装mono,你的.NET程序照样可以在Linux上运行

让.NET应用程序在linux上运行,目前通用的做法就是在Linux上安装mono,然后通过”mono your.exe“命令运行这个程序。 这种运行.net程序的办法有两个弱点,一个是需要客户机安装mono,二个是 ”mono xx.exe“ 这种命令行总让人感到有点…

JAVA面试常考系列一

转载自 JAVA面试常考系列一 题目一 什么是Java虚拟机?为什么Java被称为平台无关的编程语言? java虚拟机是一个可以执行字节码文件(.class)的虚拟机进程。 为什么java与平台无关呢?因为java源程序(.java&…

转:运维监控系统-监控项及指标的梳理

转自: 运维监控系统-监控项及指标的梳理_程序员杂谈-CSDN博客_运维监控指标综合监控功能工具 综合监控工具完成对被管对象的集中监控、集中维护和集中管理,被管对象包括网络设备、服务器、PC设备、数据库、中间件、存储、备份、安全设备、应用系统等。工…

圆心角 圆弧上点坐标_数控加工中心CNC的G02/G03圆弧指令的I、J、与R的区别

G02:顺(CW)圆弧插补G03:逆(CCW)圆弧插补根据所选择的X、Y平面,指令格式如下两种:G17 G02/G03 X_ Y_ I_ J_ F_;G17 G02/G03 X_ Y_ R_ F_;定义方式:依右手坐标系统&#xf…

AutoMapper 使用实践

一. 使用意图 常常在开发过程中,碰到一个实体上的属性值,要赋值给另外一个相类似实体属性时,且属性有很多的情况。一般不利用工具的话,就要实例化被赋值实体B,然后再将实体A的字段一个个赋值给B的属性,单…

kafka可靠数据传递

【README】 本文阐述了kafka可靠消息传递机制; 本文部分内容总结于《kafka权威指南》(一本好书,墙裂推荐),再加上自己的理解; 【1】可靠性保证 1,在讨论可靠性时,一般使用保证这个…

JAVA面试常考系列二

转载自 JAVA面试常考系列二 题目一 解释一下线程和进程 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上…