SpringBoot中 Jackson 日期的时区和日期格式问题解决

 更新时间:2022年12月10日 11:29:41   作者:蜀山雪松  
因为最近项目需要国际化,需要能够支持多种国际化语言,目前需要支持三种(法语、英语、简体中文),这篇文章主要介绍了SpringBoot中 Jackson 日期的时区和日期格式问题,需要的朋友可以参考下

1、使用场景

        因为最近项目需要国际化,需要能够支持多种国际化语言,目前需要支持三种(法语、英语、简体中文)。我们的项目部署环境为使用阿里云(德国)节点。以前我们项目主要用户在中国国内。一部署到德国服务器节点就出现一个问题了。数据返回的时间不对,存储的时间也有时差了。此文章仅仅与UTC标准时间与北京时间(东八区时间)作为实际例子。最后跟踪发现,如下几点原因:

1.1、数据库MySQL也是有时区的概念的。

     通过如下命令可以查询MySQL的时区

 show variables like "%time_zone%";

如果未做任何修改会显示如下:

+------------------+--------+
| Variable_name  | Value |
+------------------+--------+
| system_time_zone | CST  |
| time_zone    | SYSTEM |
+------------------+--------+
2 rows in set (0.00 sec)
#time_zone说明mysql使用system的时区,system_time_zone说明system使用CST时区

1.2、系统时区意味着与计算机的操作系统时区相同。

以下是我们北京时间使用MySQL时区

 set global time_zone = '+8:00'; ##修改mysql全局时区为北京时间,即我们所在的东8区
> set time_zone = '+8:00'; ##修改当前会话时区
> flush privileges; #立即生效

或者通过修改MySQL的 my.cnf配置文件来修改时区
# vim /etc/my.cnf ##在[mysqld]区域中加上
default-time_zone = '+8:00'
# /etc/init.d/mysqld restart ##重启mysql使新时区生效

1.2、SpringBoot默认的Json视图转换框架Jackson也有时区概念

     Jackson日期反序列化时区问题,Jackson里 JsonFormat的源码

/**
 * Value that indicates that default {@link java.util.TimeZone}
 * (from deserialization or serialization context) should be used:
 * annotation does not define value to use.
 *<p>
 * NOTE: default here does NOT mean JVM defaults but Jackson databindings
 * default, usually UTC, but may be changed on <code>ObjectMapper</code>.
 */
public final static String DEFAULT_TIMEZONE = "##default";
 
值,该值指示默认{@链接java.util.TimeZone}
 
(来自反序列化或序列化上下文)应使用:
 
注释未定义要使用的值。
 
注意:这里的默认值并不意味着JVM默认值,而是Jackson数据绑定。
 
默认值,通常为UTC,但可以在<code>objectmapper<code>上更改。

那个注释已经说明默认情况下会将 时区设置为UTC ,Jackson反序列化时间类型的底层实际上调用的是Java的 SimpleDateFormat#parse() 方法,而JVM中的时区则会根据你的操作系统来获取,所以JVM认为你的时区应该是 GMT+8 时区,
而要将 UTC 时区的时间转成 GMT+8 时区的时间,就会将你传进来的时间+8个小时。

2、代码实现

2.1、解决方案一下在每个带有日期地方加上注解

日期类型的字段上的 @JsonFormat 加上属性 timezone="GMT+8"

@NotNull
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
@JsonProperty("start_time")
private Date startTime;

此类方法需要在包含日期地方都加上注解属性,比较繁琐。

2.2、只需要配置一个bean实现整体修改

@Bean
    public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
        return jacksonObjectMapperBuilder ->
                jacksonObjectMapperBuilder.timeZone(TimeZone.getTimeZone("GMT+8"));
    }

参考文章:Jackson日期反序列化时区问题

2.3、使用SpringBoot的配置方式

spring.jackson.default-property-inclusion=NON_NULL
spring.jackson.time-zone=GMT+8
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss

第一个设置就是使用24小时的时间格式;第二个设置就是设置时区为东八区。

