SpringBoot如何根据用户系统时区动态展示时间
作者:RealJt 发布时间:2021-09-23 23:37:10
根据用户系统时区动态展示时间
当我们使用SpringBoot+Mysql开发系统时,总是统一设置UTC+8时区,这样用户在任何地区访问系统,展示的时间都是国内标准时间,体验不友好,下面通过获取当前用户系统所在的时区,给用户展示不同的时间。
一、用户时区的获取
我们可以通过JavaScript来获取系统所在的时区,然后统一设置在请求头里。
Intl.DateTimeFormat().resolvedOptions().timeZone; // Asia/Shanghai
二、核心代码
这里统一使用LocalDateTime,更方便的处理时区转换问题,通过标识当前LocalDateTime对象所属时区,然后转换为目标时区时间。
public LocalDateTime convertLocalDateTime(LocalDateTime localDateTime, ZoneId originZoneId,
ZoneId targetZoneId)
{
return localDateTime.atZone(originZoneId).withZoneSameInstant(targetZoneId).toLocalDateTime();
}
三、SpringBoot返回json时统一处理时区
当程序从数据库中读取出并转换成LocalDateTime对象,并经过业务逻辑处理,这时候该对象还是属于UTC+8时区,对应的ZoneId=Asia/Shanghai,当需要返回给前端时,可以通过自定义jackson序列化器,在LocalDateTime转json前转换到用户目标时区。
@Configuration
public class JacksonConfiguration
{
@Autowired
private JacksonProperties jacksonProperties;/**
* 时区转换
*
* @param localDateTime
* @param originZoneId
* @param targetZoneId
* @return
*/
public static LocalDateTime convertLocalDateTime(LocalDateTime localDateTime, ZoneId originZoneId,
ZoneId targetZoneId)
{
return localDateTime.atZone(originZoneId).withZoneSameInstant(targetZoneId).toLocalDateTime();
}/**
* LocalDateTime序列化
*/
public static class CustomLocalDateTimeSerializer extends JsonSerializer<LocalDateTime>
{
private DateTimeFormatter formatter;public CustomLocalDateTimeSerializer(DateTimeFormatter formatter)
{
super();
this.formatter = formatter;
}@Override
public void serialize(LocalDateTime value, JsonGenerator generator, SerializerProvider provider)
throws IOException
{
generator.writeString(convertLocalDateTime(value, ZoneId.of("Asia/Shanghai"), ZoneId.of("Africa/Sao_Tome"))
.format(formatter));
}}/**
* LocalDateTime反序列化
*
*/
public static class CustomLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime>
{
private DateTimeFormatter formatter;public CustomLocalDateTimeDeserializer(DateTimeFormatter formatter)
{
super();
this.formatter = formatter;
}@Override
public LocalDateTime deserialize(JsonParser parser, DeserializationContext context)
throws IOException, JacksonException
{
return convertLocalDateTime(LocalDateTime.parse(parser.getText(), formatter), ZoneId.of("Africa/Sao_Tome"),
ZoneId.of("Asia/Shanghai"));
}}@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer()
{
return builder ->
{
builder.serializerByType(LocalDateTime.class,
new CustomLocalDateTimeSerializer(DateTimeFormatter.ofPattern(jacksonProperties.getDateFormat())));
builder.deserializerByType(LocalDateTime.class,
new CustomLocalDateTimeDeserializer(DateTimeFormatter.ofPattern(jacksonProperties.getDateFormat())));
};
}
}
上面示例代码设定用户时区ZoneId=Africa/Sao_Tome,并且自定义处理了LocalDateTime反序列化器,当使用ResquestBody注解时,对象中的LocalDateTime属性值也会转换成UTC+8时区,不用再额外处理,可直接保存到数据库。
四、SpringBoot接收时间参数统一处理时区
除了上面所说通过ResquestBody注解来接收参数外,还可能通过Get或者Post参数来接收LocalDateTime对象,这时候我们就要自定义一个Converter来处理String转换到LocalDateTime,同时把用户提交的属于用户时区的对象转换成UTC+8时区对象。
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer
{
@Autowired
private WebMvcProperties webMvcProperties;@Override
public void addFormatters(FormatterRegistry registry)
{
registry.addConverter(new Converter<String, LocalDateTime>()
{private LocalDateTime convertLocalDateTime(LocalDateTime localDateTime, ZoneId originZoneId,
ZoneId targetZoneId)
{
return localDateTime.atZone(originZoneId).withZoneSameInstant(targetZoneId).toLocalDateTime();
}@Override
public LocalDateTime convert(String source)
{
return convertLocalDateTime(
LocalDateTime.parse(source,
DateTimeFormatter.ofPattern(webMvcProperties.getFormat().getDateTime())),
ZoneId.of("Africa/Sao_Tome"), ZoneId.of("Asia/Shanghai"));
}});
}}
五、总结
通过上面的处理,JavaScript负责获取用户时区,并且每次请求时带到后台,后台在接收请求和返回前端时统一转换用户时区,业务处理时不必再考虑时区问题。
来源:https://blog.csdn.net/juntian2008/article/details/123867977


