运营相关开源框架-SpringBoot系列

Spring Boot 获取 HttpServletReques

2020-04-16  本文已影响0人  又语

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


目录


概述

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


方法

Controller 方法参数

原理:
在 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 对象作为方法参数,相当于局部变量,是 线程安全 的。

缺点:

属性自动注入

代码示例:

@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 对象是 线程安全 的。

优点:

缺点:

手动方法调用

代码示例:

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

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

优点:

缺点:

借助 @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 {

    @Autowired
    private HttpServletRequest autowiredRequest;

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

    @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.";
    }
}
上一篇下一篇

猜你喜欢

热点阅读