HttpClient 是 Java 領域最常用的 HTTP 客戶端庫。本文總結 HttpClient 4.x 中各類 POST 請求的典型用法,涵蓋基本表單提交、認證、JSON 傳輸、Fluent API、Multipart 文件上傳及上傳進度監控,供開發快速查閱。
使用 UrlEncodedFormEntity 封裝鍵值對參數:
@Test
public void basicPost() throws Exception {
CloseableHttpClient client = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("https://www.example.com");
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("username", "John"));
params.add(new BasicNameValuePair("password", "pass"));
httpPost.setEntity(new UrlEncodedFormEntity(params));
CloseableHttpResponse response = client.execute(httpPost);
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
client.close();
}
在 Header 中加入認證信息:
@Test
public void postWithAuth() throws Exception {
CloseableHttpClient client = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("https://www.example.com");
httpPost.setEntity(new StringEntity("test post"));
UsernamePasswordCredentials creds = new UsernamePasswordCredentials("John", "pass");
httpPost.addHeader(new BasicScheme().authenticate(creds, httpPost, null));
CloseableHttpResponse response = client.execute(httpPost);
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
client.close();
}
設置 Content-Type 為 application/json:
@Test
public void postJson() throws Exception {
CloseableHttpClient client = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("https://www.example.com");
String json = "{\"id\":1,\"name\":\"John\"}";
StringEntity entity = new StringEntity(json);
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
CloseableHttpResponse response = client.execute(httpPost);
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
client.close();
}
鏈式調用,代碼更簡潔:
@Test
public void postFluent() throws Exception {
HttpResponse response = Request.Post("https://www.example.com")
.bodyForm(Form.form().add("username", "John").add("password", "pass").build())
.execute().returnResponse();
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}
使用 MultipartEntityBuilder 構建多部分實體:
@Test
public void postMultipart() throws Exception {
CloseableHttpClient client = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("https://www.example.com");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("username", "John");
builder.addTextBody("password", "pass");
builder.addBinaryBody("file", new File("test.txt"), ContentType.APPLICATION_OCTET_STREAM, "file.ext");
httpPost.setEntity(builder.build());
CloseableHttpResponse response = client.execute(httpPost);
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
client.close();
}
僅上傳文件二進制流:
@Test
public void uploadFile() throws Exception {
CloseableHttpClient client = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("https://www.example.com");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addBinaryBody("file", new File("test.txt"), ContentType.APPLICATION_OCTET_STREAM, "file.ext");
httpPost.setEntity(builder.build());
CloseableHttpResponse response = client.execute(httpPost);
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
client.close();
}
通過擴展 HttpEntityWrapper 實現進度回調:
// 進度監聽接口
public interface ProgressListener { void progress(float percentage); }
// 包裝實體,寫入時統計已傳輸字節
public class ProgressEntityWrapper extends HttpEntityWrapper {
private ProgressListener listener;
public ProgressEntityWrapper(HttpEntity entity, ProgressListener listener) {
super(entity); this.listener = listener;
}
@Override public void writeTo(OutputStream out) throws IOException {
super.writeTo(new CountingOutputStream(out, listener, getContentLength()));
}
}
// 計數輸出流
public static class CountingOutputStream extends FilterOutputStream {
private ProgressListener listener; private long transferred; private long totalBytes;
public CountingOutputStream(OutputStream out, ProgressListener listener, long totalBytes) {
super(out); this.listener = listener; this.totalBytes = totalBytes;
}
@Override public void write(byte[] b, int off, int len) throws IOException {
out.write(b, off, len); transferred += len; listener.progress(getCurrentProgress());
}
@Override public void write(int b) throws IOException { out.write(b); transferred++; listener.progress(getCurrentProgress()); }
private float getCurrentProgress() { return ((float) transferred / totalBytes) * 100; }
}
// 使用示例
@Test
public void uploadWithProgress() throws Exception {
CloseableHttpClient client = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("https://www.example.com");
HttpEntity multipart = MultipartEntityBuilder.create()
.addBinaryBody("file", new File("test.txt"), ContentType.APPLICATION_OCTET_STREAM, "file.ext")
.build();
httpPost.setEntity(new ProgressEntityWrapper(multipart, percentage -> {
System.out.println("上傳進度: " + percentage + "%");
assertFalse(Float.compare(percentage, 100) > 0);
}));
CloseableHttpResponse response = client.execute(httpPost);
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
client.close();
}
HttpClient 4.x 提供了豐富的 API 滿足各種 POST 場景。實際開發中,建議配合連接池管理客端實例,並妥善關閉響應流以釋放資源。