当前位置: 首页 > news >正文

请求上下文对象RequestContextHolder

RequestContextHolder 是 Spring Framework 提供的一个工具类,主要用于在 非 Web 层(如 Service 层、工具类等)中便捷地获取当前 HTTP 请求的上下文信息,而无需通过方法参数显式传递 HttpServletRequest 或 HttpServletResponse 对象。

核心作用:

  1. 存储和访问请求上下文
    它通过 ThreadLocal 机制将当前请求的上下文(RequestAttributes 对象,封装了 HttpServletRequestHttpServletResponse 等信息)与当前线程绑定,确保在多线程环境下,每个线程都能获取到自己对应的请求上下文。

  2. 简化代码
    在传统方式中,若 Service 层需要访问请求信息(如获取请求参数、Session、用户信息等),需从 Controller 层通过方法参数传递 HttpServletRequest。而 RequestContextHolder 允许直接在 Service 层获取这些信息,减少了参数传递的冗余代码。

常用方法:

// 获取当前请求的上下文(RequestAttributes)
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();// 强制转换为 ServletRequestAttributes,获取 HttpServletRequest 等对象
ServletRequestAttributes servletAttributes = (ServletRequestAttributes) requestAttributes;// 获取 HttpServletRequest 对象
HttpServletRequest request = servletAttributes.getRequest();// 获取 HttpServletResponse 对象
HttpServletResponse response = servletAttributes.getResponse();// 获取 Session
HttpSession session = request.getSession();

RequestContextHolder常用的方法

1. 获取请求上下文
// 获取当前请求的上下文(RequestAttributes 对象)
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
  • 返回值为 RequestAttributes 接口,包含了请求相关的属性信息。
  • 在 Web 环境下,实际类型是 ServletRequestAttributes(可强制转换后获取更多 Web 相关方法)。
2. 获取具有继承性的上下文
// 获取允许子线程继承的请求上下文
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(true);
  • 参数 true 表示:若当前线程有上下文,子线程可以继承该上下文(适用于异步处理场景)。
3. 设置请求上下文
// 手动设置请求上下文(通常由 Spring 自动处理,极少手动调用)
RequestContextHolder.setRequestAttributes(requestAttributes);// 第二个参数表示是否允许子线程继承
RequestContextHolder.setRequestAttributes(requestAttributes, true);
  • 一般用于异步线程中传递上下文,例如:在主线程中获取上下文后,传递给子线程。
4. 重置请求上下文
// 清除当前线程绑定的请求上下文
RequestContextHolder.resetRequestAttributes();
  • 通常在请求处理结束时由 Spring 自动调用,避免 ThreadLocal 内存泄漏。

HttpServletRequest常用的方法

  1. 获取请求路径相关信息
    • String getContextPath():获取当前 Web 应用的上下文路径
    • String getServletPath():获取 Servlet 的路径
    • String getRequestURI():获取请求的 URI(不包含协议、主机和端口)
    • String getRequestURL():获取完整的请求 URL(包含协议、主机和端口)
    • String getQueryString():获取请求 URL 中的查询字符串(?后面的部分)
  2. 获取请求参数
    • String getParameter(String name):获取指定名称的请求参数值
    • String[] getParameterValues(String name):获取指定名称的请求参数的所有值(适用于复选框等)
    • Enumeration<String> getParameterNames():获取所有请求参数的名称
    • Map<String, String[]> getParameterMap():获取所有请求参数的键值对集合
  3. 获取请求头信息
    • String getHeader(String name):获取指定名称的请求头值
    • Enumeration<String> getHeaders(String name):获取指定名称的所有请求头值
    • Enumeration<String> getHeaderNames():获取所有请求头的名称
    • int getIntHeader(String name):获取指定名称的整数类型请求头值
    • long getDateHeader(String name):获取指定名称的日期类型请求头值
  4. 获取客户端信息
    • String getRemoteAddr():获取客户端的 IP 地址
    • String getRemoteHost():获取客户端的主机名
    • int getRemotePort():获取客户端的端口号
    • String getLocalAddr():获取服务器的 IP 地址
    • int getLocalPort():获取服务器的端口号
  5. 获取请求方法和协议
    • String getMethod():获取 HTTP 请求方法(GET、POST 等)
    • String getProtocol():获取请求使用的协议及版本(如 HTTP/1.1)
  6. 请求属性操作
    • Object getAttribute(String name):获取指定名称的请求属性
    • void setAttribute(String name, Object value):设置请求属性
    • void removeAttribute(String name):移除指定名称的请求属性
    • Enumeration<String> getAttributeNames():获取所有请求属性的名称
  7. 其他常用方法
    • String getCharacterEncoding():获取请求的字符编码
    • void setCharacterEncoding(String env):设置请求的字符编码
    • int getContentLength():获取请求体的长度
    • String getContentType():获取请求体的 MIME 类型
    • ServletInputStream getInputStream():获取请求体的输入流
    • HttpSession getSession():获取或创建与当前请求关联的会话
    • Cookie[] getCookies():获取请求中的所有 Cookie

HttpServletResponse常用的方法

一、设置响应状态码

用于告知客户端请求处理的结果(成功、错误等)。

// 设置状态码(如 200 成功、404 未找到、500 服务器错误)
void setStatus(int sc);// 发送错误状态码(会自动生成错误页面)
void sendError(int sc);// 发送错误状态码并附加错误信息
void sendError(int sc, String msg);

