# Bài 8: HTTP Client API (Java 11)

#### Mục tiêu

Bài viết này nhằm mục đích giúp bạn hiểu và sử dụng HTTP Client API mới trong Java 11. Chúng ta sẽ xem xét các vấn đề với API cũ, các thành phần chính của HTTP Client API, các phương thức quan trọng và các ví dụ thực tế.

#### Nội dung

### 1\. Giới thiệu về HTTP Client API

#### 1.1 Vấn đề với API cũ

* **Hạn chế của** `HttpURLConnection`:
    
    * `HttpURLConnection` là API cũ để thực hiện các yêu cầu HTTP. Nó phức tạp, khó sử dụng và thiếu tính năng hiện đại.
        
    * Không hỗ trợ HTTP/2, không tích hợp tốt với lập trình không đồng bộ và lập trình phản ứng (reactive programming).
        
    * Ví dụ:
        
        ```java
        URL url = new URL("http://example.com");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        
        int responseCode = connection.getResponseCode();
        InputStream responseStream = connection.getInputStream();
        ```
        

#### 1.2 Mục đích và lợi ích của HTTP Client API

* **Mục đích:**
    
    * HTTP Client API được giới thiệu trong Java 11 để thay thế `HttpURLConnection`, cung cấp một API hiện đại, dễ sử dụng và mạnh mẽ cho việc thực hiện các yêu cầu HTTP.
        
* **Lợi ích:**
    
    * Hỗ trợ HTTP/1.1 và HTTP/2.
        
    * Tích hợp tốt với lập trình không đồng bộ và lập trình phản ứng.
        
    * Cung cấp các phương thức tiện lợi và rõ ràng để thực hiện các yêu cầu HTTP.
        

### 2\. Các thành phần chính của HTTP Client API

#### 2.1 HttpClient

* **Mục đích:** Đại diện cho một HTTP client, dùng để gửi các yêu cầu HTTP.
    
* **Tạo HttpClient:**
    
    ```java
    HttpClient client = HttpClient.newHttpClient();
    ```
    

#### 2.2 HttpRequest

* **Mục đích:** Đại diện cho một yêu cầu HTTP.
    
* **Tạo HttpRequest:**
    
    ```java
    HttpRequest request = HttpRequest.newBuilder()
                                     .uri(URI.create("http://example.com"))
                                     .GET()
                                     .build();
    ```
    

#### 2.3 HttpResponse

* **Mục đích:** Đại diện cho một phản hồi HTTP.
    
* **Xử lý HttpResponse:**
    
    ```java
    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    int statusCode = response.statusCode();
    String responseBody = response.body();
    ```
    

### 3\. Các phương thức quan trọng của HTTP Client API

#### 3.1 Gửi yêu cầu đồng bộ

* **Ví dụ:**
    
    ```java
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
                                     .uri(URI.create("http://example.com"))
                                     .GET()
                                     .build();
    
    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    
    int statusCode = response.statusCode();
    String responseBody = response.body();
    
    System.out.println("Status code: " + statusCode);
    System.out.println("Response body: " + responseBody);
    ```
    

#### 3.2 Gửi yêu cầu không đồng bộ

* **Ví dụ:**
    
    ```java
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
                                     .uri(URI.create("http://example.com"))
                                     .GET()
                                     .build();
    
    CompletableFuture<HttpResponse<String>> futureResponse = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
    
    futureResponse.thenApply(HttpResponse::body)
                  .thenAccept(System.out::println)
                  .join();
    ```
    

#### 3.3 Gửi yêu cầu POST

* **Ví dụ:**
    
    ```java
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
                                     .uri(URI.create("http://example.com/post"))
                                     .POST(HttpRequest.BodyPublishers.ofString("Hello, World!"))
                                     .build();
    
    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    
    int statusCode = response.statusCode();
    String responseBody = response.body();
    
    System.out.println("Status code: " + statusCode);
    System.out.println("Response body: " + responseBody);
    ```
    

