为什么@RequestBody不需要arg构造函数?

pez*_*tem 2 java rest spring-boot

我只是在玩 spring-boot,只是想创建一个控制器method = RequestMethod.POST

我的控制器:

@RequestMapping(value = "/user/signup",
        method = RequestMethod.POST)
private String signUpNewUser(@Valid @RequestBody SignInUserForm userForm){
        // validation + logic
}
Run Code Online (Sandbox Code Playgroud)

注册用户表单类:

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class SignInUserForm {
    @NotEmpty
    @Email
    private String email;

    @NotEmpty
    @Size(min = 8, max = 24)
    private String password;

    @NotEmpty
    @Size(min = 8, max = 24)
    private String repeatedPassword;
}
Run Code Online (Sandbox Code Playgroud)

最后是我的测试:

@Test
    public void shouldCallPostMethod() throws Exception {

        SignInUserForm signInUserForm = new SignInUserForm("test@mail.com", "aaaaaaaa", "aaaaaaaa");

        String json = new Gson().toJson(signInUserForm);

        mockMvc.perform(
                MockMvcRequestBuilders.post("/user/signup")
                    .contentType(MediaType.APPLICATION_JSON_VALUE)
                    .content(json))
                .andDo(MockMvcResultHandlers.print())
                .andExpect(MockMvcResultMatchers.status().isCreated());
    }
Run Code Online (Sandbox Code Playgroud)

就 SignUpControllerForm 包含无参数构造函数而言,一切正常,但是一旦缺少,这就是我从以下地方收到的内容MockMvcResultHandlers.print()

MockHttpServletRequest:
         HTTP Method = POST
         Request URI = /user/signup
          Parameters = {}
             Headers = {Content-Type=[application/json]}

             Handler:
                Type = org.bitbucket.akfaz.gui.controller.SignUpController
              Method = private java.lang.String org.bitbucket.akfaz.gui.controller.SignUpController.signUpNewUser(org.bitbucket.akfaz.gui.model.SignInUserForm)

               Async:
       Async started = false
        Async result = null

  Resolved Exception:
                Type = org.springframework.http.converter.HttpMessageNotReadableException

        ModelAndView:
           View name = null
                View = null
               Model = null

            FlashMap:

MockHttpServletResponse:
              Status = 400
       Error message = null
             Headers = {}
        Content type = null
                Body = 
       Forwarded URL = null
      Redirected URL = null
             Cookies = []
Run Code Online (Sandbox Code Playgroud)

我想表达的是,异常的HttpMessageNotReadableException描述性不够。@RequestBody 不应该有任何异常吗?这会节省很多时间。

Spring 究竟是如何使用无参数构造函数将 JSON 转换为 java 对象(正如我检查的那样,它不使用 getters)?

jst*_*lne 6

正如@Sotitios所说,您可以启用调试日志,您可以通过将 logback.xml (它也可以是groovy)添加到您的资源文件夹中来实现这一点。这是我的

<configuration>
    <appender name="FILE"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>logFile.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>logFile.%d{yyyy-MM-dd}.log</FileNamePattern>
            <maxHistory>5</maxHistory>
        </rollingPolicy>

        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{35} -
                %msg%n</Pattern>
        </layout>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="FILE" />
    </root>

</configuration>
Run Code Online (Sandbox Code Playgroud)

关于您关于无参数构造函数的问题,您可以创建自己的构造函数并强制杰克逊使用它,我相信这是一个很好的实践,因为您对可变性有更多的控制

@JsonCreator
    public UserDto(
            @JsonProperty("id") Long id, 
            @JsonProperty("firstName") String firstName, 
            @JsonProperty("lastName") String lastName,
            @JsonProperty("emailAddress") String emailAddress,
            @JsonProperty("active") boolean active,
            @JsonProperty("position") String position,
            @JsonProperty("pendingDays") Integer pendingDays,
            @JsonProperty("taxUid")  String taxUid,
            @JsonProperty("userName") String userName,
            @JsonProperty("approver") boolean approver,
            @JsonProperty("startWorkingDate") Date startWorkingDate,
            @JsonProperty("birthDate") Date birthDate){

        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.taxUid = taxUid;
        this.userName = userName;
        this.emailAddress = emailAddress;
        this.pendingDays = pendingDays;
        this.position = position;
        this.active = active;
        //this.resourceUrl = resourceUrl;
        this.isApprover = approver;
        this.birthDate = birthDate;
        this.startWorkingDate = startWorkingDate;

    }
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助