- 服务器端:如何获取客户端发来的 HTTP 请求
- 客户端:如何向其他服务器发送 HTTP 请求并获取响应
服务器端获取客户端请求
当你编写一个 Web 服务器(如使用 Spring Boot、Servlet API)时,你需要获取浏览器或其他客户端发来的请求信息,这是最常见的情况。

原生 Servlet API (Java EE / Jakarta EE)
这是最基础、最核心的方式,理解它有助于你理解底层原理,所有现代 Java Web 框架(如 Spring MVC)的底层原理都与此类似。
假设你有一个继承自 HttpServlet 的类,你需要重写 doGet 或 doPost 方法。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/myServlet") // 映射这个 Servlet 的访问路径
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 获取请求行信息
String method = request.getMethod(); // 获取请求方法,如 "GET"
String requestUri = request.getRequestURI(); // 获取请求的 URI,如 "/myApp/myServlet"
String queryString = request.getQueryString(); // 获取查询字符串,如 "name=John&age=30"
String protocol = request.getProtocol(); // 获取协议版本,如 "HTTP/1.1"
System.out.println("Method: " + method);
System.out.println("Request URI: " + requestUri);
System.out.println("Query String: " + queryString);
System.out.println("Protocol: " + protocol);
// 2. 获取请求头信息
String userAgent = request.getHeader("User-Agent"); // 获取特定的请求头
String acceptLanguage = request.getHeader("Accept-Language");
System.out.println("User-Agent: " + userAgent);
System.out.println("Accept-Language: " + acceptLanguage);
// 3. 获取请求参数 (主要来自 URL 的 query string 或 POST 表单)
// getParameter 返回字符串
String name = request.getParameter("name"); // URL 是 ?name=John
// getParameterValues 返回字符串数组,用于复选框等
String[] hobbies = request.getParameterValues("hobby"); // URL 是 ?hobby=reading&hobby=sports
System.out.println("Name: " + name);
System.out.println("Hobbies: " + (hobbies != null ? String.join(", ", hobbies) : "None"));
// 4. 获取请求体信息 (POST 请求中的 JSON 或 XML 数据)
// 对于 JSON 数据,通常需要使用 getInputStream() 或 getReader() 并配合 JSON 库(如 Jackson, Gson)来解析
// 注意:request.getInputStream() 只能读取一次,读取后内容就没了。
/*
BufferedReader reader = request.getReader();
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
String requestBody = sb.toString();
System.out.println("Request Body: " + requestBody);
*/
// 5. 获取其他属性
String remoteAddr = request.getRemoteAddr(); // 获取客户端 IP 地址
int remotePort = request.getRemotePort(); // 获取客户端端口
System.out.println("Client IP: " + remoteAddr);
System.out.println("Client Port: " + remotePort);
// 6. 设置响应并返回给客户端
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1>Hello from Servlet!</h1>");
out.println("<p>Name from request: " + name + "</p>");
out.println("</body></html>");
}
}
Spring Boot (更现代、更便捷的方式)
在 Spring Boot 中,你通常通过在方法参数中声明 HttpServletRequest (或其子类 javax.servlet.http.HttpServletRequest) 来直接使用它,Spring 会自动将其注入。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
@RestController
public class MyController {
@GetMapping("/hello")
public String hello(HttpServletRequest request, @RequestParam String name) {
// 1. 获取请求行
System.out.println("Request URI: " + request.getRequestURI());
System.out.println("Query String: " + request.getQueryString());
// 2. 获取请求头
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
System.out.println(headerName + ": " + request.getHeader(headerName));
}
// 3. 获取请求参数 (也可以通过 @RequestParam 注解直接获取)
// String name = request.getParameter("name"); // 和上面的 @RequestParam "name" 效果一样
System.out.println("Name from @RequestParam: " + name);
// 4. 获取请求体
// Spring Boot 通常通过 @RequestBody 注解来接收 JSON/XML 请求体,更方便。
// String requestBody = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
// System.out.println("Request Body: " + requestBody);
// 5. 获取客户端信息
System.out.println("Client IP: " + request.getRemoteAddr());
return "Hello, " + name + "! Your request has been processed.";
}
}
客户端发送请求并获取响应
当你需要编写一个 Java 程序去调用另一个 Web 服务的 API 时,你就是客户端。

