转: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 对象,还可以注入其它
scope
为request
或session
的对象,如 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.";}
}
转:Spring Boot 获取 HttpServletRequest 的方法相关推荐
- Spring boot 获取本机的IP地址mac地址以及电脑名称!
Spring boot 获取本机的IP地址mac地址以及电脑名称! package com.example.demo;import java.net.InetAddress;import java.n ...
- spring boot 获取cookie信息
spring boot 获取cookie信息 先创建一个cookie @RequestMapping(value = "/setCookies",method = RequestM ...
- Spring boot异常统一处理方法:@ControllerAdvice注解的使用、全局异常捕获、自定义异常捕获
Spring boot异常统一处理方法:@ControllerAdvice注解的使用.全局异常捕获.自定义异常捕获 参考文章: (1)Spring boot异常统一处理方法:@ControllerAd ...
- Spring Boot 启动执行某个方法的三种实现方式
Spring Boot 启动执行某个方法的三种实现方式 Spring Boot 启动执行某个方法的三种实现方式 第一种方式 @PostConstruct 注解解释 具体实现 第二种方式 Applica ...
- Spring Boot 定义接口的方法是否可以声明为 private?
我们在 Controller 中定义接口的时候,一般都是像下面这样: @GetMapping("/01") public String hello(Map<String,Ob ...
- Web笔记-session盗用安全问题(Spring Boot获取所有session及提高安全性)
此处本人的过滤代码如下: 仅仅是判断了这个session有没有被记录,有没有attribute! 某些IT论坛,就是这样的,通过session,就可以进行批量帐号操作,发取http协议. 这里演示如下 ...
- Spring Boot 获取 Bean 的 3 种方式!还有谁不会?
作者 | chilx 来源 | https://blog.csdn.net/showchi/article/details/97005720 注意:调用者要被spring管理 方式一 注解@PostC ...
- C++|Java混合实验-Spring Boot获取客户端操作系统,浏览器,Ip等信息,Qt端展示
目录 概述 演示 源码 概述 这里用Spring Boot控制"/"和"index.html"请求,获取客户端http的信息: Qt端使用QML和C++混合编程 ...
- spring boot获取spring容器中的bean对象
我们知道如果我们要在一个类使用 spring提供的bean对象,我们需要把这个类注入到spring容器中,交给spring容器进行管理,但是在实际当中,我们往往会碰到在一个普通的Java类中,想直接 ...
最新文章
- Zend Guard 各版本下载【破解方法】
- STM32开发 -- HardFault_Handler处理
- 【Spring 数据访问终篇】Spring + Hibernate + Mysql
- Action Service Dao三层的功能划分
- 建立和操作 JDOM 文档
- jenkins maven没有使用全局设置文件地址_Jenkins手把手图文教程「基于Jenkins 2.164.1」...
- 点击home键_iPhone小技巧:无Home键iPhone11如何强制重启?
- java技术秘籍 转摘
- 统计面要素中点要素的个数.
- 拓端tecdat|Python贝叶斯推断Metropolis-Hastings(M-H)MCMC采样算法的实现
- PHP二维数组按照指定的字段排序的函数
- 新浪微博:“救命的黄金稻草”
- 安全教育平台账号后四位_2020中小学国家安全教育专题活动入口官网:学校安全教育平台...
- JAVA 实现《warcraft java版》游戏
- Matlab画平滑曲线的两种方法( 拟合或插值后再用plot即可)
- 【Python学习笔记】复习sql主键外键索引
- 图灵大会 | 新观点:AI盛世,其实我们离得还很远
- css中pt单位,css中字体单位px,pt,em,百分比之间的区别和用法
- MySQL更新时间的时候生成随机时间
- 2020 Python中文社区热门文章 Top 10
热门文章
- AtCoder Beginner Contest 194 F - Digits Paradise in Hexadecimal 数位dp
- 快速沃尔什变换:从入门到背板(含推导过程)
- CF1063A Oh Those Palindromes
- HDU 5510 Bazinga
- [ZJOI2014] 星系调查(树上差分 + 数学推式子)
- 2021CSP:游记
- 不止代码:友好城市(动态规划)
- P5825-排列计数【EGF,NTT】
- P3041-[USACO12JAN]Video Game G【AC自动机,dp】
- U102488-傻叉题【dp】