1. 简介

我们在《OkHttp 使用指南》一文中已经介绍了 OkHttp 客户端的基础用法。

本文则聚焦于 OkHttp 3.x 版本中,如何发送各种类型的 POST 请求。内容虽短,但覆盖了日常开发中最常见的几种场景,帮你少踩坑、提升效率。


2. 基础 POST 请求

✅ 最常见的表单提交场景,比如登录、注册等,使用 FormBody.Builder 构建请求体即可。

它会自动将参数编码为 application/x-www-form-urlencoded 格式,简单粗暴又实用。

@Test
public void whenSendPostRequest_thenCorrect() 
  throws IOException {
    RequestBody formBody = new FormBody.Builder()
      .add("username", "test")
      .add("password", "test")
      .build();

    Request request = new Request.Builder()
      .url("https://api.example.com/users")
      .post(formBody)
      .build();

    Call call = client.newCall(request);
    Response response = call.execute();
    
    assertThat(response.code(), equalTo(200));
}

⚠️ 注意:.post(formBody) 必须显式调用,否则默认是 GET。


3. 带认证的 POST 请求

❌ 很多人手动拼 Authorization 头,容易出错。推荐使用 OkHttp 自带的 Credentials.basic() 工具方法,自动完成 Base64 编码。

适用于 Basic Auth 场景(虽然现在用得少了,但对接老系统时还是常遇到)。

@Test
public void whenSendPostRequestWithAuthorization_thenCorrect() 
  throws IOException {
    String postBody = "test post";
    
    Request request = new Request.Builder()
      .url("https://api.example.com/secure-endpoint")
      .addHeader("Authorization", Credentials.basic("admin", "secret123"))
      .post(RequestBody.create(
        MediaType.parse("text/x-markdown"), postBody))
      .build();

    Call call = client.newCall(request);
    Response response = call.execute();

    assertThat(response.code(), equalTo(200));
}

📌 小贴士:MediaType.parse() 参数记得检查引号闭合,上面代码原示例有语法错误(少了一个引号),已修复。


4. 发送 JSON 数据

✅ 当前主流的接口通信格式,必须设置 Content-Type: application/json

通过 RequestBody.create() 指定媒体类型即可。

@Test
public void whenPostJson_thenCorrect() throws IOException {
    String json = "{\"id\":1,\"name\":\"John\"}";

    RequestBody body = RequestBody.create(
      MediaType.parse("application/json"), json);

    Request request = new Request.Builder()
      .url("https://api.example.com/users/detail")
      .post(body)
      .build();
 
    Call call = client.newCall(request);
    Response response = call.execute();

    assertThat(response.code(), equalTo(200));
}

💡 建议:实际项目中通常配合 Jackson/Gson 将对象序列化为 JSON 字符串后再发送,避免手拼字符串出错。


5. 多部分请求(Multipart POST)

✅ 文件上传 + 表单字段混合提交的标准做法。

使用 MultipartBody.Builder,并设置 .setType(MultipartBody.FORM),这是关键!

@Test
public void whenSendMultipartRequest_thenCorrect() 
  throws IOException {    
    RequestBody requestBody = new MultipartBody.Builder()
      .setType(MultipartBody.FORM)
      .addFormDataPart("username", "test")
      .addFormDataPart("password", "test")
      .addFormDataPart("file", "file.txt",
        RequestBody.create(MediaType.parse("application/octet-stream"), 
          new File("src/test/resources/test.txt")))
      .build();

    Request request = new Request.Builder()
      .url("https://api.example.com/users/multipart")
      .post(requestBody)
      .build();

    Call call = client.newCall(request);
    Response response = call.execute();

    assertThat(response.code(), equalTo(200));
}

📌 注意事项:

  • addFormDataPart 用于添加普通字段或文件
  • 文件部分需用 RequestBody.create 指定文件内容和 MIME 类型
  • 常见类型如 image/jpeg, application/pdf 等可根据文件扩展名动态设置

6. 自定义字符编码

OkHttp 默认使用 UTF-8 编码,大多数情况下没问题。

但如果你对接的是某些老旧系统,可能要求使用 UTF-16 或其他编码,这时就需要手动指定。

6.1 默认编码验证

@Test
public void whenPostJsonWithoutCharset_thenCharsetIsUtf8() throws IOException {
    final String json = "{\"id\":1,\"name\":\"John\"}";

    final RequestBody body = RequestBody.create(
        MediaType.parse("application/json"), json);

    String charset = body.contentType().charset().displayName();

    assertThat(charset, equalTo("UTF-8"));
}

6.2 指定 UTF-16 编码

@Test
public void whenPostJsonWithUtf16Charset_thenCharsetIsUtf16() throws IOException {
    final String json = "{\"id\":1,\"name\":\"John\"}";

    final RequestBody body = RequestBody.create(
        MediaType.parse("application/json; charset=utf-16"), json);

    String charset = body.contentType().charset().displayName();

    assertThat(charset, equalTo("UTF-16"));
}

⚠️ 踩坑提醒:服务端必须支持该编码格式,否则会解析失败。建议优先使用 UTF-8,除非有特殊需求。


7. 总结

本文涵盖了 OkHttp 发送 POST 请求的五种典型场景:

  • ✅ 普通表单提交
  • ✅ 带 Basic Auth 的请求
  • ✅ JSON 数据传输
  • ✅ 文件上传(Multipart)
  • ✅ 自定义字符编码处理

这些例子覆盖了绝大多数实际开发中的需求。建议集合备用,避免每次都要查文档。

示例代码已整理至 GitHub:https://github.com/yourname/tutorials/tree/master/libraries-http


原始标题:A Quick Guide to Post Requests with OkHttp