架构设计 - WEB项目的基础序列化配置

摘要:web项目中做好基础架构(redis,json)的序列化配置有重要意义

  • 支持复杂数据结构:Redis 支持多种不同的数据结构,如字符串、哈希表、列表、集合和有序集合。在将这些数据结构存储到 Redis 中时,需要将其序列化为字节流。通过 JSON 序列化,我们可以将复杂的数据结构(如对象、数组等)转换为字符串格式的 JSON 数据,便于在 Redis 中存储和读取。
  • 减少网络传输量:在分布式系统中,Redis 通常用作缓存层。当应用程序需要从 Redis 中读取数据时,需要通过网络传输数据。直接使用原始数据结构进行网络传输可能会消耗大量的带宽。通过 JSON 序列化,可以将数据转换为紧凑的字符串格式,从而减少网络传输量,提高传输效率。
  • 跨平台兼容性:JSON 是一种通用的数据交换格式,具有广泛的跨平台兼容性。无论使用哪种编程语言或平台,只要支持 JSON 格式,就可以方便地进行数据交换和存储。这使得 Redis 中的数据可以轻松地与不同的应用程序或系统进行集成。
  • 数据可读性:将数据序列化为 JSON 格式后,可以方便地查看和调试数据。JSON 格式具有清晰的结构和可读性强的特点,使得开发人员可以轻松地理解数据的含义和结构。
  • 对象持久化存储:通过将对象序列化为 JSON 格式的字符串后,可以将其存储到 Redis 中实现持久化存储。这样,在应用程序重启或重新加载时,可以轻松地恢复对象的状态。

Redis 序列化配置举例

Redis数据格式序列化配置类

java 复制代码
/**
 * @title Redis 基础配置类
 * @desc 使用自己定义的 RedisTemplate Bean
 */
@AutoConfiguration(before = RedissonAutoConfiguration.class)
public class SingRedisAutoConfiguration {

    /**
     * 创建 RedisTemplate Bean,使用 JSON 序列化方式
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        // 创建 RedisTemplate 对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置 RedisConnection 工厂 实现多种 Java Redis 客户端接入
        template.setConnectionFactory(factory);
        // 使用 String 格式 KEY
        template.setKeySerializer(RedisSerializer.string());
        // 使用 String 格式 序列化 哈希键
        template.setHashKeySerializer(RedisSerializer.string());
        // 使用 JSON 序列化方式(Jackson库)序列化 VALUE 。
        template.setValueSerializer(buildRedisSerializer());
        // 设置哈希值序列化器
        template.setHashValueSerializer(buildRedisSerializer());
        return template;
    }

    public static RedisSerializer<?> buildRedisSerializer() {
        RedisSerializer<Object> json = RedisSerializer.json();
        // 序列化LocalDateTime 类型的日期字段
        ObjectMapper objectMapper = (ObjectMapper) ReflectUtil.getFieldValue(json, "mapper");
        objectMapper.registerModules(new JavaTimeModule());
        return json;
    }

}

2. 全局 json 序列化配置类

java 复制代码
@AutoConfiguration
@Slf4j
public class YudaoJacksonAutoConfiguration {

    @Bean
    @SuppressWarnings("InstantiationUtilClass")
    public JsonUtils jsonUtils(List<ObjectMapper> objectMappers) {
        // 创建 SimpleModule 对象
        SimpleModule simpleModule = new SimpleModule();
        simpleModule
                // Long 自动序列化为字符串类型, 防止数值超过 2^53-1 在 JS 会出现精度丢失问题
                .addSerializer(Long.class, NumberSerializer.INSTANCE)
                .addSerializer(Long.TYPE, NumberSerializer.INSTANCE)
                .addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE)
                .addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE)
                .addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE)
                .addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE)
                // LocalDateTime 序列化、反序列化规则,使用 Long 时间戳
                .addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE)
                .addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
        // 注册到 objectMapper
        objectMappers.forEach(objectMapper -> objectMapper.registerModule(simpleModule));

        // 设置 objectMapper 到 JsonUtils
        JsonUtils.init(CollUtil.getFirst(objectMappers));
        
        return new JsonUtils();
    }

}

基于时间戳的 LocalDateTime 序列化器

java 复制代码
/**
 * 基于时间戳的 LocalDateTime 序列化器
 *
 */
public class SingLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {

    public static final SingLocalDateTimeSerializer INSTANCE = new SingLocalDateTimeSerializer();

    @Override
    public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        // 将 LocalDateTime 对象 序列化为 Long 时间戳
        gen.writeNumber(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
    }

}

基于时间戳的 LocalDateTime 反序列化器

java 复制代码
/**
 * 基于时间戳的 LocalDateTime 反序列化器
 *
 */
public class SingLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {

    public static final SingLocalDateTimeDeserializer INSTANCE = new SingLocalDateTimeDeserializer();

    @Override
    public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        // 将 Long 时间戳 序列化为 LocalDateTime 对象
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(p.getValueAsLong()), ZoneId.systemDefault());
    }

}
相关推荐
最贪吃的虎10 小时前
Spring Boot 自动装配(Auto-Configuration)深度实现原理全解析
java·运维·spring boot·后端·mysql
Ahuuua10 小时前
Spring Bean作用域深度解析
java·后端·spring
大学生资源网10 小时前
基于Vue的网上购物管理系统的设计与实现(java+vue+源码+文档)
java·前端·vue.js·spring boot·后端·源码
qq_124987075310 小时前
基于微信小程序的私房菜定制上门服务系统(源码+论文+部署+安装)
java·spring boot·微信小程序·小程序·毕业设计·毕设
a努力。10 小时前
京东Java面试被问:Fork/Join框架的使用场景
java·开发语言·面试
有一个好名字11 小时前
Spring AI 工具调用(Tool Calling):解锁智能应用新能力
java·人工智能·spring
蓝影铁哥11 小时前
浅谈国产数据库OceanBase
java·linux·数据库·oceanbase
五阿哥永琪11 小时前
SpringAOP的底层实现原理
java·spring
JosieBook11 小时前
【大模型】用 AI Ping 免费体验 GLM-4.7 与 MiniMax M2.1:从配置到实战的完整教程
数据库·人工智能·redis
彭于晏Yan11 小时前
excel导入导出
spring boot·excel