问题描述
在API返回数据中含有Date类型的数据,这些数据在数据库中存储的格式为北京时间 yyyy-MM-dd HH:mm:ss
格式,API的方法中获取到的时间也正常,但是在接口返回的数据中,时间变为了标准时间
,格式也发生了变化,如:2021-07-28T06:30:10.378+00:00
。
原因分析
之所以会出现这样的情况,是因为Spring的消息转化机制引起的,对于返回值content-type
类型为application/json
格式的数据,默认使用jackson
来进行json序列化,使用的消息转换器为org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
关于消息转换器的内容可以参考:SpringMVC源码剖析——消息转换器HttpMessageConverter
知道了这些以后我们还可以对返回数据进行其他的处理:
将jackson替换为fastjson:Springboot替换默认jackSon为fastJson过程
定制化返回数据:SpringBoot定制@ResponseBody注解返回的Json格式
解决办法
由于返回值content-type
类型为application/json
格式的数据,默认使用jackson
来进行json序列化,所以只需要对jackson的属性进行设置即可,在配置文件中添加如下配置:
spring:
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
- 默认情况下会将 时区设置为UTC ,Jackson反序列化时间类型的底层实际上调用的是Java的 SimpleDateFormat#parse() 方法,而JVM中的时区则会根据你的操作系统来获取,所以JVM认为你的时区应该是 GMT+8 时区,而要将 UTC 时区的时间转成 GMT+8 时区的时间,就会将你传进来的时间+8个小时。
- 增加以上的配置的以后,则默认为接口的
入参时间字段
为(GMT+8)的时间;接口的出参为(GMT+8)的时间;【如果没有time-zone: GMT+8
的配置,则会对接收到的时间按照UTC时间进行处理,如果系统所在时区为GMT+8
,则会出现前端传过来的时间到后端以后被+8
的情况;在输出数据的时候,则会认为要输出的日期字符串的时区是0时区,而现在的web服务器的时区是东8区,0时区比当前web服务器的东8区,慢8小时,所以转成UTC 的0时区后在进行输出。】
除了使用上述的配置也可以使用以下方式,直接配置到具体的字段上:
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") // 设置出参的时区及格式
// @DateTimeFormat(pattern="yyyy-MM-dd")// 设置入参的格式
private Date createdDate;
连接数据库时的时区问题及serverTimeZone的作用
在开发过程中,经常会发现,在将时间数据传入到数据库时,传入时东八区的时间,到数据库中以后就比传入的时间少了8个小时【例如:传入2021-09-27 10:30:30,数据库中写入的却为2021-09-27 02:30:30】,其实出现这种问题的原因是因为mysql数据库服务所在的时区与web服务所在的时区不一致导致的,【如:web服务器是在东八区,而mysql则是处于标准时间所在时区】;这种问题常见的解法如下:
# 加上serverTimezone=Asia/Shanghai
jdbc:mysql://localhost:3306/learn?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
但是这里就存在两个问题:
- 时间的转换是在web服务器上进行的,还是在mysql上进行的?
- serverTimezone参数的作用是什么?
这里直接上结论:
1、时间的转换是在web服务服务器上进行的
,当从数据库中取值时,如果数据库服务器中存的时间为UTC时间,但是web服务器是在东八区,如果在web服务器中使用String
类型来接收的话,会看到接收到的时间数据与数据库中的保持一致;如果用Date
类型来接收的话,会转换为东八区的时间。
2、serverTimeZone的作用就是指定web服务器和mysql服务器的会话期间的mysql服务器时区,就是临时指定mysql服务器的时区。当不加这一个参数时,如果数据库服务器中存的时间为UTC时间,但是web服务器是在东八区,则web服务器检测到mysql服务器为UTC时间,则会对即将存入的时间-8
然后存入到数据库,所以就会出现传入的数据与数据库中存入数据不一致的情况。
本节内容参考博文:
serverTimeZone的作用,mysql的时区,时区问题