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
猜你喜欢
- mybatis-plus的代码生成器会在实体类中生成数据库所有字段,我们去用mapper接口查询时,会返回数据库所有的字段。但有些字段不是我
- 事件处理主要涉及:事件源,事件,事件处理者在GUI中事件源是事件发生的场所,通常是各个组件,如被单击的按钮;事件是用户对界面的操作,如操作键
- 一、返回一般数据类型比如要根据 id 属性获得数据库中的某个字段值。mapper 接口:// 根据 id 获得数据库中的 username
- 图片象对:经过理处过的jpg格式的位图(头像照片) 算
- 项目开发中为了保护用户隐私安全,一般都会用MD5进行密码加密以下就简单举例SpringBoot 实现Mysql使用MD5进行密码加密做一个简
- start方法和run方法$start()$方法用来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到$cpu$时间片,就
- 这篇文章主要介绍了spring如何实现两个xml配置文件间的互调,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值
- 本文实例为大家分享了Java实现寻找迷宫出路的具体代码,供大家参考,具体内容如下项目名称寻找迷宫出路项目描述给定一个自定义迷宫,0表示能通过
- 简介在实现登录功能时,一般为了安全都会设置验证码登录,为了防止某个用户用特定的程序暴力破解方式进行不断的尝试登录。常见验证码分为图片验证码和
- Java语言的垃圾回收1.垃圾回收机制的基本概念问:1.什么是Java垃圾回收?答:在Java语言的生命周期中,Java运行环境提供了一个系
- Spring 使用Junit单元测试并配置数据源一、问题描述由于公司项目中的数据源是配置在Tomcat中的server.xml中的,所以在使
- SQL 映射XML 文件是所有sql语句放置的地方。需要定义一个workspace,一般定义为对应的接口类的路径。写好SQL语句映射文件后,
- Java类中字段可以不赋予初始值的原因Java虚拟机会对类的实例对象进行分配内存,在分配内存后,会将内存空间(除了对象头)全部初始化为零值。
- list stream: reduce的使用stream 中的 reduce 的主要作用就是stream中元素进行组合,组合的方式可以是加减
- 需求:传入多个 id 查询用户信息,用下边两个 sql 实现:SELECT * FROM USERS WHERE username LIKE
- Java裁剪压缩PNG图片,透明背景色变黑import java.awt.Graphics2D;import java.awt.Image;
- 微服务之间token传递问题假设现在有A服务,B服务,外部使用RESTApi请求调用A服务,在请求头上有token字段,A服务使用完后,B服
- Java 开发语言中实现HTTP请求的方法主要有两种:一种是JAVA的标准类HttpUrlConnection,比较原生的实现方法;另一种是
- C#编程语言非常优美,我个人还是非常赞同的。特别是在学习一段时间C#后发现确实在它的语法和美观度来说确实要比其它编程语言强一些(也可能是由于
- 委托:顾名思义,让别人帮你办件事。委托是C#实现回调函数的一种机制。可能有人会问了,回调函数是个啥???举个例子:我现在是一家公司的老板,公