当前位置: 首页 > backend >正文

Redis序列化配置类

Redis序列化配置类,用于定制Redis数据的存储和读取方式

package com.example.usermanagement.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;/*** Redis配置类* 配置Redis序列化方式,使存储的数据更易读*/
@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);// 方案1:使用GenericJackson2JsonRedisSerializer(推荐)GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer =new GenericJackson2JsonRedisSerializer();// String序列化StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();// key使用String序列化template.setKeySerializer(stringRedisSerializer);// hash的key也使用String序列化template.setHashKeySerializer(stringRedisSerializer);// value使用Jackson序列化template.setValueSerializer(genericJackson2JsonRedisSerializer);// hash的value使用Jackson序列化template.setHashValueSerializer(genericJackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}}

默认序列化的问题

Spring Boot默认使用JDK序列化,会产生以下问题:

// 默认JDK序列化存储的数据(不可读)
Key: "\xac\xed\x00\x05t\x00\x04user"
Value: "\xac\xed\x00\x05sr\x00\x1ccom.example.User..."// 自定义配置后的存储(可读)
Key: "user:1"
Value: {"id":1,"username":"admin","email":"admin@example.com"}

对比效果:

  • JDK序列化:二进制格式,不可读,占用空间大
  • JSON序列化:文本格式,可读性强,便于调试

2.1 RedisTemplate配置

@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory)

作用:

  • 创建自定义的RedisTemplateBean
  • <String, Object>:Key为String类型,Value可以是任意对象
  • factory:Spring自动注入的Redis连接工厂

2.2 设置连接工厂

template.setConnectionFactory(factory);
  • 建立RedisTemplate与Redis服务器的连接
  • factory来自Spring Boot的自动配置

3. 序列化器详解

3.1 GenericJackson2JsonRedisSerializer

GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();

特点:

  • 使用Jackson库进行JSON序列化
  • 包含类型信息:存储时会保存对象的类名
  • 反序列化时能正确还原为原始对象类型
  • 支持复杂对象和集合

存储示例:

{"@class": "com.example.usermanagement.entity.User","id": 1,"username": "admin","email": "admin@example.com","status": 1
}

3.2 StringRedisSerializer

StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

特点:

  • 将字符串按UTF-8编码序列化
  • 用于Key的序列化,保证Key的可读性
  • 性能高,占用空间小

4. 四种序列化配置

4.1 Key序列化

template.setKeySerializer(stringRedisSerializer);
  • 用途:普通的Redis Key
  • 效果"user:1" 而不是二进制数据

4.2 Hash Key序列化

template.setHashKeySerializer(stringRedisSerializer);
  • 用途:Hash数据结构中的field名
  • 示例
// 使用Hash存储用户信息
redisTemplate.opsForHash().put("user:1", "username", "admin");
redisTemplate.opsForHash().put("user:1", "email", "admin@example.com");

4.3 Value序列化

template.setValueSerializer(genericJackson2JsonRedisSerializer);
  • 用途:普通的Redis Value
  • 效果:对象被序列化为JSON格式

4.4 Hash Value序列化

template.setHashValueSerializer(genericJackson2JsonRedisSerializer);
  • 用途:Hash数据结构中的值
  • 效果:Hash中的每个值都按JSON格式存储

5. afterPropertiesSet()方法

template.afterPropertiesSet();
  • 作用:确保所有配置生效
  • 时机:在所有属性设置完成后调用
  • 必需性:必须调用,否则配置可能不生效

6. 实际应用效果对比

6.1 存储User对象

Java代码:

@Autowired
private RedisTemplate<String, Object> redisTemplate;public void saveUser(User user) {redisTemplate.opsForValue().set("user:" + user.getId(), user);
}

Redis中的存储效果:

Key: user:1
Value:

{"@class": "com.example.usermanagement.entity.User","id": 1,"username": "admin","password": "123456","email": "admin@example.com","phone": "13800138001","status": 1,"score": 95,"createTime": ["java.util.Date", 1691823600000],"updateTime": ["java.util.Date", 1691823600000]
}

6.2 存储列表数据

public void saveUserList(List<User> users) {redisTemplate.opsForValue().set("users:all", users);
}

存储效果:

{"@class": "java.util.ArrayList","content": [{"@class": "com.example.usermanagement.entity.User","id": 1,"username": "admin"},{"@class": "com.example.usermanagement.entity.User", "id": 2,"username": "user001"}]
}

7. 高级配置选项

7.1 自定义ObjectMapper

@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);// 自定义ObjectMapperObjectMapper objectMapper = new ObjectMapper();objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer(objectMapper);// 设置序列化器StringRedisSerializer stringSerializer = new StringRedisSerializer();template.setKeySerializer(stringSerializer);template.setHashKeySerializer(stringSerializer);template.setValueSerializer(serializer);template.setHashValueSerializer(serializer);template.afterPropertiesSet();return template;
}

