全部
常见问题
产品动态
精选推荐

RestClient 和 WebClient 在异常处理上有哪些具体差异?

管理 管理 编辑 删除

RestClient 和 WebClient 在异常处理上的具体差异

RestClient 和 WebClient 在异常处理上有显著的不同,这些差异主要体现在异常处理机制、错误处理的复杂性和灵活性上。以下是两者的详细对比:【起飞嘎嘎飞LSIXSO】

一、RestClient 的异常处理

(一)异常处理机制

RestClient 提供了改进的错误处理机制,使得异常处理和 HTTP 状态码的管理变得更加简单和直接。RestClient 在接收到客户端错误状态码(400-499)或服务器错误状态码(500-599)时,会抛出 RestClientException 的子类。

(二)自定义错误处理器

RestClient 支持通过 defaultStatusHandler 方法定义全局的错误处理器,也可以通过 onStatus 方法为特定请求定义错误处理器。例如:

java复制


RestClient restClient = RestClient.builder()
    .baseUrl(properties.getUrl())
    .defaultHeader(HttpHeaders.AUTHORIZATION, encodeBasic("pig", "pig"))
    .defaultStatusHandler(
        HttpStatusCode::is4xxClientError,
        (request, response) -> {
            logger.error("Client Error Status " + response.getStatusCode());
            logger.error("Client Error Body " + new String(response.getBody().readAllBytes()));
        }
    )
    .build();
    在运行删除命令行运行程序后,控制台的输出如下:
    
    复制
Client Error Status 404 NOT_FOUND
Client Error Body {"status":404,"message":"Entity Customer for id 2 was not found.","timestamp":"2023-07-23T09:24:55.4088208"}
另一种选择是为删除操作实现 onStatus 方法。它优先于 RestClient 默认处理程序行为:

java复制
ResponseEntity response = restClient.delete()
    .uri("/{id}", 2)
    .accept(MediaType.APPLICATION_JSON)
    .retrieve()
    .onStatus(HttpStatusCode::is4xxClientError,
        (req, res) -> logger.error("Couldn't delete " + res.getStatusText())
    )
    .toBodilessEntity();
    现在控制台中的消息将是:Couldn't delete Not Found

(三)优点

  • 简化错误处理:RestClient 提供了改进的错误处理机制,使得异常处理和 HTTP 状态码的管理变得更加简单和直接。
  • 灵活的错误处理器:支持全局和局部的错误处理器,可以根据需要灵活配置。

(四)缺点

  • 功能有限:虽然 RestClient 提供了改进的错误处理机制,但其功能相对 WebClient 较为有限。

二、WebClient 的异常处理

(一)异常处理机制

WebClient 提供了强大的错误处理功能,支持响应式编程模型。WebClient 的错误处理通常使用 onErrorResume、onErrorReturn 等操作符。例如:

java复制


import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

public static Mono<String> makePostRequestAsync(String url, String postData) {
    WebClient webClient = WebClient.builder()
        .baseUrl(url)
        .build();
    return webClient.post()
        .uri("/")
        .contentType(MediaType.APPLICATION_FORM_URLENCODED)
        .body(BodyInserters.fromFormData("data", postData))
        .retrieve()
        .onStatus(HttpStatus::is4xxClientError, clientResponse -> Mono.error(new RuntimeException("Client error")))
        .onStatus(HttpStatus::is5xxServerError, clientResponse -> Mono.error(new RuntimeException("Server error")))
        .bodyToMono(String.class);
}
在此示例中,onStatus() 方法被调用两次,一次针对 4xx 客户端错误,一次针对 5xx 服务器错误。onStatus() 每次调用都采用两个参数:
  • Predicate:确定错误状态代码是否与条件匹配。
  • Function:用于返回 Mono,即要传播到订阅者的错误信息。
  • 如果状态代码与条件匹配,Mono 则会发出相应的状态代码,并且 Mono 链会因错误而终止。在此示例中,Mono 将发出一条 RuntimeException 错误消息,指示该错误是客户端错误还是服务器错误。

(二)错误处理的复杂性

WebClient 的错误处理可能更复杂,需要开发者在处理响应状态、异常和重试机制时更加小心和全面。例如,以下代码展示了如何处理成功响应和错误:

java复制


