杰瑞科技汇

Java POST提交数据时,如何正确处理请求体?

  1. POST 请求的本质是什么? (数据如何编码)
  2. 如何发送一个简单的 POST 请求? (原生 HttpURLConnection)
  3. 如何发送包含 JSON 数据的 POST 请求? (最现代、最常见的方式)
  4. 如何发送包含 Form 表单数据的 POST 请求?
  5. 如何在 Spring Boot 中接收和处理 POST 请求?

POST 请求的本质:两种主要的编码方式

在发送 POST 请求时,数据需要被编码后放在 HTTP 请求体中,最常见的两种编码方式是:

Java POST提交数据时,如何正确处理请求体?-图1
(图片来源网络,侵删)
  • 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 请求 (推荐)

在实际开发中,强烈推荐使用第三方网络库,如 OkHttpApache 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 便捷

核心要点回顾:

  1. 明确编码类型:发送前要确定是 application/x-www-form-urlencoded 还是 application/json,并设置正确的 Content-Type 请求头。
  2. 客户端发送:对于 Java 客户端,OkHttp 是首选,发送 JSON 数据时,使用 RequestBody.create(jsonString, MediaType.get("application/json"))
  3. 服务端接收:在 Spring Boot 中,接收 Form 数据用 @ModelAttribute,接收 JSON 数据用 @RequestBody
  4. 编码处理:手动处理数据时,不要忘记对数据进行 URL 编码(URLEncoder),OkHttp 和 Spring Boot 会自动处理。
分享:
扫描分享到社交APP
上一篇
下一篇