优秀是一种习惯!!!

分布式时间问题集合

2023-11-29

分布式时间问题集合

一、

@SpringBootApplication
public class SwappingApplication {
public static void main(String[] args) {
   SpringApplication.run(SwappingApplication.class, args);
 }
@PostConstruct
void started() {
   TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
 }
}

这段代码是一个基于 Spring Boot 框架的应用程序入口类。让我来解释一下:

  1. @SpringBootApplication:这是一个注解,标记了该类是一个 Spring Boot 应用程序的入口类。它将自动进行一些配置,包括自动扫描和加载其他组件、配置以及设置默认属性。
  2. public static void main(String[] args):这是一个 Java 程序的入口方法。在该方法中,通过调用 SpringApplication.run() 来启动 Spring Boot 应用程序。SwappingApplication.class 是应用程序的主类,args 是传递给应用程序的命令行参数。
  3. @PostConstruct:这是一个注解,表示带有该注解的方法会在应用程序启动时执行。在这个例子中,started() 方法用于设置默认的时区为 GMT+8。
  4. TimeZone.setDefault(TimeZone.getTimeZone("GMT+8")):这是 java.util.TimeZone 类的方法调用,用于设置默认时区为 GMT+8。在应用程序启动时,started() 方法会被调用,从而设置默认的时区。

总之,上述代码创建了一个 Spring Boot 应用程序入口类,并在应用程序启动时将默认时区设置为 GMT+8。通过 main() 方法启动应用程序后,Spring Boot 将根据配置和自动扫描加载其他组件,并开始运行应用程序。

二、

生成自定义token方法:public String generateCustomJwtToken() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Date now = new Date();
Date expiryDate = new Date(now.getTime() + jwtExpiration * 1000L);
SecretKey secretKey = Keys.hmacShaKeyFor(jwtSecret.getBytes(StandardCharsets.UTF_8));
Map<String, Object> permissions = Maps.newHashMap();
Map<String, Object> user = Maps.newHashMap();
permissions.put("permissions", authentication.getCredentials());
user.put("user", authentication.getPrincipal());
return "Bearer " + Jwts.builder()
.addClaims(permissions)
.addClaims(user)
.setSubject(authentication.getName())
.setIssuedAt(now)
.setExpiration(expiryDate)
.signWith(secretKey)
.compact();
},报错:Unable to serialize claims object to json: Unable to serialize object: Java 8 date/time type java.time.LocalDateTime not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: io.jsonwebtoken.impl.DefaultClaims["user"]->com.xirui.qrcode.modules.web.domain.User["create_date"])

错误信息表明你正在尝试将一个 java.time.LocalDateTime 对象序列化为 JSON,但 Jackson(用于处理 JSON 的库)默认不支持 java.time.LocalDateTime。解决方法是添加 jackson-datatype-jsr310 模块,它为 Java 8 的日期/时间类型提供了支持。

如果你的项目是 Maven 项目,你可以在 pom.xml 文件中添加以下依赖:

<dependency>
   <groupId>com.fasterxml.jackson.datatype</groupId>
   <artifactId>jackson-datatype-jsr310</artifactId>
   <version>2.12.5</version> <!-- 请使用最新版本 -->
</dependency>

如果你的项目是 Gradle 项目,你可以在 build.gradle 文件中添加以下依赖:

implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.12.5' // 请使用最新版本

然后,你需要在你的配置中注册这个模块。如果你使用的是 Spring Boot,它会自动为你注册这个模块。如果不是,你需要手动注册,如下所示:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());

这样,你就应该可以正常序列化 java.time.LocalDateTime 对象了。

根据上述回答,ObjectMapper mapper = new ObjectMapper();mapper.registerModule(new JavaTimeModule());手动注册写在哪儿?

在你的应用程序中,你需要创建一个配置类(通常在 Spring Boot 中,我们把它放在 @Configuration 注解的类中),然后在这个类中创建一个 ObjectMapper 的 Bean,并注册 JavaTimeModule 模块。以下是一个例子:

@Configuration
public class JacksonConfig {

   @Bean
   public ObjectMapper objectMapper() {
       ObjectMapper mapper = new ObjectMapper();
       mapper.registerModule(new JavaTimeModule());
       return mapper;
   }
}