7.2 各个配置项说明

setVisibility:

objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  • 设置Jackson的字段可见性
  • PropertyAccessor.ALL:包括字段、getter、setter等
  • JsonAutoDetect.Visibility.ANY:任何访问级别都可见

activateDefaultTyping:

objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL
);
  • 启用类型信息存储
  • LaissezFaireSubTypeValidator:宽松的类型验证器
  • NON_FINAL:对非final类启用类型信息

9.1 Service层使用

@Service
public class UserServiceImpl implements UserService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;private static final String USER_KEY_PREFIX = "user:";public User getUserById(Long id) {String key = USER_KEY_PREFIX + id;// 从Redis获取(自动反序列化为User对象)User user = (User) redisTemplate.opsForValue().get(key);if (user != null) {return user;}// 从数据库查询user = userMapper.selectById(id);if (user != null) {// 存入Redis(自动序列化)redisTemplate.opsForValue().set(key, user, 2, TimeUnit.HOURS);}return user;}public void deleteUserCache(Long id) {String key = USER_KEY_PREFIX + id;redisTemplate.delete(key);}
}

9.2 Hash操作示例

public void saveUserToHash(User user) {String key = "user:hash:" + user.getId();// 将User对象的各个字段存储到Hash中redisTemplate.opsForHash().put(key, "username", user.getUsername());redisTemplate.opsForHash().put(key, "email", user.getEmail());redisTemplate.opsForHash().put(key, "user", user); // 整个对象
}

10. 常见问题与解决

10.1 类型转换异常

问题: ClassCastException: LinkedHashMap cannot be cast to User

原因: 反序列化时丢失了类型信息

解决:

// 方法1:使用强类型转换
User user = objectMapper.convertValue(redisTemplate.opsForValue().get(key), User.class
);// 方法2:确保使用GenericJackson2JsonRedisSerializer

10.2 日期格式问题

问题: 日期序列化格式不正确

解决:

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

10.3 性能优化

// 连接池配置
@Bean
public LettuceConnectionFactory redisConnectionFactory() {GenericObjectPoolConfig<Object> poolConfig = new GenericObjectPoolConfig<>();poolConfig.setMaxTotal(20);poolConfig.setMaxIdle(10);poolConfig.setMinIdle(5);LettucePoolingClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder().poolConfig(poolConfig).build();return new LettuceConnectionFactory(new RedisStandaloneConfiguration("localhost", 6379), clientConfig);
}
http://www.xdnf.cn/news/17631.html

相关文章:

  • vue2+elementUI实现园型动态步骤条小组件,带缩放功能
  • 【4】Transformers快速入门:自然语言模型 vs 统计语言模型
  • 【无标题】centos 配置阿里云的yum源
  • vue文件或文件夹拖拽上传
  • WPS文字和Word:不只是表格,段落也可以排序
  • 校园快递小程序(腾讯地图API、二维码识别、Echarts图形化分析)
  • 【Dify学习笔记】:Dify搭建图片文件数据分析助手
  • Kimi K2 架构深度解析:万亿MoE模型的效率革命与智能体突破
  • Linux文件系统:从虚拟接口到物理实现的架构解析
  • 【C++】5. 内存管理
  • Android Studio注释如何不从行首开始
  • gpt-5与gpt-5-fast
  • CPPIO流
  • Postman接口测试:postman设置接口关联,实现参数化
  • 当多模态大语言模型遇上视觉难题!AI视觉探索之旅
  • 视频输入输出模块介绍和示例
  • 编译 BusyBox for ARM 平台
  • 力扣面试150题--爬楼梯 打家劫舍 零钱兑换 最长递增子序列
  • Elasticsearch JS 自定义 ConnectionPool / Connection / Serializer、敏感信息脱敏与 v8 平滑迁移
  • 01-Ansible 自动化介绍与使用
  • 83. 删除排序链表中的重复元素
  • Neo4j Cypher
  • Fiddler国内中文网使用经验分享,从抓包入门到API调试进阶
  • 【读代码】深度解析 Researcher:开源自动化科研助手
  • K8S 节点初始化一键脚本(禁用 SELinux + 关闭 swap + 开启 ipvs 亲测实用)
  • Golang 语言中 Context 的使用方式
  • 计算机视觉(6)-自动驾驶感知方案对比
  • AV、IPS、WAF对比
  • CMake笔记:PUBLIC/PRIVATE/INTERFACE的使用
  • 力扣经典算法篇-50-单词规律(双哈希结构+正反向求解)