当表单中存在多个相同类型的参数时,会出现全局绑定初始化器问题



我有以下设置:

@ControllerAdvice
public class GlobalBindingInitializer {
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(ZonedDateTime.class, new ZonedDateTimeBinder());
    }
}
public class ZonedDateTimeBinder extends PropertyEditorSupport {
    public void setAsText(String value) {
        setValue(ZonedDateTime.parse(value));
    }
    public String getAsText() {
        return ((ZonedDateTime) getValue()).toString();
    }
}
@RequestMapping(value = "/bx", method = RequestMethod.POST)
public ResponseEntity<X> bx(@Valid @RequestBody MyForm form, BindingResult result) {
    .............
}
public class AddNewBookingPeriodForm {
    .....
    @NotNull
    private ZonedDateTime dateFrom;
    @NotNull
    private ZonedDateTime dateTo;
    .....
}
@Test
public void test_bx_valid() throws Exception {
    String content = "{" +
            ""uuid":""+...+""," +
            ""dateFrom":""+...+""," +
            ""dateTo":""+...+""," +
            ""ln":""+...+""," +
            ""fn":""+...+""," +
            ""p":""+...+""" +
            "}";
    mockMvc.perform(post("/b/bx")
            .contentType("application/json;charset=UTF-8")
            .content((content).getBytes()))
            .andDo(print())
            .andExpect(status().isCreated())
            .andExpect(content().contentType("application/json;charset=UTF-8"))
            .andExpect((jsonPath("$.", Matchers.hasSize(3))))
            .andDo(print());
}

问题是,当我运行测试时,它找到控制器处理程序方法,并说它无法读取请求,因为主体。我调试了发送的消息,它具有所需的表单,它是一个有效的JSON对象。问题在于两个ZonedDateTime字段。

我有一个类似的代码在另一个地方,但用于验证的形式只有一个ZonedDateTime和它的工作。我想问题可能是我在这个表格中有两个,但我不知道发生了什么。

我尝试将dateFromdateTo的类型从我的形式更改为String,一切都很好,所以问题是与这两个。

任何想法?

测试打印的调试信息:

MockHttpServletRequest:
         HTTP Method = POST
         Request URI = /b/bx
          Parameters = {}
             Headers = {Content-Type=[application/json;charset=UTF-8]}
             Handler:
                Type = valid handler controller
              Method = valid handler method
               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 = []

编辑1

这是一个有效的示例

{  
   "uuid":"e50b5cbf-c81a-40de-9eee-ceecd21ad179",
   "dateFrom":"2015-09-07T19:25:42+03:00",
   "dateTo":"2015-09-08T19:25:42+03:00",
   "ln":"ln",
   "fn":"fn",
   "p":"007"
}

我认为问题可能来自@RequestBody注释,因为在工作情况下,我在前面的行中谈到,我使用GET方法没有@RequestBody注释和映射工作得很好。

给定RequestBody, Spring将使用HttpMessageConverter将请求体反序列化为给定类型的实例。在本例中,它将对JSON使用MappingJackson2HttpMessageConverter。这个转换器根本不涉及您的PropertyEditorSupport

要正确反序列化ZonedDateTime,您需要注册一个适当的Jackson模块来映射java.time类型。一种可能是jackson-datatype-jsr310。我认为当在类路径上找到它时应该自动注册。如果不是,您需要手动注册它,通过手动创建MappingJackson2HttpMessageConverter并将其注册为适当创建的ObjectMapper

最新更新