【问题标题】:PropertyEditor is not called on AJAX (JSON) request未在 AJAX (JSON) 请求上调用 PropertyEditor
【发布时间】:2013-01-03 04:32:18
【问题描述】:

我在提交表单时遇到了 Ajax 请求问题。该表单包含这些字符串化 JSON 数据:

{"articleContent":"<p>aaa</p>","title":"Po vyplnění titulku aktuality budete","header":"aa","enabled":false,"timestamp":"1358610697521","publishedSince":"03.01.2013 00:00","publishedUntil":"","id":"10"}

当 json 包含 "03.01.2013 00:00" 值时,服务器响应为 400 Bad Request

问题是,自定义的 DateTimePropertyEditor(注册到@InitBinder)没有被调用,String 格式的 DateTime 没有被调用。你知道如何解决这个问题吗?

控制器映射方法,即处理请求

@RequestMapping( value = "/admin/article/edit/{articleId}", method = RequestMethod.POST, headers = {"content-type=application/json"})
public @ResponseBody JsonResponse  processAjaxUpdate(@RequestBody Article article, @PathVariable Long articleId){
    JsonResponse response = new JsonResponse();
    Article persistedArticle = articleService.getArticleById(articleId);
    if(persistedArticle == null){
        return response;
    }
    List<String> errors = articleValidator.validate(article, persistedArticle);

    if(errors.size() == 0){
        updateArticle(article, persistedArticle);
        response.setStatus(JsonStatus.SUCCESS);
        response.setResult(persistedArticle.getChanged().getMillis());
    }else{
        response.setResult(errors);
    }

    return response;
}

InitBinder

 @InitBinder
        public void initBinder(WebDataBinder binder) {
            binder.registerCustomEditor(DateTime.class, this.dateTimeEditor);
        }

【问题讨论】:

    标签: java ajax json spring spring-mvc


    【解决方案1】:

    使用 Spring MVC 4.2.1.RELEASE,您需要使用新的 Jackson2 依赖项,如下所示,Deserializer 才能工作。

    不要用这个

    <dependency>  
                <groupId>org.codehaus.jackson</groupId>  
                <artifactId>jackson-mapper-asl</artifactId>  
                <version>1.9.12</version>  
            </dependency>  
    

    改用这个。

    <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-annotations</artifactId>
                <version>2.2.2</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>2.2.2</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.2.2</version>
            </dependency>  
    

    还使用 com.fasterxml.jackson.databind.JsonDeserializer 和 com.fasterxml.jackson.databind.annotation.JsonDeserialize 进行反序列化,而不是使用 org.codehaus.jackson 中的类

    【讨论】:

      【解决方案2】:

      我使用 @JsonDeserialize

      解决了这个问题
      @JsonDeserialize(using=DateTimeDeserializer.class)
      public DateTime getPublishedUntil() {
          return publishedUntil;
      }
      

      我必须实现自定义反序列化器。

          public class DateTimeDeserializer extends StdDeserializer<DateTime> {
      
          private DateTimeFormatter formatter = DateTimeFormat.forPattern(Constants.DATE_TIME_FORMAT);
      
          public DateTimeDeserializer(){
              super(DateTime.class);
          }
      
          @Override
          public DateTime deserialize(JsonParser json, DeserializationContext context) throws IOException, JsonProcessingException {
                  try {
                      if(StringUtils.isBlank(json.getText())){
                          return null;
                      }
                      return formatter.parseDateTime(json.getText());
                  } catch (ParseException e) {
                      return null;
                  }
          }
      }
      

      【讨论】:

        【解决方案3】:

        这不是由属性编辑器处理的——它作用于表单字段而不是 json 主体。要处理 json 中的非标准日期格式,您必须自定义底层 ObjectMapper。假设您使用的是 jackson 2.0+,您可以执行以下操作:

        一个。使用注释标记 publishedSince 字段,告诉对象映射器日期格式 - 基于指令here

        public class Article{
            ...
            @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="MM.dd.yyyy HH:mm")
            private Date publishedSince;
        }
        

        b.或者第二个选项是修改 ObjectMapper 本身,虽然这可能是全局的,所以可能不适合你:

        public class CustomObjectMapper extends ObjectMapper {
            public CustomObjectMapper(){
                super.setDateFormat(new SimpleDateFormat("MM.dd.yyyy hh:mm"));
            }   
        }
        

        并使用 Spring MVC 进行配置:

        <mvc:annotation-driven> 
           <mvc:message-converters register-defaults="true">
               <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                   <property name="objectMapper">
                       <bean class="..CustomObjectMapper"/>
                   </property>
               </bean>
           </mvc:message-converters>
        </mvc:annotation-driven>
        

        【讨论】:

        • 感谢您的回复。我尝试了这个解决方案,但它不起作用。我正在使用 Joda DateTime,可能是这个问题吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-27
        • 2014-05-06
        • 1970-01-01
        • 2015-08-14
        • 1970-01-01
        相关资源
        最近更新 更多