使用 java.net.HttpURLConnection (JDK 内置,无需额外库)
这是 Java 标准库自带的 HTTP 客户端,比较底层,需要手动处理很多细节。
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpURLConnectionExample {
public static void main(String[] args) throws Exception {
// 1. 创建 URL 对象
String urlString = "https://jsonplaceholder.typicode.com/posts/1";
URL url = new URL(urlString);
// 2. 打开连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 3. 设置请求方法
connection.setRequestMethod("GET");
// 4. 设置请求头
connection.setRequestProperty("User-Agent", "MyJavaApp/1.0");
connection.setRequestProperty("Accept", "application/json");
// 5. 获取响应码
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
// 6. 读取响应内容
if (responseCode == HttpURLConnection.HTTP_OK) { // 200 OK
BufferedReader in = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// 7. 打印响应内容
System.out.println("Response Body:");
System.out.println(response.toString());
} else {
System.out.println("GET request failed");
}
}
}
使用 HttpClient (Java 11+ 内置,推荐)
从 Java 11 开始,java.net.http.HttpClient 成为官方推荐的 HTTP 客户端 API,它更现代、更强大、支持异步操作。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class HttpClientExample {
public static void main(String[] args) throws Exception {
// 1. 创建 HttpClient
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.connectTimeout(Duration.ofSeconds(10))
.build();
// 2. 创建 HttpRequest
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.header("User-Agent", "MyJavaApp/1.0")
.header("Accept", "application/json")
.build();
// 3. 发送请求并获取响应 (同步方式)
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// 4. 处理响应
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body:");
System.out.println(response.body());
}
}
使用第三方库 (如 OkHttp, Apache HttpClient)
如果项目允许使用第三方库,它们通常提供更简洁、更强大的 API。
OkHttp 示例 (需要添加 com.squareup.okhttp3:okhttp 依赖):

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class OkHttpExample {
public static void main(String[] args) throws Exception {
// 1. 创建 OkHttpClient
OkHttpClient client = new OkHttpClient();
// 2. 创建 Request
Request request = new Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts/1")
.header("User-Agent", "MyJavaApp/1.0")
.build();
// 3. 执行请求
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
// 4. 获取响应体
String responseBody = response.body().string();
System.out.println("Response Body:");
System.out.println(responseBody);
}
}
}
总结与对比
| 场景 | 推荐技术 | 优点 | 缺点 |
|---|---|---|---|
| 服务器端 (获取请求) |
Spring Boot | 简洁、自动化、生态强大,通过注解轻松获取所有请求信息。 | 需要引入 Spring 框架。 |
| 原生 Servlet API | 标准化、轻量级、不依赖框架,适合学习底层原理。 | 代码繁琐,需要手动处理很多细节。 | |
| 客户端 (发送请求) |
Java 11+ HttpClient | 官方推荐、现代、支持异步、性能好、无需额外依赖。 | Java 11 以下版本不可用。 |
| OkHttp | API 极其简洁、功能强大(连接池、拦截器)、社区活跃。 | 需要引入第三方库。 | |
| HttpURLConnection | JDK 内置、无需额外依赖。 | API 过时、功能有限、使用繁琐。 |
如何选择?
- 如果你在写 Web 服务器(后端应用):
- 如果使用 Spring Boot,直接在方法参数里注入
HttpServletRequest。 - 如果学习或使用原生 Java EE,使用
HttpServletRequest对象。
- 如果使用 Spring Boot,直接在方法参数里注入
- 如果你在写一个客户端程序去调用 API:
- 优先使用 Java 11+ 的
HttpClient,它是未来趋势。 - 如果项目不能升级 Java 版本,或者需要更简洁的 API,OkHttp 是绝佳选择。
HttpURLConnection仅在不允许任何第三方依赖的极端情况下使用。
- 优先使用 Java 11+ 的
