我有以下设置:
@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和它的工作。我想问题可能是我在这个表格中有两个,但我不知道发生了什么。
我尝试将dateFrom
和dateTo
的类型从我的形式更改为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
。