0x03:一次时间序列化问题
0x03一次时间序列化问题
问题描述:
数据库中:时间是2023-06-08 16:00:00
前端接口请求后返回:2023-06-09 00:00:00
处理步骤:
前端数据从buiness服务返回,业务服务是order。
先大致锁定是那个环节出了问题:
1.数据库->order服务?
通过日志判断数据库传到order服务是正确的。
2.order服务返回给business服务?
因为spring默认是用Jackson 序列话,故在两个服务的controller输出序列话结果。
@Autowired
private ObjectMapper objectMapper;
try {
String json = objectMapper.writeValueAsString(complainSuggestionDTO);
System.out.println("order服务序列化结果:" + json);
} catch (Exception e) {
System.out.println(e.getMessage());
}
String json = objectMapper.writeValueAsString(orderComplainSuggestionDTO);
System.out.println("business服务序列化结果:" + json);
输出结果如下:
order:
business:
order服务正常,business服务就错了。
deepseek给出的原因:
- 数据库时区与服务端时区不匹配
- 序列化框架时区配置问题
- 数据库连接配置缺失
数据库时区是正确的,排除1
通过检查配置,数据库连接也是正确的,排除3
需要验证是否是jackson的时区配置不正确
两个服务的配置均有:time-zone: Asia/Shanghai
@PostConstruct
public void checkConfig() {
System.out.println("当前时区:" + objectMapper.getSerializationConfig().getTimeZone());
System.out.println("日期格式:" + objectMapper.getDateFormat());
}
两个服务的配置也均为 Asia/Shanghai:
因为该字段有注解:
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
部分回答中提到注解需要加上时区
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss" ,timezone = "Asia/Shanghai")
经过测试 注解加上时区后,两个服务的时间就一致了。至此,算时间解决了问题。
等等?还有最重要的why?为什么已经指定了jackson的时区,还是需要在注解中再次指定?注解加上时区后序列话有所不同吗?
在wireshark中不加注解,端口出去的是:
加了注解端口出去的还是
也就是注解并不会影响http传输的内容
deepseek给的解释是:
- 字段注解优先级覆盖了全局配置,注解中没有明确指明就使用的jvm默认时区。
- 因为序列化时没有携带时区信息,反序列化时将其当作默认时区再按照本地时区给+8小时。
最终原因:
太难debug了,找到后面发现restTemplate里的ObjectMapper 的baseconfig里的时区为null,解析时发现注解没有指定get方法就返回了默认UTC时区。可是为什么配置中已经有了jackson:time-zone: Asia/Shanghai,且Autowired的ObjectMapper时区是对的,为什么restTemplate里的Mapper就没有时区呢?可能不是同一个对象。
fuck:restTemplate 是用的 Jackson2ObjectMapperBuilder.json().build() 不是spring 自动管理的,故配置无效。