Spring HttpMessageConverter如何将请求正文解析为我定义的模型

时间:2019-03-21 14:16:39

标签: spring spring-boot

我有点好奇弹簧是如何处理的,所以做了一些实验。 这是我的请求处理方法:

@PostMapping(value = "/testRequestBody")
public String testRequestBody(@RequestBody MyRequestBody requestBody) {
    System.out.println(requestBody);

    return "Success";
}

我尝试了三种MyRequestBody

提示1:

public class MyRequestBody {
private int id;
private String name;
public void setId(int id) {
    this.id = id;
}
public void setName(String name) {
    this.name = name;
}
public String toString() {
    return "MyRequestBody(id="+id+",name="+name+")";
}}

类型2:

public class MyRequestBody {
private int id;
private String name;
public MyRequestBody(int id, String name) {
    this.id = id;
    this.name = name;
}
public String toString() {
    return "MyRequestBody(id="+id+",name="+name+")";
}}

类型3:

public class MyRequestBody {
private int id;
private String name;
public String toString() {
    return "MyRequestBody(id="+id+",name="+name+")";
}}

类型1和类型2都可以在控制台中获得MyRequestBody(id=1,name=test name),作为输入{"id": 1,"name": "test name"},类型3给我MyRequestBody(id=0,name=null)。看来Spring可以根据为我的模型定义setter和构造函数的方式选择不同的方法来解析我的模型。我想知道Spring是如何实现的?

1 个答案:

答案 0 :(得分:0)

MappingJackson2HttpMessageConverter委托杰克逊完成将json转换为Java对象的工作。因此,杰克逊遵循的规则可以解释您所看到的行为。

以下是Jackson所执行操作的简化序列,它解释了使用三个MyRequestBody定义所看到的行为。

  • 通过调用构造函数来创建类的对象。如果构造函数接受参数,则参数值将从json字符串中获取。以下是确定应调用哪个构造函数的规则。

    • 如果有一个用@JsonCreator注释的构造函数,则会调用该构造函数。

    • 如果没有用@JsonCreator注释的构造函数

      • 如果只有一个构造函数,则调用该构造函数。这可以是参数化构造函数,也可以是默认构造函数。
      • 如果有多个构造函数,包括一个默认构造函数,则会调用该默认构造函数。
      • 在其他情况下,会引发异常。
  • 通过调用setX()方法设置字段值。

Java reflection用于检查构造函数/方法并调用它们。

所以,就您而言

  • 对于第一个RequestBody定义,将调用默认构造函数并调用setX()方法。
  • 对于第二个RequestBody定义,将调用参数化构造函数(没有默认构造函数)
  • 默认构造函数被调用。