当前位置:网站首页>关于LocalDateTime的全局返回时间带“T“的时间格式处理
关于LocalDateTime的全局返回时间带“T“的时间格式处理
2022-07-31 05:08:00 【m0_67401920】
关于LocalDateTime的全局返回带"T"的时间格式处理
关于背景的大概描述,如下。
时间类型LocalDateTime相较于于Date的确有自己独特的优势,因此在之后的版本迭代上,将部分隔离开的模块使用了新型的LocalDateTime替代了Date,因已经使用了全局时间转换,但是测试的时候发现返回的时间格式很奇怪 2022-01-01T00:00:00.000,全局时间序列化、反序列化并没有起作用,寻找相关资料和DEGBU之后将相关资料整理如下。
目前常用的时间类型格式如下:
时间类型
时间默认格式
Date
Tue Feb 01 00:00:00 CST 2022
Timestamp
2022-01-01 00:00:00.0
LocalDateTime
2022-01-01T00:00:00.000
1.关于jackson的全局返回带T的处理方式
对于Date和Timestamp在引入LocalDateTime之前是经过spring.jackson.date-format进行全局数据绑定格式化时间类型。
spring:
jackson:
date-format: 格式化类
在格式化类中添加对LocalDateTime的格式化语句发现无效果。经过搜索资料后发现在使用jackson在对localDateTime类型的序列化和反序列化方法另有其他方法。(这里不输出关于源码内的信息。可自行查看。)
// 涉及源码类 其余的可自行debug追踪
Jackson2ObjectMapperBuilder
Jackson2ObjectMapperBuilderCustomizer // 最终做处理的服务类
JacksonAutoConfiguration
@Configuration
public class LocalDateTimeSerializerConfig {
// jackson注册的时候会将序列化和反序列化的方法提前注册进,做数据转换会自行根据具体的实现去调用。
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return builder -> {
builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
builder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer());
};
}
/**
* 反序列化
*/
public static class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext)
throws IOException {
long timestamp = p.getValueAsLong();
if (timestamp > 0) {
return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
} else {
return null;
}
}
}
}
2.关于fastjson的全局返回带T的处理方式
使用fastjson进行时间格式化处理,自己写的类去实现 WebMvcConfigurer配置类,重写父类方法configureMessageConverters,在进行全局时间返回格式绑定后,之前使用的格式化时间类是fastjson自身提供的SimpleDateFormatSerializer方法,发现在进行对LocalDateTime添加后进行时间转化返回后存在异常,异常信息提示LocalDateTime不能强转为Date,进行多次DEBUG跟踪后定位到了SimpleDateFormatSerializer方法内部,会将拿到的value直接进行Date的强转,SimpleDateFormatSerializer源码如下
public class SimpleDateFormatSerializer implements ObjectSerializer {
private final String pattern;
public SimpleDateFormatSerializer(String pattern){
this.pattern = pattern;
}
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
if (object == null) {
serializer.out.writeNull();
return;
}
// 对LocalDateTime 进行强制转换,此处会报错。因此,主要的重点改造就是此处。
Date date = (Date) object;
SimpleDateFormat format = new SimpleDateFormat(pattern, serializer.locale);
format.setTimeZone(serializer.timeZone);
String text = format.format(date);
serializer.write(text);
}
}
既然已经发现问题的关键点那对关键点进行处理即可,目前有两个方法:
- 写好SimpleDateFormatSerializer的继承类
- 实现ObjectSerializer的write方法进行处理。
我选用的是第一种方式对SimpleDateFormatSerializer集成后重写write方法,因为之前的时间格式已经使用的SimpleDateFormatSerializer进行处理,为了稳定进行最小程度的调整。结果如下
public class OwnSimpleDateFormatSerializer extends SimpleDateFormatSerializer {
private final String pattern;
public OwnSimpleDateFormatSerializer (String pattern) {
super(pattern);
this.pattern = pattern;
}
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
if (object == null) {
serializer.out.writeNull();
} else {
Date date = null;
// 改造内容 增加类型判断进行处理
if (object instanceof LocalDateTime) {
LocalDateTime localDateTime = (LocalDateTime) object;
date = Date.from(localDateTime.atZone( ZoneId.systemDefault()).toInstant());
} else {
date = (Date)object;
}
SimpleDateFormat format = new SimpleDateFormat(this.pattern, Locale.SIMPLIFIED_CHINESE);
TimeZone timeZone = new ZoneInfo();
timeZone.setRawOffset(28800000);
timeZone.setID("Asia/Shanghai");
format.setTimeZone(timeZone);
String text = format.format(date);
serializer.write(text);
}
}
}
// 涉及类
WebMvcConfigurer
SimpleDateFormatSerializer // 之前使用的时间格式化类
ObjectSerializer // 最终执行时间格式化处理的服务类
FastJsonConfig // 配置类
SerializeConfig // 序列化配置信息
@Component
public class DefaultMvcFilter implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// ...
// 重点在此 对FastJsonConfig进行配置
FastJsonConfig fastJsonConfig = new FastJsonConfig();
// 修改全局json配置
SerializeConfig serializeConfig = SerializeConfig.globalInstance;
// 格式化时间
serializeConfig.put(Date.class, new OwnSimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
serializeConfig.put(java.sql.Date.class, new OwnSimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
serializeConfig.put(java.sql.Timestamp.class, new OwnSimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
serializeConfig.put(java.sql.Time.class, new OwnSimpleDateFormatSerializer("HH:mm:ss"));
// 对LocalDateTime进行时间格式化 注意序列化的实现类 是需要自己写的,并不是使用fastjson自带的SimpleDateFormatSerializer
serializeConfig.put(LocalDateTime.class, new OwnSimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
fastJsonConfig.setSerializeConfig(serializeConfig);
fastJsonConfig.setSerializerFeatures(
SerializerFeature.WriteDateUseDateFormat,
SerializerFeature.IgnoreErrorGetter,
SerializerFeature.WriteNullNumberAsZero,
SerializerFeature.WriteNullBooleanAsFalse,
SerializerFeature.DisableCircularReferenceDetect
);
}
}
以上对于jackson和fastjson改造完成后进行测试,发现时间格式全部展示正确,以此来记录问题发生和处理方式。主要还是根据源码跟踪来确定问题,问题确定后的处理就会有很多方式了,选择最适用的处理方式即可。
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦
边栏推荐
- MySQL optimization slow log query
- 快速掌握并发编程 --- 基础篇
- ERROR 1064 (42000) You have an error in your SQL syntax; check the manual that corresponds to your
- sql语句-如何以一个表中的数据为条件据查询另一个表中的数据
- ERROR 1819 (HY000) Your password does not satisfy the current policy requirements
- Minio upload file ssl certificate is not trusted
- MySQL8.0安装教程,在Linux环境安装MySQL8.0教程,最新教程 超详细
- The 15th day of the special assault version of the sword offer
- matlab abel变换图片处理
- Duplicate entry ‘XXX‘ for key ‘XXX.PRIMARY‘解决方案。
猜你喜欢
STM32 - DMA
MySQL optimization slow log query
Heavyweight | The Open Atomic School Source Line activity was officially launched
<urlopen error [Errno 11001] getaddrinfo failed>的解决、isinstance()函数初略介绍
三道leetcode上的oj题
DVWA安装教程(懂你的不懂·详细)
Moment Pool Cloud quickly installs packages such as torch-sparse and torch-geometric
Unity框架设计系列:Unity 如何设计网络框架
mysql存储过程
【一起学Rust】Rust学习前准备——注释和格式化输出
随机推荐
STM32 - DMA
Numpy中np.meshgrid的简单用法示例
Temporal客户端模型
mysql使用on duplicate key update批量更新数据
一文了解大厂的DDD领域驱动设计
ERROR 1819 (HY000) Your password does not satisfy the current policy requirements
三道leetcode上的oj题
CentOS7 安装MySQL 图文详细教程
mysql stored procedure
Unity shader forge和自带的shader graph,有哪些优缺点?
Mysql应用安装后找不到my.ini文件
Go中间件
PCL calculates the point cloud coordinate maximum and its index
Simple read operation of EasyExcel
【ORACLE Explain 详解】
MySQL8--Windows下使用压缩包安装的方法
ABC D - Distinct Trio (Number of k-tuples
Shell重油常压塔模拟仿真与控制
Minio upload file ssl certificate is not trusted
Temporal介绍