stringredistemplate不能直接存对象,因其默认使用stringredisserializer,仅支持string类型key和value;存对象需手动序列化为json等字符串,推荐用复用的objectmapper处理。

StringRedisTemplate 为什么不能直接存对象
因为 StringRedisTemplate 的序列化器默认是 StringRedisSerializer,只认 String 类型的 key 和 value。你要是传个 User 对象进去,它会调用 toString(),结果存进去的是类似 com.example.User@1a2b3c 这种没用的字符串,取出来也没法还原。
- 存对象必须自己处理序列化,
StringRedisTemplate不帮你干这事 - 它和
RedisTemplate的根本区别就在这儿:RedisTemplate默认用JdkSerializationRedisSerializer(能存对象但可读性差、有兼容风险),而StringRedisTemplate强制走字符串路线 - 如果你只是存 JSON、ID、计数器、开关标记这类纯文本数据,
StringRedisTemplate反而是更安全、更轻量的选择
存 JSON 字符串是最常用也最稳的做法
把对象转成 JSON 字符串再交给 StringRedisTemplate,取的时候再反序列化——这是规避泛型转换问题最直接、最可控的方式。
- 推荐用
ObjectMapper(Jackson)而不是fastjson,后者在新 JDK 上有反射限制和安全风险 - 注意
ObjectMapper实例要复用,别每次 new 一个,否则性能掉得明显 - 存之前检查对象是否为
null,避免序列化出"null"字符串,后续判断容易混淆 - 示例:
String json = objectMapper.writeValueAsString(user);<br>stringRedisTemplate.opsForValue().set("user:1001", json);<br>User user = objectMapper.readValue(stringRedisTemplate.opsForValue().get("user:1001"), User.class);
key 和 value 都得是 String,别在 key 里塞对象
有人图省事把 user.getId() + "_" + user.getTenantId() 拼成 key,看着没问题,但一旦中间出现特殊字符(比如 :、/、空格),或者 tenantId 是中文,StringRedisTemplate 虽然不报错,但后续用 SCAN 或 Redis CLI 查看时会乱码或匹配失败。
- key 建议只含字母、数字、下划线、冒号(
:)——这是 Redis 社区通用约定,不是强制规则但非常实用 - value 如果是 JSON,确保
ObjectMapper设置了WRITE_DATES_AS_TIMESTAMPS(false),否则时间字段变成数字,可读性差还容易和前端时间格式对不上 - 别依赖
StringRedisTemplate的boundValueOps(key).get()返回值自动转类型——它返回的就是String,强转User会直接ClassCastException
想省代码?封装一个工具类比换模板更靠谱
有人一遇到“要反复序列化”就想换成 RedisTemplate<object object></object>,结果引入了 JDK 序列化,升级 Spring Boot 后发现老数据反序列化失败,或者跨语言服务根本读不了。其实只要把 JSON 序列化逻辑包一层,用起来一样干净。
- 工具类里统一处理
Null、异常、日志,比到处写writeValueAsString更可靠 - 不要在工具类里缓存
ObjectMapper实例到静态字段然后不加锁——多线程并发时可能出状态污染 - 如果项目已用 Lombok,记得给实体类加
@Data和@NoArgsConstructor,否则 Jackson 反序列化会失败 - 示例方法签名:
public <T> T get(String key, Class<T> targetType) { ... }内部调用objectMapper.readValue(..., targetType)
"true" 就够了,非得套一层 JSON,既浪费空间又增加解析开销。StringRedisTemplate 的边界感,得靠使用场景来守。