#### 3.4 Xử lý HTTP/2

* **Ví dụ:**
    
    ```java
    HttpClient client = HttpClient.newBuilder()
                                  .version(HttpClient.Version.HTTP_2)
                                  .build();
    
    HttpRequest request = HttpRequest.newBuilder()
                                     .uri(URI.create("https://http2.akamai.com/demo"))
                                     .GET()
                                     .build();
    
    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    
    int statusCode = response.statusCode();
    String responseBody = response.body();
    
    System.out.println("Status code: " + statusCode);
    System.out.println("Response body: " + responseBody);
    ```
    

#### 3.5 Sử dụng Headers

* **Ví dụ:**
    
    ```java
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
                                     .uri(URI.create("http://example.com"))
                                     .header("User-Agent", "Java 11 HttpClient Bot")
                                     .GET()
                                     .build();
    
    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    
    int statusCode = response.statusCode();
    String responseBody = response.body();
    
    System.out.println("Status code: " + statusCode);
    System.out.println("Response body: " + responseBody);
    ```
    

#### 3.6 Xử lý JSON

* **Ví dụ:**
    
    ```java
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class HttpClientExample {
        public static void main(String[] args) throws Exception {
            HttpClient client = HttpClient.newHttpClient();
            HttpRequest request = HttpRequest.newBuilder()
                                             .uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
                                             .GET()
                                             .build();
    
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    
            ObjectMapper mapper = new ObjectMapper();
            Post post = mapper.readValue(response.body(), Post.class);
    
            System.out.println("Post ID: " + post.getId());
            System.out.println("Title: " + post.getTitle());
        }
    
        public static class Post {
            private int id;
            private String title;
    
            // Getters and setters
            public int getId() { return id; }
            public void setId(int id) { this.id = id; }
            public String getTitle() { return title; }
            public void setTitle(String title) { this.title = title; }
        }
    }
    ```
    

### 4\. Ví dụ thực tế sử dụng HTTP Client API

#### 4.1 Gửi yêu cầu GET và xử lý phản hồi

* **Ví dụ:**
    
    ```java
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
                                     .uri(URI.create("http://example.com"))
                                     .GET()
                                     .build();
    
    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    
    int statusCode = response.statusCode();
    String responseBody = response.body();
    
    System.out.println("Status code: " + statusCode);
    System.out.println("Response body: " + responseBody);
    ```
    

#### 4.2 Gửi yêu cầu POST với JSON payload

* **Ví dụ:**
    
    ```java
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class HttpClientExample {
        public static void main(String[] args) throws Exception {
            HttpClient client = HttpClient.newHttpClient();
            ObjectMapper mapper = new ObjectMapper();
    
            Post post = new Post();
            post.setTitle("Hello, World!");
            String json = mapper.writeValueAsString(post);
    
            HttpRequest request = HttpRequest.newBuilder()
                                             .uri(URI.create("https://jsonplaceholder.typicode.com/posts"))
                                             .header("Content-Type", "application/json")
                                             .POST(HttpRequest.BodyPublishers.ofString(json))
                                             .build();
    
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    
            int statusCode = response.statusCode();
            String responseBody = response.body();
    
            System.out.println("Status code: " + statusCode);
            System.out.println("Response body: " + responseBody);
        }
    
        public static class Post {
            private String title;
    
            // Getters and setters
            public String getTitle() { return title; }
            public void setTitle(String title) { this.title = title; }
        }
    }
    ```
    

#### 4.3 Gửi yêu cầu không đồng bộ và xử lý kết quả

* **Ví dụ:**
    
    ```java
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
                                     .uri(URI.create("http://example.com"))
                                     .GET()
                                     .build();
    
    CompletableFuture<HttpResponse<String>> futureResponse = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
    
    futureResponse.thenApply(HttpResponse::body)
                  .thenAccept(System.out::println)
                  .join();
    ```
    

### 5\. Thực hành với các bài

