StringRedisTemplate

上一小节我们提到了RedisTemplate<Stinrg,Object>使用SpringDataRedis 默认的 JDK 序列化方式时,Redis 的key/value 可读性比较差。

因此课程里通常会自定义 RedisTemplate

目的就是:

plaintext 复制代码
默认 JDK 序列化
        ↓
数据不直观、不方便阅读

改成

Key   → String 序列化
Value → JSON 序列化
        ↓
Redis 中的数据更容易阅读

但这里又产生了新的问题:

假设保存:

java 复制代码
User user = new User("张三", 20);

redisTemplate.opsForValue().set("user:1", user);

为了以后能够把 JSON 反序列化回 User 对象,某些 JSON 序列化方案会把 Java 类型信息一起保存进去。

Redis 中可能类似:

js 复制代码
{
  "@class": "com.example.pojo.User",
  "name": "张三",
  "age": 20
}

问题就在这里:

text 复制代码
真正业务数据
name
age

+

额外类型信息
com.example.pojo.User

也就是说:

为了自动反序列化对象,需要保存额外的 Java 类型信息,增加了 Redis 的存储开销,而且 Redis 数据和 Java 类结构耦合得更紧。

为了解决这个问题我们提供了另一种思路:StringRedisTemplate

它不帮你处理复杂 Java 对象,而是明确规定:

text 复制代码
Key   → String
Value → String

因此:

java 复制代码
@Autowired
private StringRedisTemplate stringRedisTemplate;

存普通字符串:

java 复制代码
stringRedisTemplate.opsForValue()
        .set("name", "Jack");

如果要存 User

java 复制代码
User user = new User("张三", 20);

先由我们自己:

text 复制代码
User 对象
   ↓
ObjectMapper
   ↓
JSON 字符串
   ↓
StringRedisTemplate
   ↓
Redis

Redis 里只需要

js 复制代码
{
  "name": "张三",
  "age": 20
}

读取的时候反过来:

text 复制代码
Redis
 ↓
JSON String
 ↓
ObjectMapper
 ↓
User

也就是:

先通过ObjectMapper将 user 对象转成 JSON 格式的字符串

java 复制代码
String json = objectMapper.writeValueAsString(user);

然后调用 Spring 给我们的提供的 API将 String 类型的 key/value 写入 redis:

java 复制代码
redisTemplate.opsForvalue().set("user",json);

读取的时候同样需要调用ObjectMapper 手动将读取到的JSON 字符串通过字节码对象转成 User 对象:

java 复制代码
String json = stringRedisTemplate.opsForValue()
        .get("user");

User user = objectMapper.readValue(json, User.class);

虽然看起来多写了一步:

java 复制代码
对象 → JSON
JSON → 对象

但是好处是Redis 只负责存字符串,Java 程序自己决定这个字符串应该转换成什么对象

总结:

为了节省内存空间,我们并不会使用 JSON 序列化器来处理 value,而是统一使用 String 序列化器,要求只能存储 String 类型的 key 和 value,这两者的区别在于:JSON 序列化器会手动帮我们把Java 对象序列化成 String 数据,但为了实现自动反序列化需要保存额外的 Java 类型信息,导致Redis 的存储开销变大并且增加了Java 类与 Redis 数据的耦合度,而后者则在需要存储 Java 对象时,通过ObjectMapperwriteValueAsString(user)readValue(json,User.class)手动完成对象的序列化和反序列化。

补充:

  1. ObjectMapper 是一个 JSON 工具

    需要我们手动的创建对象:

    private static final ObjectMapper mapper = new ObjectMapper();

  2. Spring 默认提供了一个 StringRedisTemplate 类,它的 key 和 value 默认就是 String 方式,省去了我们自定义 RedisTemplate 的过程.

  3. User.class得到的是 User 类对应的 Class 对象,可以暂时把它理解为"字节码对象",但更严谨的叫法是:

User.classUser 类在 JVM 中对应的 Class<User> 对象。

text 复制代码
User.java
   ↓ 编译
User.class 字节码文件
   ↓ JVM 加载
JVM 中的 User 类
   ↓
对应一个 Class<User> 对象
   ↑
User.class 可以拿到它

相当于拿到这个对象的信息:

text 复制代码
json        → 数据是什么
User.class  → 告诉 Jackson 要转换成什么类型

                  ↓

              User 对象
相关推荐
Gopher_HBo1 小时前
beego 配置模块(core/config)
后端
小园子的小菜1 小时前
LangChain核心进阶解析:输出解析、聊天记忆与回调机制实战
后端
freewcx1 小时前
SpringDataRedis的序列化方式
后端
YHL1 小时前
🚀 NestJS 后端开发实战:从设计模式到 CRUD 全栈
后端
晚安日记wanna1 小时前
接口幂等性怎么保证
后端·面试
风中的小熊生气1 小时前
Spring Boot 面试知识(一):从启动流程到 AOP 与事务失效
spring boot·后端·面试
神秘的猪头1 小时前
Gin 项目为什么要分 Handler、Service、Repository?顺便讲透接口、依赖注入与指针
后端·go
程序员cxuan1 小时前
DeepSeek V4.1 Flash 正式发布!
人工智能·后端·程序员
特立独行的猫A1 小时前
AtomMQTT Broker — 用 Rust 实现的轻量级高性能 MQTT 消息代理
前端·后端·架构