当前位置:网站首页>关于LocalDateTime的全局返回时间带“T“的时间格式处理
关于LocalDateTime的全局返回时间带“T“的时间格式处理
2022-08-01 16:57:00 【m0_61083409】
关于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开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦
边栏推荐
猜你喜欢
京东软件测试面试题,仅30题就已经拯救了50%的人
AntDB数据库亮相24届高速展,助力智慧高速创新应用
DOM series of touch screen events
C语言:表达式求值详解
每日优鲜大败局
[Dark Horse Morning Post] Hu Jun's endorsement of Wukong's financial management is suspected of fraud, which is suspected to involve 39 billion yuan; Fuling mustard responded that mustard ate toenails
MySQL加锁案例分析
【Unity,C#】哨兵射线触发器模板代码
Sftp中文件名乱码
Bugku-Misc-贝斯手
随机推荐
MLX90640 红外热成像仪测温模块开发笔记(完整版)
暑气渐敛,8月让我们开源一夏!
Winform message prompt box helper class
RecSys'22|CARCA:交叉注意力感知上下文和属性进行推荐
C#的DataTable帮助类
酷逼了 Pathetic Dog 第 304 场周赛
Go unit tests
C语言:表达式求值详解
2022年深圳市临床医学研究中心申请指南
金仓数据库KingbaseES安全指南--6.5. LDAP身份验证
SQL函数 TO_CHAR(一)
程序员架构修炼之道:如何设计“易理解”的系统架构?
matlab 基于奇偶校验的LSB隐藏水印 三种改进
Vulnhub靶机:HARRYPOTTER_ NAGINI
网站备案后没有找到站点 您没有将此域名或IP绑定到对应站点! 配置文件未生效!
在码云拉取代码后,调整了seata版本1.5.2。出现如下异常。是因为数据库表缺少字段导致的吗?
The anxiety of the post-90s was cured by the vegetable market
The site is not found after the website is filed. You have not bound this domain name or IP to the corresponding site! The configuration file does not take effect!
沈腾拯救暑期档
【建议收藏】技术面必考题:多线程、多进程