- POST 请求的本质是什么? (数据如何编码)
- 如何发送一个简单的 POST 请求? (原生
HttpURLConnection) - 如何发送包含 JSON 数据的 POST 请求? (最现代、最常见的方式)
- 如何发送包含 Form 表单数据的 POST 请求?
- 如何在 Spring Boot 中接收和处理 POST 请求?
POST 请求的本质:两种主要的编码方式
在发送 POST 请求时,数据需要被编码后放在 HTTP 请求体中,最常见的两种编码方式是:

-
application/x-www-form-urlencoded(表单编码)- 这是最传统的方式,早期 HTML 表单默认使用它。
- 数据格式是
key1=value1&key2=value2。 - 空格会被转换为 ,特殊字符会被进行 URL 编码(
&变成%26)。 - 适用场景:传统的登录、注册表单提交。
-
application/json(JSON 编码)- 这是现代 Web API 最主流的方式。
- 数据是一个完整的 JSON 对象,如
{"username": "zhangsan", "password": "123456"}。 - 适用场景:前后端分离的 RESTful API 交互,传递结构化数据。
理解这两种编码方式是后续所有操作的基础。
使用原生 Java (HttpURLConnection) 发送 POST 请求
Java 标准库中的 java.net.HttpURLConnection 是最基础的方式,不需要引入任何第三方依赖,但它的代码比较冗长。
示例:发送 Form 表单数据 (application/x-www-form-urlencoded)
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
public class NativePostExample {
public static void main(String[] args) throws Exception {
// 1. 创建 URL 对象
String urlString = "https://example.com/api/login";
URL url = new URL(urlString);
// 2. 打开连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 3. 设置请求方法为 POST
connection.setRequestMethod("POST");
// 4. 设置请求头
// 表单提交需要设置 Content-Type
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
// 允许输入输出流
connection.setDoOutput(true);
// 5. 准备要提交的数据
String username = "test_user";
String password = "test_password";
// 注意:需要对数据进行 URL 编码
String urlParameters = "username=" + URLEncoder.encode(username, StandardCharsets.UTF_8.name()) +
"&password=" + URLEncoder.encode(password, StandardCharsets.UTF_8.name());
// 6. 将数据写入请求体
try (DataOutputStream out = new DataOutputStream(connection.getOutputStream())) {
out.write(urlParameters.getBytes(StandardCharsets.UTF_8));
out.flush();
}
// 7. 获取响应码
int responseCode = connection.getResponseCode();
System.out.println("POST Response Code: " + responseCode);
// 8. 读取响应内容
if (responseCode == HttpURLConnection.HTTP_OK) { // 200
try (BufferedReader in = new BufferedReader(
new InputStreamReader(connection.getInputStream()))) {
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
System.out.println("Response: " + response.toString());
}
} else {
System.out.println("POST request failed");
}
}
}
使用第三方库 OkHttp 发送 POST 请求 (推荐)
在实际开发中,强烈推荐使用第三方网络库,如 OkHttp 或 Apache HttpClient,它们极大地简化了代码,并提供了更强大的功能(如异步请求、连接池等)。
添加 OkHttp 依赖 (Maven):
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version> <!-- 使用最新版本 -->
</dependency>
示例 1:发送 Form 表单数据
import okhttp3.*;
import java.io.IOException;
public class OkHttpFormPostExample {
public static void main(String[] args) {
// 1. 创建 OkHttpClient 实例
OkHttpClient client = new OkHttpClient();
// 2. 构建表单数据 (FormBody)
// OkHttp 会自动处理 URL 编码
FormBody formBody = new FormBody.Builder()
.add("username", "test_user")
.add("password", "test_password")
.build();
// 3. 创建 Request 对象
Request request = new Request.Builder()
.url("https://example.com/api/login")
.post(formBody) // 设置 POST 请求体
.build();
// 4. 发送请求并处理响应
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
// 获取响应体
String responseBody = response.body().string();
System.out.println("Response: " + responseBody);
} catch (IOException e) {
e.printStackTrace();
}
}
}
示例 2:发送 JSON 数据 (最常用)
这是现代 API 交互的标准方式。
import okhttp3.*;
import java.io.IOException;
public class OkHttpJsonPostExample {
public static void main(String[] args) {
OkHttpClient client = new OkHttpClient();
// 1. 准备 JSON 数据
String jsonBody = "{\"username\": \"zhangsan\", \"password\": \"123456\", \"email\": \"zhangsan@example.com\"}";
// 2. 构建请求体 (RequestBody)
// MediaType 指定了内容类型为 JSON
MediaType JSON = MediaType.get("application/json; charset=utf-8");
RequestBody body = RequestBody.create(jsonBody, JSON);
// 3. 创建 Request 对象
Request request = new Request.Builder()
.url("https://example.com/api/users")
.post(body)
.build();
// 4. 发送请求
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
String responseBody = response.body().string();
System.out.println("Response: " + responseBody);
} catch (IOException e) {
e.printStackTrace();
}
}
}
在 Spring Boot 中接收 POST 请求
Java 应用更多时候是作为服务器端,接收和处理来自客户端的 POST 请求,Spring Boot 提供了极其简洁和强大的方式。
示例:接收 Form 表单数据
创建一个 DTO (Data Transfer Object) 类来接收数据。
UserForm.java
public class UserForm {
private String username;
private String password;
// 必须有无参构造函数
public UserForm() {}
// Getters and Setters
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
}
UserController.java
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.ui.Model;
@Controller
public class UserController {
@PostMapping("/register") // 映射 POST 请求到 /register 路径
public String handleFormSubmission(@ModelAttribute UserForm userForm, Model model) {
// @ModelAttribute 会自动将请求中的 Form 数据绑定到 userForm 对象中
System.out.println("Received user: " + userForm.getUsername());
// 将接收到的数据添加到模型中,用于在视图(如 JSP, Thymeleaf)中显示
model.addAttribute("message", "User " + userForm.getUsername() + " registered successfully!");
// 返回视图名称
return "result"; // 假设你有一个名为 result.html 的模板文件
}
}
示例:接收 JSON 数据
这需要添加 jackson-databind 依赖(Spring Boot Web starter 通常已经包含它)。
User.java (一个标准的 POJO)
public class User {
private String username;
private String password;
private String email;
// Getters, Setters, and no-args constructor
// (Lombok @Data 注解可以自动生成这些)
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
// ... 其他 getter/setter
}
UserController.java
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController // @RestController = @Controller + @ResponseBody,直接返回 JSON
public class UserController {
@PostMapping("/api/users") // 映射 POST 请求到 /api/users 路径
public String createUser(@RequestBody User user) {
// @RequestBody 会自动将请求体中的 JSON 数据反序列化成 User 对象
System.out.println("Creating user: " + user.getUsername());
// 在实际应用中,这里会将 user 对象保存到数据库
// ...
// 直接返回一个字符串,Spring Boot 会自动将其作为响应体返回
// 返回 JSON 对象更常见:return ResponseEntity.ok(user);
return "User " + user.getUsername() + " created with email " + user.getEmail();
}
}
总结与对比
| 场景 | 推荐方式 | 优点 | 缺点 |
|---|---|---|---|
| Java 客户端发送请求 | OkHttp | 代码简洁、功能强大(异步、拦截器)、性能好 | 需要引入第三方依赖 |
HttpURLConnection |
Java 标准库,无需额外依赖 | 代码冗长、功能有限 | |
| Java 服务端接收请求 | Spring Boot | 配置极其简单、与生态系统无缝集成、功能强大 | 项目相对较重,不适合简单的独立脚本 |
| Servlet API | 标准、灵活,可嵌入任何 Java Web 容器 | 需要更多模板代码,不如 Spring Boot 便捷 |
核心要点回顾:
- 明确编码类型:发送前要确定是
application/x-www-form-urlencoded还是application/json,并设置正确的Content-Type请求头。 - 客户端发送:对于 Java 客户端,OkHttp 是首选,发送 JSON 数据时,使用
RequestBody.create(jsonString, MediaType.get("application/json"))。 - 服务端接收:在 Spring Boot 中,接收 Form 数据用
@ModelAttribute,接收 JSON 数据用@RequestBody。 - 编码处理:手动处理数据时,不要忘记对数据进行 URL 编码(
URLEncoder),OkHttp 和 Spring Boot 会自动处理。
