Spring WebClient如何通过构造器将响应转换为无setter的实体对象
你不需要手动传入构造好的响应对象,WebClient默认使用的Jackson反序列化工具本身就支持构造器注入的方式生成对象,完全不需要无参构造方法和setter方法,原有bodyToMono(MyResponse.class)的写法不需要改动,只要按规则定义MyResponse类即可。
具体实现方案
根据你使用的Java版本和类定义方式,选对应方案即可:
方案1:使用Java 16+ 记录类(Record)
Jackson 2.12及以上版本原生支持Record类型反序列化,Spring Boot默认依赖的Jackson版本已经满足要求。你只需要把响应类定义为Record,保证属性名和响应JSON的字段名对应即可,不需要额外加任何注解,也不需要写setter、无参构造:public record MyResponse(String val1, Integer val2, Boolean val3) {}这种方式下所有属性默认是final的,只自动生成getter方法,完全符合你的要求。
方案2:使用普通Java类
如果你的项目还不能用Record,用普通类也可以实现,两种配置方式二选一:- 给全参构造方法加Jackson注解,给每个参数明确指定对应的JSON字段名,类里只保留getter,不需要写setter和无参构造:
public class MyResponse { private final String val1; private final Integer val2; private final Boolean val3; @JsonCreator public MyResponse( @JsonProperty("val1") String val1, @JsonProperty("val2") Integer val2, @JsonProperty("val3") Boolean val3) { this.val1 = val1; this.val2 = val2; this.val3 = val3; } // 仅保留getter即可 public String getVal1() {return val1;} public Integer getVal2() {return val2;} public Boolean getVal3() {return val3;} }- 如果你不想在构造器上写
@JsonProperty注解,可以给项目里的Jackson注册ParameterNamesModule模块,同时编译时加上-parameters参数保留方法参数名,Jackson会自动根据构造器参数名匹配JSON字段,这种情况只需要写全参构造和getter即可。
注意:你设想的
s.bodyToMono(new MyResponse(val1, val2, val3))写法无法实现,因为调用bodyToMono方法时还没有拿到HTTP响应内容,根本获取不到val1/val2/val3这些实际值,反序列化操作是在响应体内容拉取完成后由Jackson自动执行的,会自动匹配字段调用构造器生成对象,不需要你手动实例化。
如果你用的是Spring Boot默认自动配置的WebClient和ObjectMapper,上面的方案不需要额外调整任何全局配置,写完类直接用原来的bodyToMono(MyResponse.class)就能正常反序列化。
内容的提问来源于stack exchange,提问作者treo

