将 class 与自定义 getter setter 作为 RequestBody 一起使用时,WebClient 给出不支持 MediaType 的异常

WebClient giving MediaType not supported Exception when using class with custom getter setter as RequestBody

我的 spring Webflux 应用程序中有 class 所有 classes,它有 getter/setters 没有 get 和 set 前缀和 setter return 这个。因此,我还定义了我的自定义 Jackson 配置,它可以很好地与我的所有控制器一起成功地进行序列化反序列化。

我的杰克逊配置

@Configuration
public class JacksonObjectMapperConfiguration implements Jackson2ObjectMapperBuilderCustomizer {

  @Override
  public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
    jacksonObjectMapperBuilder
      .serializationInclusion(NON_NULL)
      .failOnUnknownProperties(false)
      .visibility(FIELD, ANY)
      .modulesToInstall(new ParameterNamesModule(PROPERTIES));
  }
}

我的要求Class

@Accessors(chain = true, fluent = true)
@Getter
@Setter // from project Lombok
public class Test {
  private String a;
  private List<String> b;
}

现在,如果我像下面这样使用 webclient 发出请求

  public Mono<Void> postRequest(String a, List<String> b) {
    Webclient webclient = Webclient.create();
    return webClient.post()
      .uri("some_url")
      .contentType(MediaType.APPLICATION_JSON)
      .bodyValue(new Test().a(a).b(b))
      .retrieve()
      .bodyToMono(Void.class);
  }

我遇到如下异常

org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/json' not supported for bodyType=<Classpath>

但是如果我像下面这样传递一个地图,它就可以工作。

  public Mono<Void> postRequest(String a, List<String> b) {
    Webclient webclient = Webclient.create();
    return webClient.post()
      .uri(format("some_url")
      .contentType(MediaType.APPLICATION_JSON)
      .bodyValue(new HashMap<String,Object>(){{put("a",a);put("b",b);}})
      .retrieve()
      .bodyToMono(Void.class);
  }

我已经尝试删除@Accessor 注释并自己创建getter setter,但仍然无效。

我认为异常是由于某些反序列化问题而发生的。不过我不确定。杰克逊在应用程序中与我的所有控制器一起工作正常。

我如何才能使第一个案例发挥作用,我可以提供 class 作为正文而不是地图?

像下面这样创建 Webclient 解决了我的问题。

  public WebClient webClient() {
    WebClient.Builder builder = WebClient.builder();
    builder.exchangeStrategies(EXCHANGE_STRATEGIES)
      .defaultHeader("content-type", "application/json");
    return builder.build();
  }

  public static final ObjectMapper GSON_LIKE_OM = new ObjectMapper()
    .setSerializationInclusion(NON_NULL)
    .setVisibility(FIELD, ANY)
    .configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
    .registerModule(new ParameterNamesModule(PROPERTIES));

  public static final ExchangeStrategies EXCHANGE_STRATEGIES = ExchangeStrategies
    .builder()
    .codecs(clientDefaultCodecsConfigurer -> {
      clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(GSON_LIKE_OM, APPLICATION_JSON));
      clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(GSON_LIKE_OM, APPLICATION_JSON));
    }).build();