使用 Spring WebClient,我如何反序列化不同类型的成功和失败响应?

家庭

tbjorch的回答让我走上了正确的道路,但我发现的一件事是我应该使用 和 的静态方法构造HTTP.create异常如果我不这样做,我的所有异常都将作为超类抛出,这是不可取的,因为它丢失了原始 Http 状态代码的上下文。HttpClientErrorExceptionHttpServerErrorExceptionException

我是使用 Spring WebClient 的新手。我正在实现的 API 根据成功或失败使用不同的 JSON 结构进行响应。在失败的情况下,我希望能够反序列化响应正文并返回错误消息。根据下面的代码,我收到一条错误消息:

java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-2
        at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:83)

我同意,在 2 个地方屏蔽是没有意义的。但我不明白如何反序列化错误响应以获取错误消息。我在网上和 StackOverflow 上阅读的所有内容都表明人们只是返回Mono.error或抛出异常,但在这些情况下他们似乎没有反序列化响应正文。这是我的代码:

  public boolean updatePassword(String id, String data) {
    final var responseSpec =
        client
            .post()
            .uri(builder -> builder.path("/{id}/change_password").build(id))
            .header(HttpHeaders.AUTHORIZATION, "Bearer " + staticData.getAPIToken())
            .accept(MediaType.APPLICATION_JSON)
            .contentType(MediaType.APPLICATION_JSON)
            .body(BodyInserters.fromValue(data))
            .retrieve()
            .onStatus(
                HttpStatus::isError,
                error -> {
                  final var errorResponse = error.bodyToMono(ErrorResponse.class).block();
                  final var errorMsg = errorResponse.getCause().getSummary();

                  if (error.statusCode().is4xxClientError()) {
                    throw new HttpClientErrorException(error.statusCode(), errorMsg);
                  }
                  if (error.statusCode().is5xxServerError()) {
                    throw new HttpServerErrorException(error.statusCode(), errorMsg);
                  }
                  return Mono.error(
                      new HttpServerErrorException(
                          HttpStatus.INTERNAL_SERVER_ERROR, "Something else."));
                })
            .bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {});

    final var response = responseSpec.block();

    return response.containsKey("password") && response.containsKey("provider");
  }

PS。我也尝试过使用.exchangeToMono而不是.retrieve,这样我就可以检查响应状态代码,然后为.bodyToMono函数使用不同的类型,但是一旦我在成功和失败之间编写了两种不同的类型,我就会收到一条错误消息,指出无法推断类型参数。

tbjorch

无法完全尝试您的代码,但请尝试以下操作:

public boolean updatePassword(String id, String data) {
    final var responseSpec =
        client
            .post()
            .uri(builder -> builder.path("/{id}/change_password").build(id))
            .header(HttpHeaders.AUTHORIZATION, "Bearer " /*+ staticData.getAPIToken()*/)
            .accept(MediaType.APPLICATION_JSON)
            .contentType(MediaType.APPLICATION_JSON)
            .body(BodyInserters.fromValue(data))
            .retrieve()
            .onStatus(
                HttpStatus::isError,
                error -> error.bodyToMono(ErrorResponse.class)
                    .map(errorResponse -> {
                    final var errorMsg = errorResponse.getCause().getSummary();
                    if (error.statusCode().is4xxClientError()) {
                      throw new HttpClientErrorException(error.statusCode(), errorMsg);
                    }
                    if (error.statusCode().is5xxServerError()) {
                      throw new HttpServerErrorException(error.statusCode(), errorMsg);
                    }
                    return new HttpServerErrorException(
                            HttpStatus.INTERNAL_SERVER_ERROR, "Something else.");
                  }))
            .bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {});

    final var response = responseSpec.block();

    return response.containsKey("password") && response.containsKey("provider");
  }

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

使用Spring WebClient反序列化整数列表

使用RestTemplate和Unwrap Root时,Spring Boot(2.3.6.RELEASE)反序列化失败

具有不同类型的字段的 JSON 反序列化(使用 Jackson 和 Scala)

如何反序列化包含相同键名但使用不同类型的JSON文件(使用Google JSON)?

如何使用Jackson ObjectMapper反序列化Spring的ResponseEntity(可能使用@JsonCreator和Jackson mixins)

GSON在Android中使用两种不同类型的对象反序列化列表

spring-data-rest和控制器,使用相同的objectMaper进行序列化/反序列化

Java Spring使用RestTemplate反序列化嵌套对象

Spring使用JSONObject字段反序列化对象

Spring 使用额外的列反序列化 manytomany 表

使用spring-hateoas反序列化包含(_links和_embedded)的JSON

Spring RestTemplate使用Jackson作为HttpMessageConverter和joda DateTime属性进行反序列化

如何在Spring @RequestParam中使用自定义反序列化器

如何使用Avro克服Spring Kafka 1.3中无法反序列化的消息

如何使用Retrofit / Gson在JSON中反序列化相同类型但具有不同字段名称的对象列表?

Spring 5 Reactive WebClient似乎并未反序列化参数化类型

使用不同的propertyValue类型反序列化json

Spring AMQP RabbitMQ InboundChannelAdapter 和 OutboundEndpoint 不同的序列化/反序列化策略

如何使用Jackson API在序列化和反序列化上使用不同的JSONProperty?

如何使用@JsonProperty反序列化JSON响应?

如何在Hibernate 4和Spring中使用批注定义不同类型的关系?

如何使用GSON和Retrofit2反序列化多形状JSON响应?

如何使用Gson序列化和反序列化Java 8的java.time类型?

使用Spring Hateoas的jackson和Jackson2HalModule反序列化json时的null id属性

除了使用Spring的setter和@JsonProperty反序列化之外,还有其他方法吗?

在Spring MVC中使用JAXB注释使用Jackson进行反序列化的问题

如何在简单的Spring Boot应用程序中使用嵌套的对象数组反序列化Json

如何使用非标准(和不同的)属性名称反序列化JSON(在.NET中)

使用Jackson将不同类型反序列化为单个字段