示例:

response.sendError(404, "页面不存在"); // 404 错误
response.setStatus(200); // 成功(默认值)
二、操作响应头

用于设置响应的元数据(如内容类型、缓存策略、重定向等)。

// 设置响应头(键值对)
void setHeader(String name, String value);// 添加响应头(可重复添加相同键的不同值)
void addHeader(String name, String value);// 设置响应内容的 MIME 类型(如 text/html、application/json)
void setContentType(String type);// 设置字符编码(需在 getWriter() 前调用)
void setCharacterEncoding(String charset);// 简化设置:同时指定 Content-Type 和字符编码(推荐)
// 例如:"text/html;charset=UTF-8"
void setContentType("text/html;charset=UTF-8");// 设置重定向(状态码 302)
void sendRedirect(String location);

示例:

response.setHeader("Cache-Control", "no-cache"); // 禁止缓存
response.setContentType("application/json;charset=UTF-8"); // JSON 响应
response.sendRedirect("/login"); // 重定向到登录页
三、操作响应体

用于向客户端输出响应内容(文本、字节等)。

// 获取字符输出流(用于输出文本内容,如 HTML、JSON)
PrintWriter getWriter() throws IOException;// 获取字节输出流(用于输出二进制内容,如图片、文件)
ServletOutputStream getOutputStream() throws IOException;// 设置响应体长度(可选,帮助客户端判断内容是否完整)
void setContentLength(int len);
void setContentLengthLong(long len); // 支持大文件

示例:

// 输出文本(HTML)
PrintWriter out = response.getWriter();
out.write("<h1>Hello World</h1>");
out.flush();// 输出二进制(文件下载)
ServletOutputStream os = response.getOutputStream();
os.write(byteArray); // 写入字节数组
os.flush();
四、其他常用方法
// 设置响应的 Locale(语言地区,影响日期等格式)
void setLocale(Locale loc);// 获取当前响应的状态码
int getStatus(); // Servlet 3.0+ 支持

注意事项

  1. 流的使用顺序getWriter() 和 getOutputStream() 不能同时使用,否则会抛出异常。
  2. 编码设置时机setCharacterEncoding() 或 setContentType() 需在获取输出流(getWriter())之前调用,否则编码设置无效。
  3. 重定向特性sendRedirect() 会发送 302 状态码和 Location 响应头,客户端会发起新的请求,因此重定向后的数据无法通过 request 传递(需用 Session 或 URL 参数)。

注意事项:

  1. 线程绑定特性
    由于依赖 ThreadLocalRequestContextHolder 只能在处理当前请求的线程中使用。在异步线程中,需通过 RequestContextHolder.setRequestAttributes(attributes, true) 手动传递上下文(第二个参数表示是否允许子线程继承)。

  2. 适用场景
    主要用于 Web 环境(如 Spring MVC),在非 Web 环境(如单元测试、定时任务)中使用可能返回 null,需注意判空。

  3. 生命周期
    上下文信息会在请求开始时由 Spring 自动设置,在请求结束时自动清理,无需手动管理(避免内存泄漏)。

http://www.xdnf.cn/news/1356967.html

相关文章:

  • LIANA | part2 results部分
  • 【贪心算法】day1
  • spring源码之事务篇(事务管理器整个流程)
  • JAVA限流方法
  • PAT 1081 Rational Sum
  • 不只是关键词匹配:AI如何像人类一样‘听懂‘你在说什么
  • Spring Boot 中 @Controller与 @RestController的区别及 404 错误解析
  • 工作记录 2015-08-31
  • 【科研绘图系列】R语言浮游植物初级生产力与光照强度的关系
  • leetcode_189 轮转数组
  • 【LLIE专题】一种用于低光图像增强的空间自适应光照引导 Transformer(SAIGFormer)框架
  • Ansible 自动化基石:变量定义、优先级控制与 Vault 敏感信息加密实战指南
  • 【重学MySQL】八十七. 触发器管理全攻略:SHOW TRIGGERS与DROP TRIGGER实战详解
  • MySQL管理
  • [身份验证脚手架] 认证路由 | 认证后端控制器与请求
  • MR椎间盘和腰椎分割项目:基于深度学习的医学图像分析
  • 【数据结构】栈和队列——栈
  • MyBatis 和 MyBatis-Plus对比
  • 一个奇怪的问题-Python会替代Java吗?技术语言之争的真相-优雅草卓伊凡
  • 深度学习:CUDA、PyTorch下载安装
  • 用 Bright Data MCP Server 构建实时数据驱动的 AI 情报系统:从市场调研到技术追踪的自动化实战
  • 自由学习记录(87)
  • System.IO.Pipelines 与“零拷贝”:在 .NET 打造高吞吐二进制 RPC
  • 关于 svn无法查看下拉日志提示“要离线”和根目录看日志“no data” 的解决方法
  • 编译Marlin 1.1.9.1固件指南
  • 如何理解“向量”
  • 大数据、hadoop、爬虫、spark项目开发设计之基于数据挖掘的交通流量分析研究
  • 数据挖掘 4.1~4.7 机器学习性能评估参数
  • 【软考架构】云计算相关概念
  • 《CF1120D Power Tree》