转自:

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.";}
}

转:Spring Boot 获取 HttpServletRequest 的方法相关推荐

  1. Spring boot 获取本机的IP地址mac地址以及电脑名称!

    Spring boot 获取本机的IP地址mac地址以及电脑名称! package com.example.demo;import java.net.InetAddress;import java.n ...

  2. spring boot 获取cookie信息

    spring boot 获取cookie信息 先创建一个cookie @RequestMapping(value = "/setCookies",method = RequestM ...

  3. Spring boot异常统一处理方法:@ControllerAdvice注解的使用、全局异常捕获、自定义异常捕获

    Spring boot异常统一处理方法:@ControllerAdvice注解的使用.全局异常捕获.自定义异常捕获 参考文章: (1)Spring boot异常统一处理方法:@ControllerAd ...

  4. Spring Boot 启动执行某个方法的三种实现方式

    Spring Boot 启动执行某个方法的三种实现方式 Spring Boot 启动执行某个方法的三种实现方式 第一种方式 @PostConstruct 注解解释 具体实现 第二种方式 Applica ...

  5. Spring Boot 定义接口的方法是否可以声明为 private?

    我们在 Controller 中定义接口的时候,一般都是像下面这样: @GetMapping("/01") public String hello(Map<String,Ob ...

  6. Web笔记-session盗用安全问题(Spring Boot获取所有session及提高安全性)

    此处本人的过滤代码如下: 仅仅是判断了这个session有没有被记录,有没有attribute! 某些IT论坛,就是这样的,通过session,就可以进行批量帐号操作,发取http协议. 这里演示如下 ...

  7. Spring Boot 获取 Bean 的 3 种方式!还有谁不会?

    作者 | chilx 来源 | https://blog.csdn.net/showchi/article/details/97005720 注意:调用者要被spring管理 方式一 注解@PostC ...

  8. C++|Java混合实验-Spring Boot获取客户端操作系统,浏览器,Ip等信息,Qt端展示

    目录 概述 演示 源码 概述 这里用Spring Boot控制"/"和"index.html"请求,获取客户端http的信息: Qt端使用QML和C++混合编程 ...

  9. spring boot获取spring容器中的bean对象

    我们知道如果我们要在一个类使用  spring提供的bean对象,我们需要把这个类注入到spring容器中,交给spring容器进行管理,但是在实际当中,我们往往会碰到在一个普通的Java类中,想直接 ...

最新文章

  1. Zend Guard 各版本下载【破解方法】
  2. STM32开发 -- HardFault_Handler处理
  3. 【Spring 数据访问终篇】Spring + Hibernate + Mysql
  4. Action Service Dao三层的功能划分
  5. 建立和操作 JDOM 文档
  6. jenkins maven没有使用全局设置文件地址_Jenkins手把手图文教程「基于Jenkins 2.164.1」...
  7. 点击home键_iPhone小技巧:无Home键iPhone11如何强制重启?
  8. java技术秘籍 转摘
  9. 统计面要素中点要素的个数.
  10. 拓端tecdat|Python贝叶斯推断Metropolis-Hastings(M-H)MCMC采样算法的实现
  11. PHP二维数组按照指定的字段排序的函数
  12. 新浪微博:“救命的黄金稻草”
  13. 安全教育平台账号后四位_2020中小学国家安全教育专题活动入口官网:学校安全教育平台...
  14. JAVA 实现《warcraft java版》游戏
  15. Matlab画平滑曲线的两种方法( 拟合或插值后再用plot即可)
  16. 【Python学习笔记】复习sql主键外键索引
  17. 图灵大会 | 新观点:AI盛世,其实我们离得还很远
  18. css中pt单位,css中字体单位px,pt,em,百分比之间的区别和用法
  19. MySQL更新时间的时候生成随机时间
  20. 2020 Python中文社区热门文章 Top 10

热门文章

  1. AtCoder Beginner Contest 194 F - Digits Paradise in Hexadecimal 数位dp
  2. 快速沃尔什变换:从入门到背板(含推导过程)
  3. CF1063A Oh Those Palindromes
  4. HDU 5510 Bazinga
  5. [ZJOI2014] 星系调查(树上差分 + 数学推式子)
  6. 2021CSP:游记
  7. 不止代码:友好城市(动态规划)
  8. P5825-排列计数【EGF,NTT】
  9. P3041-[USACO12JAN]Video Game G【AC自动机,dp】
  10. U102488-傻叉题【dp】