跳转至

Java API 请求:如何等待请求完成

简介

在 Java 开发中,我们经常需要与外部 API 进行交互。当发起一个 API 请求时,很多时候我们需要等待请求完成并获取响应结果后,才能继续后续的操作。本文将详细介绍如何在 Java 中等待 API 请求完成,涵盖基础概念、使用方法、常见实践以及最佳实践,帮助读者深入理解并高效运用相关技术。

目录

  1. 基础概念
  2. 使用方法
    • 同步请求
    • 异步请求与等待
  3. 常见实践
    • 使用 HttpURLConnection
    • 使用 OkHttp
  4. 最佳实践
    • 超时处理
    • 错误处理
  5. 小结
  6. 参考资料

基础概念

同步请求

同步请求是指在发起请求后,程序会阻塞当前线程,直到请求完成并获取到响应结果,才会继续执行后续代码。这种方式简单直接,但会影响程序的性能,尤其是在处理多个请求或者需要高并发的场景下。

异步请求

异步请求是指在发起请求后,程序不会阻塞当前线程,而是继续执行后续代码。当请求完成后,会通过回调函数或者其他方式通知程序。这种方式可以提高程序的性能和响应速度,但处理起来相对复杂。

使用方法

同步请求

使用 HttpURLConnection 进行同步请求的示例代码如下:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class SynchronousRequestExample {
    public static void main(String[] args) {
        try {
            URL url = new URL("https://api.example.com");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");

            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String line;
                StringBuilder response = new StringBuilder();
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                reader.close();
                System.out.println(response.toString());
            } else {
                System.out.println("Request failed with response code: " + responseCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在上述代码中,connection.getResponseCode() 方法会阻塞当前线程,直到请求完成并获取到响应状态码。

异步请求与等待

使用 CompletableFuture 进行异步请求并等待结果的示例代码如下:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class AsynchronousRequestExample {
    public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                // 模拟 API 请求
                Thread.sleep(2000);
                return "API response";
            } catch (InterruptedException e) {
                e.printStackTrace();
                return null;
            }
        });

        try {
            String result = future.get();
            System.out.println(result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

在上述代码中,CompletableFuture.supplyAsync() 方法会异步执行 API 请求,future.get() 方法会阻塞当前线程,直到异步任务完成并获取到结果。

常见实践

使用 HttpURLConnection

HttpURLConnection 是 Java 标准库中用于进行 HTTP 请求的类。下面是一个完整的使用 HttpURLConnection 进行同步请求的示例:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpURLConnectionExample {
    public static void main(String[] args) {
        try {
            URL url = new URL("https://api.example.com");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");

            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String line;
                StringBuilder response = new StringBuilder();
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                reader.close();
                System.out.println(response.toString());
            } else {
                System.out.println("Request failed with response code: " + responseCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用 OkHttp

OkHttp 是一个高效的 HTTP 客户端库,支持同步和异步请求。下面是一个使用 OkHttp 进行异步请求并等待结果的示例:

import okhttp3.*;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;

public class OkHttpExample {
    public static void main(String[] args) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
               .url("https://api.example.com")
               .build();

        CompletableFuture<String> future = new CompletableFuture<>();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                future.completeExceptionally(e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    String result = response.body().string();
                    future.complete(result);
                } else {
                    future.completeExceptionally(new IOException("Request failed with response code: " + response.code()));
                }
            }
        });

        try {
            String result = future.get();
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

最佳实践

超时处理

在进行 API 请求时,为了避免长时间等待,可以设置请求超时时间。使用 OkHttp 设置超时时间的示例代码如下:

import okhttp3.*;

import java.io.IOException;

public class TimeoutExample {
    public static void main(String[] args) {
        OkHttpClient client = new OkHttpClient.Builder()
               .connectTimeout(5, java.util.concurrent.TimeUnit.SECONDS)
               .readTimeout(5, java.util.concurrent.TimeUnit.SECONDS)
               .build();

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

        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                System.out.println(response.body().string());
            } else {
                System.out.println("Request failed with response code: " + response.code());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

错误处理

在进行 API 请求时,需要对可能出现的错误进行处理,例如网络异常、请求失败等。下面是一个使用 try-catch 块进行错误处理的示例:

import okhttp3.*;

import java.io.IOException;

public class ErrorHandlingExample {
    public static void main(String[] args) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
               .url("https://api.example.com")
               .build();

        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                System.out.println(response.body().string());
            } else {
                System.out.println("Request failed with response code: " + response.code());
            }
        } catch (IOException e) {
            System.out.println("An error occurred: " + e.getMessage());
        }
    }
}

小结

本文详细介绍了在 Java 中等待 API 请求完成的方法,包括同步请求和异步请求。同步请求简单直接,但会阻塞当前线程;异步请求可以提高程序的性能和响应速度,但处理起来相对复杂。同时,我们还介绍了常见的实践和最佳实践,如使用 HttpURLConnectionOkHttp 进行请求,以及超时处理和错误处理。通过掌握这些知识,读者可以在实际开发中更加高效地处理 API 请求。

参考资料

  • 《Effective Java》,作者:Joshua Bloch