在 Java Web 开发中,获取 HttpServletRequest 对象是常见的需求,根据不同的运行环境和框架,获取方式有所不同,下面我将为你详细梳理在各种主流场景下如何获取 request 对象。

核心概念
HttpServletRequest 是 Java Servlet API 中的一个接口,它封装了客户端向服务器发送的 HTTP 请求的所有信息,如请求头、请求参数、Cookie、Session、请求方法、URI 等。
原生 Servlet 环境
这是最基础、最直接的方式,在实现了 HttpServlet 的类中,service() 方法或其 doGet(), doPost() 等方法会直接接收 HttpServletRequest 和 HttpServletResponse 作为参数。
示例代码:
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 1. 直接在方法参数中获取
String requestURI = request.getRequestURI();
String userAgent = request.getHeader("User-Agent");
String name = request.getParameter("name");
System.out.println("请求URI: " + requestURI);
System.out.println("User-Agent: " + userAgent);
System.out.println("参数 name: " + name);
// 使用 response 返回内容
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("<h1>你好,Servlet!</h1>");
response.getWriter().println("<p>你传入的 name 是: " + name + "</p>");
}
}
在 Servlet 中,这是最标准、最简单的方式。

Spring Framework (Spring MVC / Spring Boot)
在 Spring 框架中,获取 request 的方式非常灵活,因为它使用了依赖注入和 AOP(面向切面编程)。
方式 1:通过方法参数注入 (推荐)
这是最常用、最推荐的方式,Spring 会自动将当前请求的 HttpServletRequest 对象注入到你的方法参数中。
示例代码 (Controller 中):
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
@Controller
public class MyController {
@GetMapping("/hello")
public String sayHello(HttpServletRequest request, @RequestParam("id") String userId) {
// Spring 自动注入 request 对象
System.out.println("Request URL: " + request.getRequestURL());
System.out.println("Request Method: " + request.getMethod());
// 同时可以获取其他参数
System.out.println("User ID from @RequestParam: " + userId);
// 获取所有请求头
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
System.out.println(headerName + " : " + request.getHeader(headerName));
}
return "hello"; // 返回视图名
}
}
方式 2:使用 @Autowired 注入
如果你需要在非请求处理方法(如 Service 层、工具类)中访问 request,可以通过 @Autowired 注入一个代理对象,这个代理对象是 ServletRequestAttributes 的一个实例,它持有当前线程的 request。

前提: 必须在 Web 环境下,Spring 能管理到注入的类。
示例代码:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Service
public class MyService {
// 注入 RequestContextHolder 的包装类,而不是直接注入 request
// 因为 request 是作用域相关的,不能直接作为 bean 注入
@Autowired
private HttpServletRequest request; // 注意:这种方式在某些情况下可能不推荐,更推荐使用 RequestContextHolder
public void doSomething() {
// 推荐使用这种方式,更灵活且安全
HttpServletRequest currentRequest = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
System.out.println("在 Service 中获取请求 URI: " + currentRequest.getRequestURI());
// 如果一定要用 @Autowired,需要确保注入的是一个代理
// 但通常 RequestContextHolder 是更好的选择
// System.out.println("Autowired request URI: " + this.request.getRequestURI());
}
}
更推荐的 Service 层获取方式:
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Service
public class MyService {
public void doSomething() {
// 1. 获取当前请求的属性
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
// 2. 从属性中获取 request 对象
HttpServletRequest request = attributes.getRequest();
// 3. 使用 request
System.out.println("在 Service 中获取请求 URI: " + request.getRequestURI());
}
}
注意: RequestContextHolder 使用 ThreadLocal 来存储请求信息,这意味着它只能在处理请求的线程中工作,在异步或多线程场景下需要特殊处理。
方式 3:实现 ServletRequestAware 接口 (旧版 Spring)
在较老的 Spring 版本中,可以实现 ServletRequestAware 接口来获取 request,这种方式在新版 Spring 中已不常用,因为方式1和方式2更简洁。
其他 Java Web 框架
Jakarta EE (原 Java EE)
在 Jakarta EE 的 EJB 或 CDI Bean 中,可以使用 @Context 注解来注入 HttpServletRequest。
示例代码 (CDI Bean 中):
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
@RequestScoped
@Path("/myresource")
public class MyResource {
// 方式1: 使用 @Context 注解
@Context
private HttpServletRequest request;
// 方式2: 使用依赖注入 (需要启用 CDI)
@Inject
private HttpServletRequest injectedRequest;
@GET
public String get() {
System.out.println("Request URI from @Context: " + request.getRequestURI());
return "Hello from JAX-RS!";
}
}
JSP/Servlet 中的内置对象
在 JSP 页面中,request 是一个内置对象,可以直接使用,无需任何声明。
示例代码 (JSP 中):
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>获取 Request 示例</title>
</head>
<body>
<h1>在 JSP 中直接使用 request 内置对象</h1>
<p>请求方法: <%= request.getMethod() %></p>
<p>请求协议: <%= request.getProtocol() %></p>
<p>请求路径: <%= request.getRequestURI() %></p>
<%-- 获取参数 --%>
<%
String name = request.getParameter("name");
if (name != null) {
%>
<p>你好, <%= name %>!</p>
<%
}
%>
</body>
</html>
总结与最佳实践
| 场景 | 推荐方式 | 优点 | 缺点 |
|---|---|---|---|
| 原生 Servlet | 方法参数 | 简单直接,符合规范 | 仅限 Servlet 内部 |
| Spring MVC | 方法参数注入 | 最清晰、最推荐,依赖关系明确 | 仅限 Controller 方法 |
| Spring Service/Tool | RequestContextHolder |
灵活,可在任何被 Spring 管理的类中使用 | 需注意线程安全(异步场景) |
| JSP | 直接使用内置对象 request |
非常方便 | 耦合度高,不符合 MVC 思想 |
| Jakarta EE/CDI | @Context 注解 |
标准化,适合 EJB/CDI 环境 | 需要特定环境支持 |
核心建议:
- 在 Controller 层:优先使用 方法参数注入,这是最清晰、最符合 Spring 设计思想的方式。
- 在 Service 或其他业务层:使用
RequestContextHolder.currentRequestAttributes()来获取,这是获取当前线程请求的标准方式。 - 避免在非 Web 环境中使用:确保你的代码只在 Web 请求处理线程中执行,否则
request对象会是null。 - 谨慎使用
@Autowired注入request:虽然可能可行,但它隐藏了依赖关系,不如RequestContextHolder灵活和明确,通常不推荐。
