当前位置: 首页 > 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.dtcms.com/a/348129.html

相关文章:

  • 【datawhale组队学习】RAG技术 - TASK04 向量及多模态嵌入(第三章1、2节)
  • AI Agent全栈开发流程推荐(全栈开发步骤)
  • 在 vue3 和 vue2 中,v-for 和 v-if 可以一起用吗,区别是什么
  • Win10部署ElasticSearch、Logstash、Kibana
  • wpf之Grid控件
  • 图像均衡化详解:从直方图均衡到 CLAHE,让图片告别 “灰蒙蒙“
  • 征程 6X 常用工具介绍
  • 第16届蓝桥杯C++中高级选拔赛(STEMA)2024年12月22日真题
  • elasticsearch 7.x elasticsearch 使用scroll滚动查询中超时问题案例
  • 【C#】构造函数实用场景总结
  • PostgreSQL interval 转换为 int4 (整数)
  • Flink SQL执行SQL错误排查
  • 结构化智能编程:用树形向量存储重构AI代码理解范式
  • RAGFlow (二)小试牛刀:登陆页重构
  • 《链路状态路由协议OSPF》
  • 前端工程师面试题-vue
  • 记一次生产环境Hbase填坑之路、Hbase客户端登陆、kerberos认证、端口列表、Pod上手撕代码【Hbase最佳实践】
  • 【CV】OpenCV①——OpenCV常用模块
  • 使用 Fargate 在 AWS ECS 上运行 Spring Boot 应用程序
  • 【C#】【WinForm】ListView_列表视图控件
  • [每周一更]-(第157期):深入理解Go语言的垃圾回收机制:调优与监控
  • BERT(Bidirectional Encoder Representations from Transformers)模型详解
  • 2.7 提示词调优编码实战(二)
  • 2025年8月第3周AI资讯
  • 将C++资源管理测试框架整合到GitLab CI/CD的完整实践指南
  • Ansible自动化配置
  • 手写MyBatis第31弹-用工厂模式重构MyBatis的SqlSession创建过程
  • 小迪安全v2023学习笔记(七十一讲)—— Python安全反序列化反编译格式化字符串安全
  • 深入解析MyBatis中#{}和${}的区别与应用场景
  • Implementing Redis in C++ : E(AVL树详解)