java - 如何正确处理HttpClientException

标签 java spring apache-httpclient-4.x

我有一个 Web 服务,它从其他 Web 服务获取数据并返回到浏览器。

  1. 我想隐藏内部客户端错误
  2. 想要抛出 404、400 等 通过以下方法从网络服务返回。

如何巧妙地解决这个问题?

选项 1 或选项 2 是干净的方式吗?

选项1

public <T> Optional<T> get(String url, Class<T> responseType) {
        String fullUrl = url;
        LOG.info("Retrieving data from url: "+fullUrl);
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setAccept(ImmutableList.of(MediaType.APPLICATION_JSON));
            headers.add("Authorization", "Basic " + httpAuthCredentials);

            HttpEntity<String> request = new HttpEntity<>(headers);
            ResponseEntity<T> exchange = restTemplate.exchange(fullUrl, HttpMethod.GET, request, responseType);
            if(exchange !=null)
                return Optional.of(exchange.getBody());
        } catch (HttpClientErrorException e) {
            LOG.error("Client Exception ", e);
            throw new HttpClientError("Client Exception: "+e.getStatusCode());
        }
         return Optional.empty();
  }

(或)

选项2

public   <T> Optional<T> get(String url, Class<T> responseType) {
        String fullUrl = url;
        LOG.info("Retrieving data from url: "+fullUrl);
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setAccept(ImmutableList.of(MediaType.APPLICATION_JSON));
            headers.add("Authorization", "Basic " + httpAuthCredentials);

            HttpEntity<String> request = new HttpEntity<>(headers);
            ResponseEntity<T> exchange = restTemplate.exchange(fullUrl, HttpMethod.GET, request, responseType);
            if(exchange !=null)
                return Optional.of(exchange.getBody());
            throw new RestClientResponseException("", 400, "", null, null, null);
        } catch (HttpStatusCodeException e) {
            LOG.error("HttpStatusCodeException ", e);
            throw new RestClientResponseException(e.getMessage(), e.getStatusCode().value(), e.getStatusText(), e.getResponseHeaders(), e.getResponseBodyAsByteArray(), Charset.defaultCharset());
        }
        return Optional.empty();
    }

最佳答案

我已经为您编写了一个示例 ResponseErrorHandler,

public class RestTemplateClientErrorHandler implements ResponseErrorHandler {

private static final Logger logger = LoggerFactory.getLogger(RestTemplateClientErrorHandler.class);

@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
    return RestUtil.isError(clientHttpResponse.getStatusCode());
}

@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
    String responseBody = "";
    if(clientHttpResponse != null && clientHttpResponse.getBody() != null){
        responseBody = IOUtils.toString(clientHttpResponse.getBody());
    }
    switch(clientHttpResponse.getRawStatusCode()){
        case 404:
            logger.error("Entity not found. Message: {}. Status: {} ",responseBody,clientHttpResponse.getStatusCode());
            throw new RestClientResponseException(responseBody);
        case 400:
            logger.error("Bad request for entity. Message: {}. Status: {}",responseBody, clientHttpResponse.getStatusCode());
            throw new RestClientResponseException(StringUtils.EMPTY, 400,StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY);
        default:
            logger.error("Unexpected HTTP status: {} received when trying to delete entity in device repository.", clientHttpResponse.getStatusCode());
            throw new RestClientResponseException(responseBody);
    }

}

public static class RestUtil {

    private RestUtil() {
        throw new IllegalAccessError("Utility class");
    }

    public static boolean isError(HttpStatus status) {
        HttpStatus.Series series = status.series();
        return HttpStatus.Series.CLIENT_ERROR.equals(series)
                || HttpStatus.Series.SERVER_ERROR.equals(series);
    }
}
}

注意:这是您的restTemplate 的常见ResponseErrorHandler,它将捕获restTemplate 引发的所有异常,您不需要在每个方法中使用try、catch block ,也不需要捕获“HttpStatusCodeException”或任何其他异常。

请使用以下代码注册此ErrorHandler。

RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new RestTemplateClientErrorHandler());

您还可以找到示例 here .

您可以像这样重构您的客户端类,

public <T> Optional<T> get(String url, Class<T> responseType) {
    String fullUrl = url;
    LOG.info("Retrieving data from url: "+fullUrl);
        HttpHeaders headers = new HttpHeaders();

       headers.setAccept(ImmutableList.of(MediaType.APPLICATION_JSON));
        headers.add("Authorization", "Basic " + httpAuthCredentials);

        HttpEntity<String> request = new HttpEntity<>(headers);
        ResponseEntity<T> exchange = restTemplate.exchange(fullUrl, HttpMethod.GET, request, responseType);
        if(exchange !=null)
            return Optional.of(exchange.getBody());
     return Optional.empty();
}

所以你的方法现在看起来不太漂亮?欢迎提出建议。

关于java - 如何正确处理HttpClientException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46367039/

相关文章:

java - iOS 开发者的第一个 Android 应用程序

java - 文件目标选择器

Java WatchService 意外停止工作

authentication - 如何配置 Apache HttpClient 4.x 以使用特定的 Websphere SSL 别名?

android - import cz.msebera.android.httpclient.conn.ssl.SSLSocketFactory无法解析

java - 无法从 Firebase 检索数据。应用程序关闭 fragment

javascript - 从 Java Servlet 下载文件

java - Spring 3.1 : Getting the <mvc:resources To Work

java - 找不到 Log4j2.xml 但 log4j2-test.xml 是

java - 如何使用 Apache httpclient 获取自定义 Content-Disposition 行?