我有以下设置:
@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());
}
问题是,当我运行测试时,它找到 Controller 处理程序方法并表示由于正文而无法读取请求。我调试了发送的消息,它具有所需的形式,它是一个有效的 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
将您的请求正文反序列化为给定类型的实例。在本例中,它将使用 MappingJackson2HttpMessageConverter
作为 JSON。此转换器根本不涉及您的 PropertyEditorSupport
。
要正确反序列化 ZonedDateTime
,您需要注册适当的 Jackson 模块来映射 java.time
类型。一种可能性是jackson-datatype-jsr310 。我相信在类路径上找到它时应该自动注册。如果不是,您需要通过使用适当创建的 ObjectMapper
手动创建和注册 MappingJackson2HttpMessageConverter
来手动注册它。
关于java - 当表单中存在多个具有相同类型的参数时,全局绑定(bind)初始值设定项会出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32485850/