场景
海外业务 数据库查询存储的事件和页面展示的事件不正确,数据库 create_time=2024-04-10 05:50:42 服务器地区UTC+3,国内页面展示 create_time=2024-04-10 10:50:42 相差了5个小时(国内东八区)
- 流程 http请求->数据库查询
create_time=2024-04-10 05:50:42-> json序列化create_time=1712717442000时间戳 - json序列化代码:
public class JacksonConfig {
// 序列化LocalDateTime
@Bean
@Primary
public ObjectMapper serializingObjectMapper(
Jackson2ObjectMapperBuilder builder, JacksonProperties jacksonProperties) {
ObjectMapper objectMapper = builder.build();
// 把“忽略重复的模块注册”禁用,否则下面的注册不生效
objectMapper.disable(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS);
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
objectMapper.registerModule(javaTimeModule);
// 重新设置为生效,避免被其他地方覆盖
objectMapper.enable(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS);
return objectMapper;
}
// 序列化实现
public static class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
@Override
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers)
throws IOException {
if (value != null) {
long timestamp =
value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
gen.writeNumber(timestamp);
}
}
}
// 反序列化实现
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;
}
}
}
}
最终发现时间戳转换到日期的时候是根据时区来的,这个时候只要把本地时区改成东三区就可以显示正确,如果是东八区时区 就会转到北京时间来显示 所以会出现差异