怎么做出有品牌感的网站分析不同网站的优缺点
news/
2025/9/24 4:43:09/
文章来源:
怎么做出有品牌感的网站,分析不同网站的优缺点,苏宁易购网站建设的不足之处,大型电子商务系统网站建设文章目录 前言一、为什么推荐使用java.time包的LocalDateTime而不是java.util的Date#xff1f;二、使用LocalDateTime和LocalDate时遇到了哪些坑#xff1f;2.1 Redis序列化报错2.1.1 问题现象2.1.2 问题分析2.1.3 解决方案 2.2 LocalDateTime和LocalDate类型的属性返回给前… 文章目录 前言一、为什么推荐使用java.time包的LocalDateTime而不是java.util的Date二、使用LocalDateTime和LocalDate时遇到了哪些坑2.1 Redis序列化报错2.1.1 问题现象2.1.2 问题分析2.1.3 解决方案 2.2 LocalDateTime和LocalDate类型的属性返回给前端的值格式不正确2.2.1 问题现象2.2.2 解决方案 三、总结 前言
近日心血来潮想做一个开源项目目标是做一款可以适配多端、功能完备的模板工程包含后台管理系统和前台系统开发者基于此项目进行裁剪和扩展来完成自己的功能开发。
本项目基于Java21和SpringBoot3开发序列化工具使用的是默认的Jackson使用Spring Data Redis操作Redis缓存。
在定义实体类过程中日期时间类型的属性我使用了java.time包下的LocalDate和LocalDateTime类而没有使用java.util包下的Date类。
但在使用过程中遇到了一些问题于是在此记录下来与诸位分享。
一、为什么推荐使用java.time包的LocalDateTime而不是java.util的Date
LocalDateTime和Date是Java中表示日期和时间的两种不同的类它们有一些区别和特点。
类型LocalDateTime是Java 8引入的新类型属于Java 8日期时间APIjava.time包。而Date是旧版Java日期时间APIjava.util包中的类。不可变性LocalDateTime是不可变的类型一旦创建后其值是不可变的对该类对象的加减等计算操作不会修改原对象而是会返回一个新的LocalDateTime对象。而Date是可变的类型可以通过方法修改其值。线程安全性LocalDateTime是线程安全的多个线程可以同时访问和操作不同的LocalDateTime实例。而Date是非线程安全的如果多个线程同时访问和修改同一个Date实例可能会导致不可预期的结果。时间精度LocalDateTime提供了纳秒级别的时间精度可以表示更加精确的时间。而Date只能表示毫秒级别的时间精度。时区处理LocalDateTime默认不包含时区信息表示的是本地日期和时间。而Date则包含时区信息它的实际值会受到系统默认时区的影响。
由于LocalDateTime是Java 8及以上版本的新类型并提供了更多的功能和灵活性推荐在新的项目中使用LocalDateTime来处理日期和时间。
对于旧版Java项目仍然需要使用Date类但在多线程环境下需要注意其线程安全性。
如果需要在LocalDateTime和Date之间进行转换可以使用相应的方法进行转换例如通过LocalDateTime的atZone()方法和Date的toInstant()方法进行转换。
二、使用LocalDateTime和LocalDate时遇到了哪些坑
2.1 Redis序列化报错
2.1.1 问题现象
在使用RedisTemplate向Redis中插入数据时遇到了如下报错
2024-01-11T21:33:25.23308:00 ERROR 13212 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exceptionorg.springframework.data.redis.serializer.SerializationException: Could not write JSON: 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: java.util.ArrayList[0]-com.fast.alden.data.model.SysApiResource[createdTime])at org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer.serialize(Jackson2JsonRedisSerializer.java:157) ~[spring-data-redis-3.2.0.jar:3.2.0]at org.springframework.data.redis.core.AbstractOperations.rawValue(AbstractOperations.java:128) ~[spring-data-redis-3.2.0.jar:3.2.0]at org.springframework.data.redis.core.DefaultValueOperations.set(DefaultValueOperations.java:236) ~[spring-data-redis-3.2.0.jar:3.2.0]2.1.2 问题分析
在使用Redis缓存含有LocalDateTime类型变量的实体类时会产生序列化问题因为Jackson库在默认情况下不支持Java8的LocalDateTime类型的序列化和反序列化。
错误堆栈中也给出了解决方案添加 com.fasterxml.jackson.datatype:jackson-datatype-jsr310依赖但光添加依赖是不够的还我们需要自定义序列化和反序列化的行为。
2.1.3 解决方案
添加maven依赖
dependencygroupIdcom.fasterxml.jackson.datatype/groupIdartifactIdjackson-datatype-jsr310/artifactIdversion2.13.0/version
/dependency修改RedisSerializer Bean配置
在定义RedisSerializer Bean的代码中自定义ObjectMapper对象处理时间属性时的序列化和反序列化行为LocalDate、LocalDateTime、LocalTime的序列化和反序列化都要自定义还要禁用将日期序列化为时间戳。
Configuration
public class RedisConfig {Beanpublic RedisSerializerObject redisSerializer() {ObjectMapper objectMapper new ObjectMapper();objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);// 必须设置否则无法将JSON转化为对象会转化成Map类型objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);// 自定义ObjectMapper的时间处理模块JavaTimeModule javaTimeModule new JavaTimeModule();javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss)));javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss)));javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(yyyy-MM-dd)));javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(yyyy-MM-dd)));javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(HH:mm:ss)));javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(HH:mm:ss)));objectMapper.registerModule(javaTimeModule);// 禁用将日期序列化为时间戳的行为objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);//创建JSON序列化器return new Jackson2JsonRedisSerializer(objectMapper, Object.class);}
}2.2 LocalDateTime和LocalDate类型的属性返回给前端的值格式不正确
2.2.1 问题现象
在application.yml中设置了全局的日期类型的序列化和反序列化格式在对应字段上也并没有使用JsonFormat进行特殊设置但是LocalDateTime类型的属性返回给前端时并没有生效返回的仍是LocalDateTime默认的ISO标准时间格式的字符串。
spring:jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT8default-property-inclusion: alwaysmvc:format:date-time: yyyy-MM-dd HH:mm:ssdate: dd/MM/yyyy2.2.2 解决方案
自定义Jackson配置代码如下
Configuration
public class JacksonConfig {Beanpublic Jackson2ObjectMapperBuilderCustomizer customizer() {return builder -builder.simpleDateFormat(yyyy-MM-dd HH:mm:ss)// long类型转string 前端处理Long类型数值过大会丢失精度.serializerByType(Long.class, ToStringSerializer.instance).serializerByType(Long.TYPE, ToStringSerializer.instance).serializationInclusion(JsonInclude.Include.NON_NULL)//指定反序列化类型也可以使用JsonFormat(pattern yyyy-MM-dd)替代。主要是mvc接收日期时使用.deserializerByType(LocalTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(HH:mm:ss))).deserializerByType(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(yyyy-MM-dd))).deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss)))// 日期序列化主要返回数据时使用.serializerByType(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(HH:mm:ss))).serializerByType(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(yyyy-MM-dd))).serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss)));}
}三、总结
在使用java.time API的过程中除了会遇到前文所说的序列化问题之外可能还会遇到以下问题
时区问题LocalDateTime不包含时区信息这可能导致在不同时区的用户之间出现不一致性。为了避免这个问题您应该考虑使用ZonedDateTime或OffsetDateTime并确保在处理日期和时间时考虑时区。数据库交互当与数据库交互时要确保数据库列的数据类型与正在使用的Java日期类型相匹配。例如如果使用的是PostgreSQL则可能需要使用timestamp without time zone列类型来存储日期和时间。默认值和验证在某些情况下可能希望为日期或时间字段设置默认值或进行验证。使用Spring的验证注解如NotNull或Size可以帮助我们确保输入的有效性。跨时区处理由于LocalDateTime不包含时区信息当与全球用户互动时需要特别注意时区转换。考虑使用像Joda-Time这样的库来帮助我们处理复杂的时区转换。处理过去和未来的日期在处理历史事件或计划未来的活动时请确保我们的应用程序能够正确地处理这些日期。考虑使用像Period或Duration这样的类来计算日期之间的差异。
我也会及时的更新后续实践中所遇到的问题希望与诸位看官一起进步。
如有错误还望批评指正。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/914869.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!