toán thực tế

#### 5.1 Tải tệp từ URL và lưu vào tệp hệ thống

* **Bài toán:** Tải một tệp từ URL và lưu nó vào tệp hệ thống.
    
* **Giải pháp:**
    
    ```java
    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.nio.file.StandardOpenOption;
    import java.net.URI;
    import java.net.http.HttpClient;
    import java.net.http.HttpRequest;
    import java.net.http.HttpResponse;
    
    public class FileDownloadExample {
        public static void main(String[] args) throws IOException, InterruptedException {
            HttpClient client = HttpClient.newHttpClient();
            HttpRequest request = HttpRequest.newBuilder()
                                             .uri(URI.create("http://example.com/file.zip"))
                                             .GET()
                                             .build();
    
            HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
    
            Files.write(Paths.get("file.zip"), response.body(), StandardOpenOption.CREATE);
            System.out.println("File downloaded successfully!");
        }
    }
    ```
    

#### 5.2 Kiểm tra trạng thái của một URL

* **Bài toán:** Kiểm tra xem một URL có hoạt động hay không bằng cách gửi yêu cầu HEAD.
    
* **Giải pháp:**
    
    ```java
    import java.net.URI;
    import java.net.http.HttpClient;
    import java.net.http.HttpRequest;
    import java.net.http.HttpResponse;
    
    public class URLStatusChecker {
        public static void main(String[] args) throws Exception {
            HttpClient client = HttpClient.newHttpClient();
            HttpRequest request = HttpRequest.newBuilder()
                                             .uri(URI.create("http://example.com"))
                                             .method("HEAD", HttpRequest.BodyPublishers.noBody())
                                             .build();
    
            HttpResponse<Void> response = client.send(request, HttpResponse.BodyHandlers.discarding());
    
            int statusCode = response.statusCode();
            System.out.println("Status code: " + statusCode);
        }
    }
    ```
    

#### 5.3 Đăng nhập vào một dịch vụ web

* **Bài toán:** Gửi yêu cầu POST để đăng nhập vào một dịch vụ web và lưu cookie phản hồi.
    
* **Giải pháp:**
    
    ```java
    import java.net.CookieManager;
    import java.net.CookiePolicy;
    import java.net.URI;
    import java.net.http.HttpClient;
    import java.net.http.HttpRequest;
    import java.net.http.HttpResponse;
    import java.util.List;
    import java.util.Map;
    
    public class WebLoginExample {
        public static void main(String[] args) throws Exception {
            CookieManager cookieManager = new CookieManager();
            cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
    
            HttpClient client = HttpClient.newBuilder()
                                          .cookieHandler(cookieManager)
                                          .build();
    
            HttpRequest request = HttpRequest.newBuilder()
                                             .uri(URI.create("http://example.com/login"))
                                             .header("Content-Type", "application/x-www-form-urlencoded")
                                             .POST(HttpRequest.BodyPublishers.ofString("username=user&password=pass"))
                                             .build();
    
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    
            System.out.println("Status code: " + response.statusCode());
            System.out.println("Response body: " + response.body());
    
            // Lấy cookie từ phản hồi
            Map<String, List<String>> headers = response.headers().map();
            List<String> cookies = headers.get("Set-Cookie");
            if (cookies != null) {
                cookies.forEach(System.out::println);
            }
        }
    }
    ```
    

### Kết luận

HTTP Client API trong Java 11 mang lại một cách tiếp cận hiện đại và mạnh mẽ để thực hiện các yêu cầu HTTP. Với hỗ trợ cho HTTP/2, lập trình không đồng bộ và các tính năng tiện lợi khác, HTTP Client API giúp lập trình viên thực hiện các tác vụ HTTP một cách dễ dàng và hiệu quả. Hiểu và sử dụng thành thạo HTTP Client API sẽ giúp bạn tận dụng tối đa sức mạnh của Java 11 trong việc giao tiếp với các dịch vụ web và API.

---