猜你喜欢
- 一、概述:在日常的app使用中,我们会在android 的app中看见 热门标签等自动换行的流式布局,今天,我们就来看看如何自定义一个类似热
- 前言WorkManager 是 Android Jetpack 中的新组件,用于负责管理后台任务。关于这个组件的介绍就不多说了,网上到处都是
- 前言在 上一节 Spring解密 - 默认标签的解析 中,重点分析了 Spring 对默认标签是如何解析的,那么本章继续讲解标签解析,着重讲
- 内存对齐的基本原则:结构(struct/class)的内置类型数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的起始位置
- 二叉排序树,又称为二叉查找树。它或者是一颗空树,或者是具有下列性质的二叉树:若它的左子树不为空。则左子树上所有的结点的值均小于跟的结点值若它
- 0. Iochttps://docs.spring.io/spring-framework/docs/current/spring-fram
- 因为项目需要,需要在一个之前没做过springBoot项目的eclipse上跑一个springBoot项目并完成打包,所以就在网上查完资料以
- Android:4.4.4一、应用场景在Android设备上,现在我们外接了一个USB转串口的设备,设备节点是/dev/ttyUSB0:#
- 前言你可能看到Java程序员每周的工作是编码开发一个可伸缩的Web应用程序,或创建一个动态的网站,或者开发高效的电子商务产品页面,也可能是开
- 继承反应了类和类之间的关系。世界上很多事物都是有共性的,共性的那一部分我们就抽象为基类,用于派生其它类,这样提高了代码的复用性,使得代码的结
- service有两种类型:本地服务(Local Service):用于应用程序内部远程服务(Remote Sercie):用于android
- 在有些时候,我们需要从数据库读取数据填充对象或从硬盘读取文件填充对象,但是这样做相对耗时。这时候我们就想到了对象的拷贝。本文即以实例形式解析
- int -> String int i=12345;String s="";核心:s=i+""
- volatile关键字相信了解Java多线程的读者都很清楚它的作用。volatile关键字用于声明简单类型变量,如int、float、boo
- 一、概念1.1、什么是服务治理Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务治理服务治理就是提供
- 0. Grinder – Grinder是一个开源的JVM负载测试框架,它通过很多负载注射器来为分布式测试提
- 本文实例为大家分享了android实现圆环倒计时控件的具体代码,供大家参考,具体内容如下1.自定义属性<?xml version=&q
- 今年新开Java课程第一步就是…配置环境就从Java的环境配置开始好了以下是正式的步骤首先,从Oracle的官网下载jdk的安装包点我下载J
- 本文实例讲述了C#实现对文件进行加密解密的方法。分享给大家供大家参考。具体如下:using System;using System.IO;u
- 概述关于 static 关键字的使用,它可以用来修饰的成员变量和成员方法,被修饰的成员是属于类的,而不是单单是属 于某个对象的。也就是说,既