zoukankan      html  css  js  c++  java
  • springboot 日期转化报错

    问题场景:

    使用Springboot框架搭建服务,传日期参数json参数为2016-08-15 17:00:00这种格式,springboot中不能识别,将其转化为对象对应的日期属性。而是抛出异常信息,提示转换失败。

    代码:

    传参对应实体类

    public class Demo {
        private String id;
    
    
        private Date date;
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public Date getDate() {
            return date;
        }
    
        public void setDate(Date date) {
            this.date = date;
        }
    }

    controller

     @RequestMapping("/demo")
        public String demo(@RequestBody Demo demo) {
            System.out.println(demo.getId());
            return "this is client1";
        }

    ajax调用使用的postman

    请求报错:

    {
        "timestamp": "2018-09-17T14:01:00.278+0000",
        "status": 400,
        "error": "Bad Request",
        "message": "JSON parse error: Cannot deserialize value of type `java.util.Date` from String "2018-09-17 21:46:08": not a valid representation (error: Failed to parse Date value '2018-09-17 21:46:08': Cannot parse date "2018-09-17 21:46:08": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSZ', parsing fails (leniency? null)); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.util.Date` from String "2018-09-17 21:46:08": not a valid representation (error: Failed to parse Date value '2018-09-17 21:46:08': Cannot parse date "2018-09-17 21:46:08": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSZ', parsing fails (leniency? null))
     at [Source: (PushbackInputStream); line: 3, column: 9] (through reference chain: com.hanggle.eurekaclient.Demo["date"])",
        "path": "/demo"
    }

    错误原因是日期转换失败,由于springboot默认采用jackson,而jackson只能识别以下几种日期格式:

    "yyyy-MM-dd'T'HH:mm:ss.SSSZ""yyyy-MM-dd'T'HH:mm:ss.SSS'Z'""yyyy-MM-dd";
    
    "EEE, dd MMM yyyy HH:mm:ss zzz";
    
    long类型的时间戳(毫秒时间戳)

    不能识别yyyy-MM-dd HH:mm:ss类似格式的数据,所以转换失败。 

    解决办法有以下几种:

    1. 采用long时间戳(毫秒时间戳!!!!)如:1537191968000 

    2.在传参的对象上加上@JsonFormat注解并且指定时区(此方法治标不治本)

    @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")

    如果项目中使用json解析框架为fastjson框架,则可使用如下解决方法:
    在实体字段上使用@JsonFormat注解格式化日期

    @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")

    3、采用全局处理方式统一处理,推荐这个做法

    重写springboot默认转换

     参考:https://blog.csdn.net/qq906627950/article/details/79503801

    public class MyDateFormat extends DateFormat {
    
        private DateFormat dateFormat;
    
        private SimpleDateFormat format1 = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
    
        public MyDateFormat(DateFormat dateFormat) {
            this.dateFormat = dateFormat;
        }
    
        @Override
        public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
            return dateFormat.format(date, toAppendTo, fieldPosition);
        }
    
        @Override
        public Date parse(String source, ParsePosition pos) {
    
            Date date = null;
    
            try {
    
                date = format1.parse(source, pos);
            } catch (Exception e) {
    
                date = dateFormat.parse(source, pos);
            }
    
            return date;
        }
    
        // 主要还是装饰这个方法
        @Override
        public Date parse(String source) throws ParseException {
    
            Date date = null;
    
            try {
    
                // 先按我的规则来
                date = format1.parse(source);
            } catch (Exception e) {
    
                // 不行,那就按原先的规则吧
                date = dateFormat.parse(source);
            }
    
            return date;
        }
    
        // 这里装饰clone方法的原因是因为clone方法在jackson中也有用到
        @Override
        public Object clone() {
            Object format = dateFormat.clone();
            return new MyDateFormat((DateFormat) format);
        }
    
    
    }
    @Configuration
    public class WebConfig {
    
        @Autowired
        private Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder;
    
        @Bean
        public MappingJackson2HttpMessageConverter MappingJsonpHttpMessageConverter() {
    
            ObjectMapper mapper = jackson2ObjectMapperBuilder.build();
    
            // ObjectMapper为了保障线程安全性,里面的配置类都是一个不可变的对象
            // 所以这里的setDateFormat的内部原理其实是创建了一个新的配置类
            DateFormat dateFormat = mapper.getDateFormat();
            mapper.setDateFormat(new MyDateFormat(dateFormat));
    
            MappingJackson2HttpMessageConverter mappingJsonpHttpMessageConverter = new MappingJackson2HttpMessageConverter(
                    mapper);
            return mappingJsonpHttpMessageConverter;
        }
    
    }

     参考资料:

    https://blog.csdn.net/pp_fzp/article/details/79588374

    https://blog.csdn.net/qq906627950/article/details/79503801

  • 相关阅读:
    属性序列化自定义与字母表排序-JSON框架Jackson精解第3篇
    URL及日期等特殊数据格式处理-JSON框架Jackson精解第2篇
    JSON数据处理框架Jackson精解第一篇-序列化与反序列化核心用法
    开源项目-跨项目及操作系统的通用代码生成器,解放您的双手
    图解并发与并行-分别从CPU和线程的角度理解
    8成以上的java线程状态图都画错了,看看这个-图解java并发第二篇
    面霸告诉你这些技术面试的非技术性经验,让你的面试成功率显著提升
    List集合对象去重及按属性去重的8种方法-java基础总结系列第六篇
    图解进程线程、互斥锁与信号量-看完不懂你来打我
    总结java中文件拷贝剪切的5种方式-JAVA IO基础总结第五篇
  • 原文地址:https://www.cnblogs.com/oskyhg/p/9665627.html
Copyright © 2011-2022 走看看