LocalDateTime在项目中的使用(LocalDateTime对接前端通过时间戳互转、LocalDateTime对接数据库)

您所在的位置:网站首页 localdatetime反序列化 LocalDateTime在项目中的使用(LocalDateTime对接前端通过时间戳互转、LocalDateTime对接数据库)

LocalDateTime在项目中的使用(LocalDateTime对接前端通过时间戳互转、LocalDateTime对接数据库)

2024-01-19 07:51| 来源: 网络整理| 查看: 265

目录1. 博客编写背景2. LocalDateTime 前端交互2.1 LocalDateTime 向前端写入时间戳2.1.1 fastJson 默认的写入格式2.1.2 更改 fastJson 写入格式,让其回写时间戳 (★★★)2.2 接收前端传递的时间戳为 LocalDateTimme2.2.1 Post 请求参数封装1. LocalDateTime 默认接收的格式2. 更改 fastJson 反序列化方法,让其能够转换时间戳为 LocalDateTime(★★★)3. 【坑】更改 SpringBoot 的 @RequestBody 为 fastJson 接收(★★★)2.2.2 GET 请求参数封装3. LocalDateTime 与数据库交互(★★★)3.1 【坑】数据库交互LocalDateTime被四舍五入(★★★)

1. 博客编写背景

本文章的编写背景:由于在 JDK 8 中,Date、Timestamp 对象已经不推荐使用,所以在公司的新项目上,我计划将 LocalDateTime 使用在新项目中。

由于本人所在项目组,统一的前后端时间的交互方式为时间戳,而时间戳并不能直接被fastJson 或 jackson 直接转换,所以踩了不少的坑,个人建议有耐心的看完。

实现的效果如下:

前端传递时间戳 { "localDateTime": 1584700466000 } 后端返回时间戳 { "code": "0", "desc": "请求成功", "data": { "localDateTime": 1584700466000 } }

========================================================

若是感觉废话比较多,那么直接看标注了【★★★】的即可 个人写这个博客,并不想直接写结论,更多的是想给读者分享踩坑的过程

========================================================

2. LocalDateTime 前端交互 2.1 LocalDateTime 向前端写入时间戳 2.1.1 fastJson 默认的写入格式

本项目使用的是 fastJson 会写前端,我们先看下以下代码

回写前端的 VO 对象 @Data public class LocalDateTimeVO { private LocalDateTime localDateTime; } 测试方法 public static void main(String[] args) { LocalDateTimeVO localDateTimeVO = new LocalDateTimeVO(); localDateTimeVO.setLocalDateTime(LocalDateTime.now()); String json = JSON.toJSONString(localDateTimeVO); System.out.println(json); } 控制台输出 {"localDateTime":"2020-03-12T23:00:28.747"}

从上图中可以看出,服务端并不能正常的返回时间戳给前端。并不符合需求。