但是配置时候需要注意

Finally, if you opt out of the Spring Boot default MVC configuration by providing your own @EnableWebMvc configuration, you can take control completely and do everything manually by using getMessageConverters from WebMvcConfigurationSupport.

《Spring Boot Reference Guide》 

需要去掉

@EnableWebMvc

参考文章:

SpringBoot升级指定jackson版本的问题

SpringBoot利用jackson格式化时间的三种方法

java如何利用FastJSON、Gson、Jackson三种Json格式工具自定义时间序列化

3、成果展现

        经过转换配置转换之后;能够正确的获得和存取对应的时间,建议使用

        2.2、只需要配置一个bean实现整体修改 或者使用 2.3、使用SpringBoot的配置方式 方式比较通用性。

其中如果使用FastJson转换也可能遇见同样的问题,可以参考文章

springmvc fastjson 反序列化时间格式化方法(推荐)

4、总结

       在SpringBoot开发应用之中设计日期转换需要特别注意,能够主要目标能够是的存储和返回的日期能够对应上自己的本地时区。同时能够使用较为通用的转换方式解决相关问题。

相关文章

  • 解决JDK8的ParallelStream遍历无序的问题

    解决JDK8的ParallelStream遍历无序的问题

    这篇文章主要介绍了解决JDK8的ParallelStream遍历无序的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 普通对象使用spring容器中的对象的实现方法

    普通对象使用spring容器中的对象的实现方法

    这篇文章主要介绍了普通对象使用spring容器中的对象的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-06-06
  • RocketMQ设计之故障规避机制

    RocketMQ设计之故障规避机制

    这篇文章主要介绍了RocketMQ设计之故障规避机制,故障规避机制就是用来解决当Broker出现故障,Producer不能及时感知而导致消息发送失败的问题,下面详细介绍需要的小伙伴可以参考一下
    2022-03-03
  • Java中的Unsafe在安全领域的使用总结和复现(实例详解)

    Java中的Unsafe在安全领域的使用总结和复现(实例详解)

    unsafe里面有很多好用的方法,比如allocateInstance可以直接创建实例对象,defineAnonymousClass可以创建一个VM匿名类(VM Anonymous Class),以及直接从内存级别修改对象的值。这篇文章主要介绍了Java中的Unsafe在安全领域的一些应用总结和复现,需要的朋友可以参考下
    2022-03-03
  • 枚举java语言中的修饰符组合的实例代码

    枚举java语言中的修饰符组合的实例代码

    这篇文章主要介绍了枚举java语言中的修饰符组合,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-07-07
  • mybatis查询实现返回List<Map>类型数据操作

    mybatis查询实现返回List<Map>类型数据操作

    这篇文章主要介绍了mybatis查询实现返回List<Map>类型数据操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • java解析多层嵌套json字符串问题

    java解析多层嵌套json字符串问题

    这篇文章主要介绍了java解析多层嵌套json字符串问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • Spring学习之动态代理(JDK动态代理和CGLIB动态代理)

    Spring学习之动态代理(JDK动态代理和CGLIB动态代理)

    本篇文章主要介绍了Spring学习之动态代理(JDK动态代理和CGLIB动态代理),具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • java使用链表来模拟栈的入栈出栈操作实例代码

    java使用链表来模拟栈的入栈出栈操作实例代码

    这篇文章主要介绍了java 使用链表来模拟栈的入栈出栈操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • 在SpringBoot当中使用Thymeleaf视图解析器的详细教程

    在SpringBoot当中使用Thymeleaf视图解析器的详细教程

    Thymeleaf是一款开源的模板引擎,它允许前端开发者使用HTML与XML编写动态网页,hymeleaf的主要特点是将表达式语言嵌入到HTML结构中,它支持Spring框架,使得在Spring MVC应用中集成非常方便,本文给大家介绍了在SpringBoot当中使用Thymeleaf视图解析器的详细教程
    2024-09-09

最新评论