基础请求

基础请求

Get

OkHttpClient client = new OkHttpClient();

String run(String url) throws IOException {
  Request request = new Request.Builder()
      .url(url)
      .build();

  try (Response response = client.newCall(request).execute()) {
    return response.body().string();
  }
}

要发送同步的 GET 请求,我们需要基于 URL 构建一个 Request 对象并进行调用。执行之后,OkHttp 返回一个 Response 实例:

@Test
public void whenGetRequest_thenCorrect() throws IOException {
    Request request = new Request.Builder()
      .url(BASE_URL + "/date")
      .build();

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

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

现在,要进行异步 GET,我们需要排队一个 Call。回调使我们可以读取可读的响应,这是在响应头准备好之后发生的。读取响应正文可能仍然会阻塞。OkHttp 当前不提供任何异步 API 来部分接收响应正文:

@Test
public void whenAsynchronousGetRequest_thenCorrect() {
    Request request = new Request.Builder()
      .url(BASE_URL + "/date")
      .build();

    Call call = client.newCall(request);
    call.enqueue(new Callback() {
        public void onResponse(Call call, Response response)
          throws IOException {
            // ...
        }

        public void onFailure(Call call, IOException e) {
            fail();
        }
    });
}

最后,要将查询参数添加到 GET 请求中,我们可以利用 HttpUrl.Builder。我们可以将构建好的请求传递给我们的 Request 对象:

@Test
public void whenGetRequestWithQueryParameter_thenCorrect()
  throws IOException {

    HttpUrl.Builder urlBuilder
      = HttpUrl.parse(BASE_URL + "/ex/bars").newBuilder();
    urlBuilder.addQueryParameter("id", "1");

    String url = urlBuilder.build().toString();

    Request request = new Request.Builder()
      .url(url)
      .build();
    Call call = client.newCall(request);
    Response response = call.execute();

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

Post

public static final MediaType JSON
    = MediaType.get("application/json; charset=utf-8");

OkHttpClient client = new OkHttpClient();

String post(String url, String json) throws IOException {
  RequestBody body = RequestBody.create(JSON, json);
  Request request = new Request.Builder()
      .url(url)
      .post(body)
      .build();
  try (Response response = client.newCall(request).execute()) {
    return response.body().string();
  }
}

表单构建

让我们看一个简单的 POST 请求,在其中构建一个 RequestBody 来发送参数 username 和 password:

@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(BASE_URL + "/users")
      .post(formBody)
      .build();

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

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

我们也可以构建 MultipartBody 的请求:

@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(BASE_URL + "/users/multipart")
      .post(requestBody)
      .build();

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

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

认证

如果要验证请求,可以使用 Credentials.basic 构建器将凭证添加到标头。在这个简单的示例中,我们还将发送一个 String 作为请求的主体:

@Test
public void whenSendPostRequestWithAuthorization_thenCorrect()
  throws IOException {
    String postBody = "test post";

    Request request = new Request.Builder()
      .url(URL_SECURED_BY_BASIC_AUTHENTICATION)
      .addHeader("Authorization", Credentials.basic("username", "password"))
      .post(RequestBody.create(
        MediaType.parse("text/x-markdown), postBody))
      .build();

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

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

JSON

为了在请求正文中发送 JSON,我们必须设置其媒体类型 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(BASE_URL + "/users/detail")
      .post(body)
      .build();

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

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

编码

如果我们要使用其他字符编码,可以将其作为 MediaType.parse() 的第二个参数传递:

@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"));
}

@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"));
}
下一页