Java HTTP Client (Java 11+)
Java 11 引入了新的 HttpClient API,提供現代化的 HTTP 請求功能,支援同步和非同步操作、HTTP/2 等。
引入套件
import java.net.http.*;
import java.net.URI;
建立 HttpClient
// 使用預設設定
HttpClient client = HttpClient.newHttpClient();
// 自訂設定
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.followRedirects(HttpClient.Redirect.NORMAL)
.connectTimeout(Duration.ofSeconds(10))
.build();
GET 請求
同步請求
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("狀態碼: " + response.statusCode());
System.out.println("回應: " + response.body());
非同步請求
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users"))
.build();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join();
POST 請求
// JSON 資料
String json = """
{
"name": "Alice",
"email": "alice@example.com"
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
設定請求標頭
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/data"))
.header("Authorization", "Bearer " + token)
.header("Accept", "application/json")
.header("User-Agent", "Java HttpClient")
.build();
其他 HTTP 方法
// PUT
HttpRequest put = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users/1"))
.PUT(HttpRequest.BodyPublishers.ofString(json))
.build();
// DELETE
HttpRequest delete = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users/1"))
.DELETE()
.build();
// PATCH(自訂方法)
HttpRequest patch = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users/1"))
.method("PATCH", HttpRequest.BodyPublishers.ofString(json))
.build();
處理回應
不同的 BodyHandler
// 字串
HttpResponse<String> strResponse = client.send(request, HttpResponse.BodyHandlers.ofString());
// 位元組陣列
HttpResponse<byte[]> bytesResponse = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
// 串流
HttpResponse<InputStream> streamResponse = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
// 寫入檔案
HttpResponse<Path> fileResponse = client.send(request,
HttpResponse.BodyHandlers.ofFile(Path.of("output.txt")));
// 捨棄(只關心狀態碼)
HttpResponse<Void> discardResponse = client.send(request, HttpResponse.BodyHandlers.discarding());
取得回應資訊
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode();
String body = response.body();
HttpHeaders headers = response.headers();
URI uri = response.uri();
// 取得特定標頭
Optional<String> contentType = headers.firstValue("Content-Type");
List<String> cookies = headers.allValues("Set-Cookie");
超時設定
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/data"))
.timeout(Duration.ofSeconds(30)) // 請求超時
.build();
表單提交
String formData = "username=alice&password=secret";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/login"))
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(formData))
.build();
實用範例
REST API 封裝
public class ApiClient {
private final HttpClient client;
private final String baseUrl;
public ApiClient(String baseUrl) {
this.baseUrl = baseUrl;
this.client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
}
public String get(String path) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + path))
.GET()
.build();
return client.send(request, HttpResponse.BodyHandlers.ofString()).body();
}
public String post(String path, String json) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + path))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
return client.send(request, HttpResponse.BodyHandlers.ofString()).body();
}
}
// 使用
ApiClient api = new ApiClient("https://api.example.com");
String users = api.get("/users");
String result = api.post("/users", """{"name":"Alice"}""");
並行請求
HttpClient client = HttpClient.newHttpClient();
List<URI> uris = List.of(
URI.create("https://api.example.com/user/1"),
URI.create("https://api.example.com/user/2"),
URI.create("https://api.example.com/user/3")
);
List<CompletableFuture<String>> futures = uris.stream()
.map(uri -> HttpRequest.newBuilder(uri).build())
.map(request -> client.sendAsync(request, HttpResponse.BodyHandlers.ofString()))
.map(future -> future.thenApply(HttpResponse::body))
.collect(Collectors.toList());
// 等待全部完成
List<String> results = futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
重點整理
- Java 11+ 的
HttpClient提供現代化 HTTP API - 支援同步(
send)和非同步(sendAsync)請求 - 支援 HTTP/2 和 WebSocket
- 使用 Builder 模式設定請求和客戶端
BodyHandlers提供多種回應處理方式- 搭配
CompletableFuture進行並行請求