responseMono.subscribe(
    response -> {
        // handle the response
        LOG.info("SUCCESS API Response {}", response);
    },
    error -> {
        // handle the error
        LOG.error("An error occurred: {}", error.getMessage());
        LOG.error("error class: {}", error.getClass());

        // Errors / Exceptions from Server
        if (error instanceof WebClientResponseException) {
            WebClientResponseException webClientResponseException =
                (WebClientResponseException) error;
            int statusCode = webClientResponseException.getStatusCode().value();
            String statusText = webClientResponseException.getStatusText();
            LOG.info("Error status code: {}", statusCode);
            LOG.info("Error status text: {}", statusText);
            if (statusCode >= 400 && statusCode < 500) {
                LOG.info(
                    "Error Response body {}", webClientResponseException.getResponseBodyAsString());
            }

            Throwable cause = webClientResponseException.getCause();
            LOG.error("webClientResponseException");
            if (null != cause) {
                LOG.info("Cause {}", cause.getClass());
                if (cause instanceof ReadTimeoutException) {
                    LOG.error("ReadTimeout Exception");
                }
                if (cause instanceof TimeoutException) {
                    LOG.error("Timeout Exception");
                }
            }
        }

        // Client errors i.e. Timeouts etc -
        if (error instanceof WebClientRequestException) {
            LOG.error("webClientRequestException");
            WebClientRequestException webClientRequestException =
                (WebClientRequestException) error;
            Throwable cause = webClientRequestException.getCause();
            if (null != cause) {
                LOG.info("Cause {}", cause.getClass());
                if (cause instanceof ReadTimeoutException) {
                    LOG.error("ReadTimeout Exception");
                }

                if (cause instanceof ConnectTimeoutException) {
                    LOG.error("Connect Timeout Exception");
                }
            }
        }
    }
);

(三)优点

  • 强大的错误处理:WebClient 提供了强大的错误处理功能,支持响应式编程模型。
  • 灵活的错误处理:支持 onErrorResume、onErrorReturn 等操作符,可以灵活处理不同类型的错误。

(四)缺点

  • 复杂性较高:WebClient 的错误处理可能更复杂,需要开发者在处理响应状态、异常和重试机制时更加小心和全面。

三、总结

RestClient 和 WebClient 在异常处理上有显著的不同:

  • RestClient:提供了改进的错误处理机制,使得异常处理和 HTTP 状态码的管理更加简单和直接。它支持全局和局部的错误处理器,可以根据需要灵活配置。
  • WebClient:提供了强大的错误处理功能,支持响应式编程模型。它支持 onErrorResume、onErrorReturn 等操作符,可以灵活处理不同类型的错误。但其错误处理可能更复杂,需要开发者在处理响应状态、异常和重试机制时更加小心和全面。
  • 如果你的应用场景需要更简单的错误处理机制,RestClient 是一个不错的选择。如果你需要更强大的错误处理功能,特别是响应式编程支持,WebClient 更适合。


请登录后查看

1048c0b63ff2 最后编辑于2025-04-04 00:01:05

快捷回复
回复
回复
回复({{post_count}}) {{!is_user ? '我的回复' :'全部回复'}}
排序 默认正序 回复倒序 点赞倒序

{{item.user_info.nickname ? item.user_info.nickname : item.user_name}} LV.{{ item.user_info.bbs_level }}

作者 管理员 企业

{{item.floor}}# 同步到gitee 已同步到gitee {{item.is_suggest == 1? '取消推荐': '推荐'}}
{{item.is_suggest == 1? '取消推荐': '推荐'}}
沙发 板凳 地板 {{item.floor}}#
{{item.user_info.title || '暂无简介'}}
附件

{{itemf.name}}

{{item.created_at}}  {{item.ip_address}}
{{item.like_count}}
{{item.showReply ? '取消回复' : '回复'}}
删除
回复
回复

{{itemc.user_info.nickname}}

{{itemc.user_name}}

回复 {{itemc.comment_user_info.nickname}}

附件

{{itemf.name}}

{{itemc.created_at}}
{{itemc.like_count}}
{{itemc.showReply ? '取消回复' : '回复'}}
删除
回复
回复
查看更多
437
{{like_count}}
{{collect_count}}
添加回复 ({{post_count}})

相关推荐

快速安全登录

使用微信扫码登录
{{item.label}} 加精
{{item.label}} {{item.label}} 板块推荐 常见问题 产品动态 精选推荐 首页头条 首页动态 首页推荐
取 消 确 定
回复
回复
问题:
问题自动获取的帖子内容,不准确时需要手动修改. [获取答案]
答案:
提交
bug 需求 取 消 确 定

微信登录/注册

切换手机号登录

{{ bind_phone ? '绑定手机' : '手机登录'}}

{{codeText}}
切换微信登录/注册
暂不绑定
CRMEB客服

CRMEB咨询热线 咨询热线

400-8888-794

微信扫码咨询

CRMEB开源商城下载 源码下载 CRMEB帮助文档 帮助文档
返回顶部 返回顶部
CRMEB客服