2.1.2 更改 fastJson 写入格式,让其回写时间戳 (★★★) fastJson提供了自定义 json 转换的方法 @JSONFiled,我们添加 serializeUsing,将其指定到我们自定义的序列化控制器即可。 自定义 fastJson 序列化转换器,重写 ObjectSerializer /** * 由于 LocalDateTime 类型在转换 JSON 的时候,并不能被转换为字符串,使用 @JsonFormat 只能转换为指定的 pattern 类型,因此我们需要自定义一个序列化执行器 * LocalDateTime 序列化(将 LocalDateTime类型 转换为 时间戳 返回给前端 ) * * @author Chimm Huang * @date 2020/3/7 */ public class LocalDateTimeSerializer implements ObjectSerializer { @Override public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException { if (object != null) { LocalDateTime localDateTime = (LocalDateTime) object; //将localDateTime转换为中国区(+8)时间戳。 serializer.write(localDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli()); } else { serializer.write(null); } } } 使用我们自己写的 fastJson 序列化转换器 @Data public class LocalDateTimeVO { @JSONField(serializeUsing = LocalDateTimeSerializer.class) private LocalDateTime localDateTime; } 再次执行测试方法,控制台输出 {"localDateTime":1584026032912}

可以看出,LocalDateTime 已经成功被转换为了时间戳,并且可以返回给前端。

2.2 接收前端传递的时间戳为 LocalDateTimme 2.2.1 Post 请求参数封装 1. LocalDateTime 默认接收的格式

不管我们传递时间戳(1584026032912),还是传递自定义格式("2020-03-13"),在服务端接受的时候,都会报错400。也就是说,传入的格式是错误的,无法被 spring 转换为 LocalDateTime

经过我的粗略测试,我发现,默认的接受格式为 LocalDateTime 特有的格式,即:2020-03-12T23:00:28.747,除此之外都会报400。这种格式与 Date 格式的唯一区别就在于,Date 在日与时之间是用空格区分的,而 LocalDateTime 是用 T 来区分的。

2. 更改 fastJson 反序列化方法,让其能够转换时间戳为 LocalDateTime(★★★) fastJson 提供的 @JSONField 注解包括了反序列化转换器的指定,因此,我们重写其方法 ObjectDeserializer /** * 由于 时间戳 并不能直接被 fastJSON 转换为 LocalDateTime 类型,因此我们需要自定义一个序列化执行器 * LocalDateTime 反序列化(将前端传递的 时间戳 转换为 LocalDateTime 类型) * * @author Chimm Huang * @date 2020/3/7 */ public class LocalDateTimeDeserializer implements ObjectDeserializer { @Override @SuppressWarnings("unchecked") public LocalDateTime deserialze(DefaultJSONParser parser, Type type, Object fieldName) { String timestampStr = parser.getLexer().numberString(); if (timestampStr == null || "".equals(timestampStr)) { return null; } timestampStr = timestampStr.replaceAll("\"", ""); long timestamp = Long.parseLong(timestampStr); if(timestamp == 0) { return null; } return Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.ofHours(8)).toLocalDateTime(); } @Override public int getFastMatchToken() { return 0; } } 使用我们自己写的 fastJson 反序列化转换器 @Data pubcli class LocalDateTimeVO { @JSONField(serializeUsing = LocalDateTimeSerializer.class, deserializeUsing = LocalDateTimeDeserializer.class) private LocalDateTime localDateTime; } 测试方法 public static void main(String[] args) { String json = "{\"localDateTime\":1584026032912}"; LocalDateTimeVO localDateTimeVO = JSON.parseObject(json, LocalDateTimeVO.class); System.out.println(localDateTimeVO); } 控制台执行结果展示 LocalDateTimeVO(localDateTime=2020-03-12T23:13:52.912)

可以看出,时间戳成功被 fastJson 接受,并转换为了 LocalDateTime。

3. 【坑】更改 SpringBoot 的 @RequestBody 为 fastJson 接收(★★★)

当你看到这个小标题时,肯定会很疑惑,我们项目目前不就是使用的 fastJson 吗? 实际情况经过我测试,得出的结论是,我们在回写前端的时候,是使用 fastJson 进行转换的,但是在接受 Json 的时候,是使用 Spring 默认的 jackson 来接受的,所以这会导致,我们重写了 fastJson 的反序列化方法并未执行。前端传递时间戳给后端,后端报错400。

因此,我们需要更改 spring 默认提供的 jackson 为 fastJson

/** * springboot 默认使用的是 jackson 进行 requestBody 请求的封装,该项目切换为使用 fastJson 进行请求封装和响应 * 配置 springboot 使用 fastJson 进行数据的请求接受和响应 * * @author Chimm Huang * @date 2020/3/7 */ @Configuration public class WebConfig implements WebMvcConfigurer { public HttpMessageConverter stringConverter() { return new StringHttpMessageConverter(StandardCharsets.UTF_8); } public FastJsonHttpMessageConverter fastConverter() { //1、定义一个convert转换消息的对象 FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); //2、添加fastJson的配置信息 FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures( SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteNullNumberAsZero, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullBooleanAsFalse); fastJsonConfig.setCharset(StandardCharsets.UTF_8); //2-1 处理中文乱码问题 List fastMediaTypes = new ArrayList(); fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); fastConverter.setSupportedMediaTypes(fastMediaTypes); //3、在convert中添加配置信息 fastConverter.setFastJsonConfig(fastJsonConfig); return fastConverter; } @Override public void extendMessageConverters(List


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3