请求上下文对象RequestContextHolder
RequestContextHolder
是 Spring Framework 提供的一个工具类,主要用于在 非 Web 层(如 Service 层、工具类等)中便捷地获取当前 HTTP 请求的上下文信息,而无需通过方法参数显式传递 HttpServletRequest
或 HttpServletResponse
对象。
核心作用:
存储和访问请求上下文
它通过ThreadLocal
机制将当前请求的上下文(RequestAttributes
对象,封装了HttpServletRequest
、HttpServletResponse
等信息)与当前线程绑定,确保在多线程环境下,每个线程都能获取到自己对应的请求上下文。简化代码
在传统方式中,若 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常用的方法
获取请求路径相关信息
String getContextPath()
:获取当前 Web 应用的上下文路径String getServletPath()
:获取 Servlet 的路径String getRequestURI()
:获取请求的 URI(不包含协议、主机和端口)String getRequestURL()
:获取完整的请求 URL(包含协议、主机和端口)String getQueryString()
:获取请求 URL 中的查询字符串(?
后面的部分)
获取请求参数
String getParameter(String name)
:获取指定名称的请求参数值String[] getParameterValues(String name)
:获取指定名称的请求参数的所有值(适用于复选框等)Enumeration<String> getParameterNames()
:获取所有请求参数的名称Map<String, String[]> getParameterMap()
:获取所有请求参数的键值对集合
获取请求头信息
String getHeader(String name)
:获取指定名称的请求头值Enumeration<String> getHeaders(String name)
:获取指定名称的所有请求头值Enumeration<String> getHeaderNames()
:获取所有请求头的名称int getIntHeader(String name)
:获取指定名称的整数类型请求头值long getDateHeader(String name)
:获取指定名称的日期类型请求头值
获取客户端信息
String getRemoteAddr()
:获取客户端的 IP 地址String getRemoteHost()
:获取客户端的主机名int getRemotePort()
:获取客户端的端口号String getLocalAddr()
:获取服务器的 IP 地址int getLocalPort()
:获取服务器的端口号
获取请求方法和协议
String getMethod()
:获取 HTTP 请求方法(GET、POST 等)String getProtocol()
:获取请求使用的协议及版本(如 HTTP/1.1)
请求属性操作
Object getAttribute(String name)
:获取指定名称的请求属性void setAttribute(String name, Object value)
:设置请求属性void removeAttribute(String name)
:移除指定名称的请求属性Enumeration<String> getAttributeNames()
:获取所有请求属性的名称
其他常用方法
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+ 支持
注意事项
- 流的使用顺序:
getWriter()
和getOutputStream()
不能同时使用,否则会抛出异常。 - 编码设置时机:
setCharacterEncoding()
或setContentType()
需在获取输出流(getWriter()
)之前调用,否则编码设置无效。 - 重定向特性:
sendRedirect()
会发送 302 状态码和Location
响应头,客户端会发起新的请求,因此重定向后的数据无法通过request
传递(需用 Session 或 URL 参数)。
注意事项:
线程绑定特性
由于依赖ThreadLocal
,RequestContextHolder
只能在处理当前请求的线程中使用。在异步线程中,需通过RequestContextHolder.setRequestAttributes(attributes, true)
手动传递上下文(第二个参数表示是否允许子线程继承)。适用场景
主要用于 Web 环境(如 Spring MVC),在非 Web 环境(如单元测试、定时任务)中使用可能返回null
,需注意判空。生命周期
上下文信息会在请求开始时由 Spring 自动设置,在请求结束时自动清理,无需手动管理(避免内存泄漏)。