我有以下设置:
@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
注释,并且映射有效很好。
答案 0 :(得分:1)
给定RequestBody
,Spring将使用HttpMessageConverter
将您的请求主体反序列化为您给定类型的实例。在这种情况下,它将使用MappingJackson2HttpMessageConverter
作为JSON。此转换器根本不涉及您的PropertyEditorSupport
。
要正确反序列化ZonedDateTime
,您需要注册适当的Jackson模块以映射java.time
类型。一种可能性是jackson-datatype-jsr310。我相信它应该在类路径上找到时自动注册。如果不是,您需要手动注册,方法是使用适当创建的MappingJackson2HttpMessageConverter
手动创建并注册ObjectMapper
。