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

时间:2015-10-06 17:10:52

标签: java rest spring-boot

我刚刚玩弹簧靴,只是想用method = RequestMethod.POST

创建一个控制器

我的控制员:

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

SignUpUserForm类:

@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;
}

最后我的测试:

@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());
    }

就SignUpControllerForm包含no-args构造函数而言,一切正常,但一旦丢失,这就是我从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 = []

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

Spring究竟是如何使用no-arg构造函数将JSON转换为java对象的(它在我检查时不使用getter)?

1 个答案:

答案 0 :(得分:1)

由于@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>

关于no-arg构造函数的问题,你可以创建自己的构造函数并强制jackson使用它,我相信这是一个很好的做法,因为你对mutablity有更多的控制

@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;

    }

希望这有帮助