【问题标题】:How to throw WebClientResponseException when using exchange() with Spring WebClient使用带有 Spring WebClient 的 exchange() 时如何抛出 WebClientResponseException
【发布时间】:2019-09-19 03:44:25
【问题描述】:

当结合使用 Spring WebClient 的 retrieve() 方法和 bodyToMono 时,会应用默认错误处理(如果响应的状态码为 4xx 或 5xx,Mono 将包含 WebClientException)。在错误情况下,生成的 WebClientException 非常有用,因为它包含请求和响应,这非常方便,例如用于记录。此外,我可以非常到位地对错误做出反应。

/*
 * Easy to use retrieve() with default error handling:
 * By default, if the response has status code 4xx or 5xx, the Mono will contain a WebClientException - AWESOME!
 */
public Optional<MyType> getMyType() {
    try {
        MyType result = client
                .get()
                .uri("/myType")
                .retrieve().bodyToMono(MyType.class).block();

        return Optional.ofNullable(result);
    } catch (NotFound e) {
        return Optional.empty();
    }
}

但是,有时我需要知道响应的确切状态代码才能在进一步处理此响应时对其做出反应。获取状态码的唯一方法是调用 exchange() 方法而不是 retrieve() 方法。不幸的是,在这种情况下,不应用默认错误处理。原因似乎是在 ClientResponse 上调用 bodyToMono() 与在 ResponseSpec 上调用它具有不同的语义。

我不能从 Spring 调用已经实现的方法来“触发”错误处理,因为所有好的方法都被隐藏在 WebClient 中作为私有方法。

即使我会尝试“手动”创建 WebClientResponseException 我也不能 访问请求以提供给异常。

public String updateMyType() {
    ClientResponse response = client
            .put()
            .uri("/myType")
            .header(CONTENT_TYPE, APPLICATION_JSON_VALUE)
            .body(fromObject(new MyType()))
            .exchange()
            .block();

    if (response.statusCode().equals(HttpStatus.CREATED)) {
        return "OK";
    } else if (response.statusCode().equals(HttpStatus.NO_CONTENT)) {
        return "updated";
    } else {
        byte[] bodyBytes = null; // already implemented by Sping but not accessible
        Charset charset = null; // already implemented by Sping but not accessible
        HttpRequest request = null; // where should I get this from?
        throw WebClientResponseException.create(response.statusCode().value(),
                response.statusCode().getReasonPhrase(),
                response.headers().asHttpHeaders(),
                bodyBytes,
                charset,
                request);
    }
}

“模仿”与 retrieve() 方法相同的行为的最佳方法是什么?

【问题讨论】:

    标签: java spring spring-webclient


    【解决方案1】:

    回答问题时可能不是这种情况,但从 Spring 5.2 开始,ClientResponse 有一个 createException() 方法,该方法将构建并返回一个 Mono&lt;WebClientResponseException&gt;

    clientResponse.createException()
                  .flatMap(e -> handleException(e))
    
    

    https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/function/client/ClientResponse.html#createException--

    https://github.com/spring-projects/spring-framework/commit/b4207823afa0f48e06d6bbfe9ae8821e389e380f

    【讨论】:

      猜你喜欢
      • 2020-12-26
      • 1970-01-01
      • 2019-04-07
      • 2019-05-16
      • 2022-12-23
      • 2021-10-14
      • 2020-09-02
      • 1970-01-01
      • 2021-05-17
      相关资源
      最近更新 更多