Springboot学习笔记之 RequestAttributes

RequestAttributes 和 ServletRequestAttributes 是 Spring 框架中用于处理请求作用域属性的核心接口和实现类。以下是它们的源码解读和关键点分析:
 

1. RequestAttributes 接口

RequestAttributes 是一个抽象接口,定义了在请求作用域内存储和获取属性的基本方法。
核心方法:

// 设置属性到指定的作用域(如请求或会话)
void setAttribute(String name, Object value, int scope);

// 获取指定作用域中的属性
Object getAttribute(String name, int scope);

// 移除指定作用域中的属性
void removeAttribute(String name, int scope);

// 注册销毁回调(通常用于清理资源)
void registerDestructionCallback(String name, Runnable callback, int scope);

// 获取会话ID
String getSessionId();

// 获取会话互斥对象(用于同步控制)
Object getSessionMutex();

作用域常量:
SCOPE_REQUEST: 表示请求作用域。
SCOPE_SESSION: 表示会话作用域。
设计目的:
RequestAttributes 提供了一个通用的抽象,使得开发者可以在不同的环境中(如 Servlet、Portlet 等)以统一的方式访问请求作用域的数据。
 


2. ServletRequestAttributes 实现类

ServletRequestAttributes 是 RequestAttributes 的具体实现,基于 Servlet API 提供了对 HTTP 请求和会话的支持。
核心字段:

private final HttpServletRequest request; // 当前的 HTTP 请求对象
private HttpServletResponse response;    // 当前的 HTTP 响应对象
private volatile HttpSession session;     // 当前的会话对象

核心方法实现:

设置属性:

  @Override
  public void setAttribute(String name, Object value, int scope) {
      if (scope == SCOPE_REQUEST) {
          this.request.setAttribute(name, value);
      } else if (scope == SCOPE_SESSION) {
          HttpSession session = getSession(true);
          session.setAttribute(name, value);
      } else {
          throw new IllegalArgumentException("Invalid scope: " + scope);
      }
  }
  

获取属性:

  @Override
  public Object getAttribute(String name, int scope) {
      if (scope == SCOPE_REQUEST) {
          return this.request.getAttribute(name);
      } else if (scope == SCOPE_SESSION) {
          HttpSession session = getSession(false);
          return (session != null ? session.getAttribute(name) : null);
      } else {
          throw new IllegalArgumentException("Invalid scope: " + scope);
      }
  }
  

移除属性:

  @Override
  public void removeAttribute(String name, int scope) {
      if (scope == SCOPE_REQUEST) {
          this.request.removeAttribute(name);
      } else if (scope == SCOPE_SESSION) {
          HttpSession session = getSession(false);
          if (session != null) {
              session.removeAttribute(name);
          }
      } else {
          throw new IllegalArgumentException("Invalid scope: " + scope);
      }
  }
  

获取会话ID:

  @Override
  public String getSessionId() {
      return getSession(true).getId();
  }
  

特性:

线程绑定:ServletRequestAttributes 通常与 RequestContextHolder 配合使用,通过 ThreadLocal 将请求上下文绑定到当前线程。
延迟加载会话:只有在需要时才会创建会话(通过 getSession(true) 或 getSession(false) 控制)。
 

3. RequestContextHolder 工具类


RequestAttributes 和 ServletRequestAttributes 通常通过 RequestContextHolder 来管理和访问。
核心方法:

// 获取当前线程的 RequestAttributes
public static RequestAttributes getRequestAttributes();

// 获取当前线程的 RequestAttributes,并强制要求不为空
public static RequestAttributes currentRequestAttributes();

4.使用案例

 private void printRequestContext() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (servletRequestAttributes != null) {
            HttpServletRequest request = servletRequestAttributes.getRequest();
            HttpSession session = request.getSession();

            System.out.println("Request headers: ==>\n");
            request.getHeaderNames().asIterator().forEachRemaining(headerName -> {
                System.out.println(headerName + ": " + request.getHeader(headerName));
            });

            System.out.println("Request attributes: ==> \n");
            request.getAttributeNames().asIterator().forEachRemaining(attributeName -> {
                System.out.println(attributeName + ": " + request.getAttribute(attributeName));
            });

            System.out.println("Cookies: ==> \n");
            Arrays.stream(request.getCookies()).forEach(System.out::println);

            System.out.println("uri: ==> " + request.getRequestURI());
            System.out.println("url: ==> " + request.getRequestURL());

            System.out.println("Session Attributes: ==> \n");
            session.getAttributeNames().asIterator().forEachRemaining(attributeName -> {
                System.out.println(attributeName + ": " + session.getAttribute(attributeName));
            });

        }
    }

返回结果如下:

Request headers: ==>

accept: */*
accept-encoding: gzip, deflate, br
user-agent: PostmanRuntime-ApipostRuntime/1.1.0
connection: keep-alive
cookie: JSESSIONID=97CC336BA78105DAFF9D6AC07B1A4A06
cache-control: no-cache
host: localhost:6085


Request attributes: ==> 

org.springframework.web.servlet.View.pathVariables: {lang=zh_CN}
org.springframework.web.context.request.async.WebAsyncManager.WEB_ASYNC_MANAGER: org.springframework.web.context.request.async.WebAsyncManager@4c504320
org.springframework.web.servlet.HandlerMapping.bestMatchingHandler: com.vorwerk.cookidoo.cn.cms.controller.HomeController#homePageLayout(String)
org.springframework.web.servlet.DispatcherServlet.CONTEXT: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@2b8bb184, started on Sat Mar 22 11:11:21 CST 2025

...
 

Cookies: ==> 

jakarta.servlet.http.Cookie@f14c39ba{JSESSIONID=97CC336BA78105DAFF9D6AC07B1A4A06,null}

uri: ==> /zh_CN/homepage
url: ==> http://localhost:6085/zh_CN/homepage


Session Attributes: ==> 

5. 总结

RequestAttributes 是一个抽象接口,定义了操作请求作用域属性的标准方法。
ServletRequestAttributes 是基于 Servlet API 的具体实现,提供了对 HTTP 请求和会话的直接支持。
RequestContextHolder 是一个工具类,用于在当前线程中访问和管理 RequestAttributes。
通过这些组件,Spring 提供了一种灵活且解耦的方式来处理请求作用域数据,适用于各种 Web 应用场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值