java - 当表单中存在多个具有相同类型的参数时,全局绑定(bind)初始值设定项会出现问题

标签 java spring spring-mvc

我有以下设置:

@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 并且它有效。我认为问题可能是因为我有两个这种形式,但我不知道发生了什么。

我尝试将 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 将您的请求正文反序列化为给定类型的实例。在本例中,它将使用 MappingJackson2HttpMessageConverter 作为 JSON。此转换器根本不涉及您的 PropertyEditorSupport

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

关于java - 当表单中存在多个具有相同类型的参数时,全局绑定(bind)初始值设定项会出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32485850/

相关文章:

java - 运行克隆的 git 存储库

java - spring 是否有办法在应用程序首次加载时加载东西?在全局范围内

java - 添加(自定义)解码器到 WebMVC 端点

java - 使用 HttpURLConnection 的 Android 分段文件上传 - 400 错误请求错误

java - 什么时候在 String.subString 上使用 String.subSequence 方法?

java - Java中链表的链表

java - Spring 安全 : How to change default user and password?

javascript - 无法在spring security中加载静态内容

mysql - 如何在 Spring MVC 中使用 SQL 实现审计跟踪?

java - 使用 spring @PathVariable 提取和解析参数