使用 Apatch HttpRequest 的情况下,使用 HttpRequest.execute 方法, 假如该方法抛出了异常,应该从哪个异常中获取到responseEntity String ?我想一定有异常包装了 responseEnity

在使用 Apache HttpClient 时,如果调用 HttpRequest.execute() 抛出了异常,通常情况下,异常不会直接包含完整的 response entity。特别是当服务器返回错误响应(如 4xx 或 5xx 状态码)时,execute() 方法可能抛出各种类型的 IOExceptionHttpResponseException,但这些异常并不一定会携带完整的 response body

Apache HttpClient 在抛出异常时,通常只会传递有关错误状态的信息(如 HTTP 状态码),而不会包装 response entity。为了从错误响应中提取 response body,你需要手动处理响应,即使发生了异常。

1. 捕获 HttpResponseException

HttpResponseException 是 Apache HttpClient 抛出的常见异常之一,它可以提供 HTTP 状态码,但默认情况下,它不会包含 response entity。你可以通过捕获 HttpResponseException 来处理状态码相关的错误。

try {
    CloseableHttpResponse response = httpClient.execute(request);
    // 正常处理
} catch (HttpResponseException e) {
    // 捕获状态码错误
    System.out.println("HTTP Status Code: " + e.getStatusCode());
} catch (IOException e) {
    // 其他IO异常处理
    e.printStackTrace();
}

然而,HttpResponseException 并不会自动将 response entity 包装在异常中。因此,我们需要另一种方式来在抛出异常时访问 response entity

2. 如何获取异常中的 response entity

要捕获并读取异常中的 response entity,你可以直接处理响应对象,即使请求导致了异常(如 4xx 或 5xx 错误),并在捕获异常之前手动检查 response 是否有内容可供读取。可以使用 HttpClient 的低级 API 来在异常发生时处理响应体。

3. 使用 responseHandler 捕获 response entity

Apache HttpClient 提供了一种机制——通过 ResponseHandler 可以捕获响应体,即使响应是错误的。通过使用 ResponseHandler,你可以自己定义如何处理成功的响应和错误的响应,并在错误的情况下获取 response entity

示例代码:使用 ResponseHandler 获取错误响应体

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;

public class HttpClientExample {

    public static void main(String[] args) {
        String url = "https://example.com/api";
        CloseableHttpClient httpClient = HttpClients.createDefault();

        try {
            HttpGet request = new HttpGet(url);

            // 使用 ResponseHandler 来处理响应
            ResponseHandler<String> responseHandler = new ResponseHandler<String>() {

                @Override
                public String handleResponse(final HttpResponse response) throws IOException {
                    int status = response.getStatusLine().getStatusCode();
                    if (status >= 200 && status < 300) {
                        HttpEntity entity = response.getEntity();
                        return entity != null ? EntityUtils.toString(entity) : null;
                    } else {
                        // 错误情况下捕获response body
                        HttpEntity entity = response.getEntity();
                        String errorResponse = entity != null ? EntityUtils.toString(entity) : null;
                        throw new ClientProtocolException("Unexpected response status: " + status + 
                                                          ", response body: " + errorResponse);
                    }
                }
            };

            // 这里使用自定义的 ResponseHandler 来执行请求并处理响应
            String responseBody = httpClient.execute(request, responseHandler);
            System.out.println(responseBody);

        } catch (ClientProtocolException e) {
            // 捕获并打印异常中的 response body
            System.out.println("Exception caught: " + e.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

关键点说明:

  1. ResponseHandler:通过自定义的 ResponseHandler,你可以在错误响应(如 4xx 或 5xx)时,捕获并读取 response entity,而不是让 execute() 方法直接抛出异常。
  2. 错误处理:在 ResponseHandler 中处理状态码大于等于 400 的响应,并将 response entity 转换为 String,即使抛出异常,也可以从异常中获取到响应体。
  3. ClientProtocolException:在异常中,你可以访问状态码以及响应体。

4. 捕获 HttpEntity 并处理异常响应

如果不想使用 ResponseHandler,你可以在捕获异常之前直接获取 CloseableHttpResponse 并检查是否存在 response entity,然后手动读取。

示例代码:手动捕获 response entity

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;

public class HttpClientExample {

    public static void main(String[] args) {
        String url = "https://example.com/api";
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;

        try {
            HttpGet request = new HttpGet(url);
            response = httpClient.execute(request);

            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode >= 200 && statusCode < 300) {
                HttpEntity entity = response.getEntity();
                String responseBody = entity != null ? EntityUtils.toString(entity) : null;
                System.out.println("Response Body: " + responseBody);
            } else {
                // 处理错误响应,获取错误的 response body
                HttpEntity entity = response.getEntity();
                String errorResponse = entity != null ? EntityUtils.toString(entity) : null;
                System.out.println("Error Response Body: " + errorResponse);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

关键点:

  • 手动管理 CloseableHttpResponse,即使在出现异常时,也可以手动读取 response entity
  • 在错误响应时,通过 response.getEntity() 手动获取并读取错误的响应体。

总结:

  • Apache HttpClient 抛出的异常,如 HttpResponseException,不会自动包含 response entity。如果你想在异常中获取到 response entity,最好的做法是使用 ResponseHandler 或在捕获异常前手动处理响应对象。
  • 通过自定义的 ResponseHandler,你可以在请求抛出异常时依然获取到完整的 response body
posted @   gongchengship  阅读(90)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示