这个 objectMapper() 方法会创建一个 ObjectMapper 的 Bean,并注册 JavaTimeModule 模块。然后,Spring 会自动将这个 ObjectMapper Bean 注入到需要它的地方。

然而,如果你的项目是一个 Spring Boot 项目,那么你通常不需要手动创建这个 Bean。Spring Boot 会自动配置一个 ObjectMapper Bean,并自动注册 JavaTimeModule 模块,只要你在项目的类路径中包含了 jackson-datatype-jsr310 依赖。

如果你已经添加了 jackson-datatype-jsr310 依赖,但仍然遇到序列化 java.time.LocalDateTime 的问题,那么可能是其他地方的配置覆盖了 Spring Boot 的自动配置。在这种情况下,你可以尝试手动创建 ObjectMapper Bean,并注册 JavaTimeModule 模块,如上述代码所示。

根据上述回答报错:Unable to serialize claims object to json: Unable to serialize object: Java 8 date/time type java.time.LocalDateTime not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: io.jsonwebtoken.impl.DefaultClaims["user"]->com.xirui.qrcode.modules.web.domain.User["create_date"])

你的错误提示表明,你正在尝试将一个 java.time.LocalDateTime 类型的对象序列化为 JSON,但是 Jackson 库默认并不支持 java.time.LocalDateTime 类型。要解决这个问题,你需要添加 jackson-datatype-jsr310 这个模块,它支持 Java 8 的日期/时间类型。

如果你的项目是一个 Maven 项目,你可以在你的 pom.xml 文件中添加以下依赖:

<dependency>
   <groupId>com.fasterxml.jackson.datatype</groupId>
   <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

如果你的项目是一个 Gradle 项目,你可以在你的 build.gradle 文件中添加以下依赖:

implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'

一旦你添加了这个依赖,Spring Boot 会自动配置 Jackson 来支持 java.time.LocalDateTime。如果你的项目不是 Spring Boot 项目,你可能需要手动配置 Jackson,方法如下:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

上述代码首先创建了一个 ObjectMapper 对象,然后注册了 JavaTimeModule,最后禁用了将日期作为时间戳写入的特性,这样日期就会被格式化为 ISO 格式的字符串,而不是时间戳。

然后,你需要确保你的应用程序在序列化和反序列化 JSON 时都使用了这个配置过的 ObjectMapper 对象。如果你使用的是 Spring MVC,你可以通过配置一个 MappingJackson2HttpMessageConverter Bean 来实现这一点。

根据上述回答报错:java.lang.IllegalArgumentException: Unable to serialize claims object to json: Unable to serialize object: Java 8 date/time type java.time.LocalDateTime not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: io.jsonwebtoken.impl.DefaultClaims["user"]->com.xirui.qrcode.modules.web.domain.User["create_date"])

你正在遇到的问题是由于在尝试将包含java.time.LocalDateTime类型的对象序列化为JSON时,Jackson库默认不支持此类型。尽管你已经添加了jackson-datatype-jsr310依赖,但问题仍然存在,这可能是因为你在创建JWT时,JJWT库使用的是其内部的JSON处理机制,而不是Spring Boot自动配置的Jackson库。

解决此问题的一种方法是尽量避免在JWT的claims中直接添加包含java.time.LocalDateTime类型的对象。你可以在添加到JWT之前,将这些对象转换为String或者Timestamp。例如,如果你的User对象中有一个java.time.LocalDateTime类型的create_date字段,你可以在添加User到JWT之前,先将create_date转换为String:

User user = (User) authentication.getPrincipal();
user.setCreateDate(user.getCreateDate().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));

然后再添加到JWT:

user.put("user", user);

这样,JWT中的用户信息就不再包含java.time.LocalDateTime类型,就不会出现序列化问题了。

另一种可能的解决方案是自定义JJWT的JSON处理机制,使其使用Jackson库,并配置JavaTimeModule。但这可能需要更复杂的代码,且可能需要修改JJWT库的源代码。


标题:分布式时间问题集合
作者:amethystfob
地址:https://newmoon.top/articles/2023/11/28/1701163165320.html

欢迎各路大侠指点留痕: