概述

使用Spring 提供的 Spring Data Redis 操作redis 必然要使用Spring提供的模板类 RedisTemplate, 今天我们好好的看看这个模板类 。

RedisTemplate

看看4个序列化相关的属性 ,主要是 用于 KEY 和 VALUE 的序列化 。 举个例子,比如说我们经常会将POJO 对象存储到 Redis 中,一般情况下会使用 JSON 方式序列化成字符串,存储到 Redis 中 。

Spring提供的Redis数据结构的操作类

  • ValueOperations 类,提供 Redis String API 操作
  • ListOperations 类,提供 Redis List API 操作
  • SetOperations 类,提供 Redis Set API 操作
  • ZSetOperations 类,提供 Redis ZSet(Sorted Set) API 操作
  • GeoOperations 类,提供 Redis Geo API 操作
  • HyperLogLogOperations 类,提供 Redis HyperLogLog API 操作

StringRedisTemplate

再看个常用的 StringRedisTemplate

RedisTemplate<K, V> 支持泛型,StringRedisTemplate K V 均为String类型。

org.springframework.data.redis.core.StringRedisTemplate 继承 RedisTemplate 类,使用 org.springframework.data.redis.serializer.StringRedisSerializer 字符串序列化方式。

RedisSerializer 序列化 接口

RedisSerializer接口 是 Redis 序列化接口,用于 Redis KEY 和 VALUE 的序列化

RedisSerializer 接口的实现类 如下

归类一下

  • JDK 序列化方式 (默认)
  • String 序列化方式J
  • SON 序列化方式
  • XML 序列化方式

JDK 序列化方式 (默认)

org.springframework.data.redis.serializer.JdkSerializationRedisSerializer ,默认情况下,RedisTemplate 使用该数据列化方式。

我们来看下源码 RedisTemplate#afterPropertiesSet()

Spring Boot 自动化配置 RedisTemplate Bean 对象时,就未设置默认的序列化方式。

绝大多数情况下,不推荐使用 JdkSerializationRedisSerializer 进行序列化。主要是不方便人工排查数据。

我们来做个测试

运行单元测试

看不懂呀 ,老哥

KEY 前面带着奇怪的 16 进制字符 , VALUE 也是一串奇怪的 16 进制字符 。。。。。

为什么是这样一串奇怪的 16 进制? ObjectOutputStream#writeString(String str, boolean unshared) 实际就是标志位 + 字符串长度 + 字符串内容

KEY 被序列化成这样,线上通过 KEY 去查询对应的 VALUE非常不方便,所以 KEY 肯定是不能被这样序列化的。

VALUE 被序列化成这样,除了阅读可能困难一点,不支持跨语言外,实际上也没还OK。不过,实际线上场景,还是使用 JSON 序列化居多。

String 序列化方式

org.springframework.data.redis.serializer.StringRedisSerializer ,字符串和二进制数组的直接转换

绝大多数情况下,我们 KEY 和 VALUE 都会使用这种序列化方案。

JSON 序列化方式

org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer 使用 Jackson 实现 JSON 的序列化方式,并且从 Generic 单词可以看出,是支持所有类。

public GenericJackson2JsonRedisSerializer(@Nullable String classPropertyTypeName) {.......... if (StringUtils.hasText(classPropertyTypeName)) {mapper.enableDefaultTypingAsProperty(DefaultTyping.NON_FINAL, classPropertyTypeName);} else {mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);}}

classPropertyTypeName 不为空的话,使用传入对象的 classPropertyTypeName 属性对应的值,作为默认类型(Default Typing) ,否则使用传入对象的类全名,作为默认类型(Default Typing)。

我们来思考下,在将一个对象序列化成一个字符串,怎么保证字符串反序列化成对象的类型呢?Jackson 通过 Default Typing ,会在字符串多冗余一个类型,这样反序列化就知道具体的类型了

先说个结论

标准JSON

{"id": 100,"name": "小工匠","sex": "Male"
}

使用 Jackson Default Typing 机制序列化

{"@class": "com.artisan.domain.Artisan","id": 100,"name": "小工匠","sex": "Male"
}

示例

测试一把

【配置类】

 @Beanpublic RedisTemplate<String, Object> redisTemplate() {// 创建 RedisTemplate 对象RedisTemplate<String, Object> template = new RedisTemplate<>();// 设置 RedisConnection 工厂。 它就是实现多种 Java Redis 客户端接入的秘密工厂template.setConnectionFactory(connectionFactory);// 使用 String 序列化方式,序列化 KEY 。template.setKeySerializer(RedisSerializer.string());// 使用 JSON 序列化方式(库是 Jackson ),序列化 VALUE 。template.setValueSerializer(RedisSerializer.json());return template;}

【单元测试】

 @Beanpublic RedisTemplate<String, Object> redisTemplate() {// 创建 RedisTemplate 对象RedisTemplate<String, Object> template = new RedisTemplate<>();// 设置 RedisConnection 工厂。 它就是实现多种 Java Redis 客户端接入的秘密工厂template.setConnectionFactory(connectionFactory);// 使用 String 序列化方式,序列化 KEY 。template.setKeySerializer(RedisSerializer.string());// 使用 JSON 序列化方式(库是 Jackson ),序列化 VALUE 。template.setValueSerializer(RedisSerializer.json());return template;}

【结果】

是不是多了@class 属性,反序列化的对象的类型就可以从这里获取到。

@class 属性看似完美解决了反序列化后的对象类型,但是带来 JSON 字符串占用变大,所以实际项目中,我们很少采用 Jackson2JsonRedisSerializer

XML 序列化方式

org.springframework.data.redis.serializer.OxmSerializer使用 Spring OXM 实现将对象和 String 的转换,从而 String 和二进制数组的转换。 没见过哪个项目用过,不啰嗦了


spring boot整合redis实现RedisTemplate三分钟快速入门

引入依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

RedisTemplate五种数据结构的操作

  • redisTemplate.opsForValue(); //操作字符串
  • redisTemplate.opsForHash(); //操作hash
  • redisTemplate.opsForList(); //操作list
  • redisTemplate.opsForSet(); //操作set
  • redisTemplate.opsForZSet(); //操作有序zset

RedisTemplate方法讲解

判断key是否存在

 /*** 判断key是否存在*/@GetMapping("haskey")public boolean hasKey(String key) {return redisTemplate.hasKey(key);}

获取指定的key的失效时间

 /*** 指定key的失效时间*/@GetMapping("expire")public void expire(String key, long time) {//参数一:key//参数二:睡眠时间//参数三:睡眠时间单位 TimeUnit.DAYS 天 TimeUnit.HOURS 小时 。。。redisTemplate.expire(key, time, TimeUnit.MINUTES);}

根据key获取过期时间

 /*** 根据key获取过期时间*/@GetMapping("getexpire")public long getExpire(String key) {Long expire = redisTemplate.getExpire(key);return expire;}

根据key删除reids中缓存数据

 /*** 根据key删除reids中缓存数据*/@GetMapping("delredisbykey")public void delete(String key) {redisTemplate.delete(key);}

保存和读取String

 /*** 保存和读取String*/@GetMapping("stringredisdemo")public String stringredisdemo() {//设置过期时间为1分钟redisTemplate.opsForValue().set("key1", "value1", 1, TimeUnit.MINUTES);redisTemplate.opsForValue().set("key2", "value2");redisTemplate.opsForValue().set("key3", "value3");//读取redis数据String result1 = redisTemplate.opsForValue().get("key1").toString();String result2 = redisTemplate.opsForValue().get("key2").toString();String result3 = redisTemplate.opsForValue().get("key3").toString();System.out.println("缓存结果为:result:" + result1 + " " + result2 + "  " + result3);return "缓存结果为:result:" + result1 + " " + result2 + "  " + result3;}

保存和读取list

 /*** 保存和读取list*/@GetMapping("listredisdemo")public String listredisdemo() {List<String> list1 = new ArrayList<>();list1.add("a1");list1.add("a2");list1.add("a3");List<String> list2 = new ArrayList<>();list2.add("b1");list2.add("b2");list2.add("b3");redisTemplate.opsForList().leftPush("listkey1", list1);redisTemplate.opsForList().rightPush("listkey2", list2);List<String> resultList1 = (List<String>) redisTemplate.opsForList().leftPop("listkey1");List<String> resultList2 = (List<String>) redisTemplate.opsForList().rightPop("listkey2");System.out.println("resultList1:" + resultList1);System.out.println("resultList2:" + resultList2);return "成功";}

Hash结构,保存和读取map

 /*** Hash结构,保存和读取map*/@GetMapping("mapredisdemo")public String mapredisdemo() {Map<String, String> map = new HashMap<>();map.put("key1", "value1");map.put("key2", "value2");map.put("key3", "value3");map.put("key4", "value4");map.put("key5", "value5");redisTemplate.opsForHash().putAll("map1", map);Map<String, String> resultMap = redisTemplate.opsForHash().entries("map1");List<String> reslutMapList = redisTemplate.opsForHash().values("map1");Set<String> resultMapSet = redisTemplate.opsForHash().keys("map1");String value = (String) redisTemplate.opsForHash().get("map1", "key1");System.out.println("value:" + value);System.out.println("resultMapSet:" + resultMapSet);System.out.println("resultMap:" + resultMap);System.out.println("resulreslutMapListtMap:" + reslutMapList);return "成功";}

保存和读取Set

 /*** 保存和读取Set*/@GetMapping("setredisdemo")public String getredisdemo() {SetOperations<String, String> set = redisTemplate.opsForSet();set.add("key1", "value1");set.add("key1", "value2");set.add("key1", "value3");Set<String> resultSet = redisTemplate.opsForSet().members("key1");System.out.println("resultSet:" + resultSet);return "resultSet:" + resultSet;}

保存和读取zset

 /*** 保存和读取zset*/@GetMapping("zsetredisdemo")public String zsetredisdemo() {ZSetOperations.TypedTuple<Object> objectTypedTuple1 = new DefaultTypedTuple<>("zset-5", 9.6);ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<>("zset-6", 9.9);Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();tuples.add(objectTypedTuple1);tuples.add(objectTypedTuple2);System.out.println(redisTemplate.opsForZSet().add("zset1", tuples));System.out.println(redisTemplate.opsForZSet().range("zset1", 0, -1));return "成功";}

完整示例代码

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.*;
import java.util.concurrent.TimeUnit;@RestController
public class ReidsDemo {@AutowiredRedisTemplate redisTemplate;/*** 指定key的失效时间*/@GetMapping("expire")public void expire(String key, long time) {//参数一:key//参数二:睡眠时间//参数三:睡眠时间单位 TimeUnit.DAYS 天 TimeUnit.HOURS 小时 。。。redisTemplate.expire(key, time, TimeUnit.MINUTES);}/*** 根据key获取过期时间*/@GetMapping("getexpire")public long getExpire(String key) {Long expire = redisTemplate.getExpire(key);return expire;}/*** 判断key是否存在*/@GetMapping("haskey")public boolean hasKey(String key) {return redisTemplate.hasKey(key);}/*** 根据key删除reids中缓存数据*/@GetMapping("delredisbykey")public void delete(String key) {redisTemplate.delete(key);}/*** 保存和读取String*/@GetMapping("stringredisdemo")public String stringredisdemo() {//设置过期时间为1分钟redisTemplate.opsForValue().set("key1", "value1", 1, TimeUnit.MINUTES);redisTemplate.opsForValue().set("key2", "value2");redisTemplate.opsForValue().set("key3", "value3");//读取redis数据String result1 = redisTemplate.opsForValue().get("key1").toString();String result2 = redisTemplate.opsForValue().get("key2").toString();String result3 = redisTemplate.opsForValue().get("key3").toString();System.out.println("缓存结果为:result:" + result1 + " " + result2 + "  " + result3);return "缓存结果为:result:" + result1 + " " + result2 + "  " + result3;}/*** 保存和读取list*/@GetMapping("listredisdemo")public String listredisdemo() {List<String> list1 = new ArrayList<>();list1.add("a1");list1.add("a2");list1.add("a3");List<String> list2 = new ArrayList<>();list2.add("b1");list2.add("b2");list2.add("b3");redisTemplate.opsForList().leftPush("listkey1", list1);redisTemplate.opsForList().rightPush("listkey2", list2);List<String> resultList1 = (List<String>) redisTemplate.opsForList().leftPop("listkey1");List<String> resultList2 = (List<String>) redisTemplate.opsForList().rightPop("listkey2");System.out.println("resultList1:" + resultList1);System.out.println("resultList2:" + resultList2);return "成功";}/*** Hash结构,保存和读取map*/@GetMapping("mapredisdemo")public String mapredisdemo() {Map<String, String> map = new HashMap<>();map.put("key1", "value1");map.put("key2", "value2");map.put("key3", "value3");redisTemplate.opsForHash().putAll("map1", map);Map<String, String> resultMap = redisTemplate.opsForHash().entries("map1");List<String> reslutMapList = redisTemplate.opsForHash().values("map1");Set<String> resultMapSet = redisTemplate.opsForHash().keys("map1");String value = (String) redisTemplate.opsForHash().get("map1", "key1");System.out.println("value:" + value);System.out.println("resultMapSet:" + resultMapSet);System.out.println("resultMap:" + resultMap);System.out.println("resulreslutMapListtMap:" + reslutMapList);return "成功";}/*** 保存和读取Set*/@GetMapping("setredisdemo")public String getredisdemo() {SetOperations<String, String> set = redisTemplate.opsForSet();set.add("key1", "value1");set.add("key1", "value2");set.add("key1", "value3");Set<String> resultSet = redisTemplate.opsForSet().members("key1");System.out.println("resultSet:" + resultSet);return "resultSet:" + resultSet;}/*** 保存和读取zset*/@GetMapping("zsetredisdemo")public String zsetredisdemo() {ZSetOperations.TypedTuple<Object> objectTypedTuple1 = new DefaultTypedTuple<>("zset-5", 9.6);ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<>("zset-6", 9.9);Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();tuples.add(objectTypedTuple1);tuples.add(objectTypedTuple2);System.out.println(redisTemplate.opsForZSet().add("zset1", tuples));System.out.println(redisTemplate.opsForZSet().range("zset1", 0, -1));return "成功";}
}

序列化

直接粘贴在项目中即可

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.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;/*
*序列化*/
@Configuration
public class MyRedisConfig {@Bean(name = "redisTemplate")public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();//参照StringRedisTemplate内部实现指定序列化器redisTemplate.setConnectionFactory(redisConnectionFactory);redisTemplate.setKeySerializer(keySerializer());redisTemplate.setHashKeySerializer(keySerializer());redisTemplate.setValueSerializer(valueSerializer());redisTemplate.setHashValueSerializer(valueSerializer());return redisTemplate;}private RedisSerializer<String> keySerializer(){return new StringRedisSerializer();}//使用Jackson序列化器private RedisSerializer<Object> valueSerializer(){return new GenericJackson2JsonRedisSerializer();}
}

深入理解 Redis Template及4种序列化方式__spring boot整合redis实现RedisTemplate三分钟快速入门相关推荐

  1. redistemplate set方法_spring boot整合redis ---- RedisTemplate 三分钟快速入门

    引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spri ...

  2. Spring Boot整合Redis以及Redis的原理

    Redis的原理及知识 Redis简介 redis是一个key-value.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合). ...

  3. Redis - RedisTemplate及4种序列化方式深入解读

    文章目录 概述 RedisTemplate StringRedisTemplate RedisSerializer 序列化 接口 JDK 序列化方式 (默认) String 序列化方式 JSON 序列 ...

  4. Springboot下RedisTemplate的两种序列化方式

    一.定义一个配置类,自定义RedisTemplate的序列化方式 @Configuration public class RedisConfig {@Beanpublic RedisTemplate& ...

  5. android对象序列化的方法,Android 进阶-两种序列化方式 Serializable 和 Parcelable

    [导读]序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后,可以通过从存储区中读取或反序列化对象的状态 ...

  6. Kryo,Hessain,Protostuff三种序列化方式对比

    前言 前段时间在写RPC框架的时候用到了Kryo.Hessian.Protostuff三种序列化方式.但是当时因为急于实现功能,就只是简单的的看了一下如何使用这三种序列化方式,并没有去深入研究各自的特 ...

  7. Spring boot整合Redis实现发布订阅(超详细)

    Redis发布订阅 基础知识 相关命令 订阅者/等待接收消息 发布者/发送消息 订阅者/成功接收消息 常用命令汇总 原理 Spring boot整合redis 导入依赖 Redis配置 消息封装类(M ...

  8. spring boot连接redis配置127.0.0.1_Java技术分享——Springboot整合redis

    springboot提供了spring-data-redis的框架来整合redis的操作.下面主要介绍,springboot整合redis的配置,以及spring-data-redis是如何提供便捷的 ...

  9. Spring boot整合Redis(入门教程)

    目录 源码分析 jedis VS lettuce 整合测试 导入依赖 配置连接 测试 存入字符串 存入对象 五大数据类型操作 自定义RedisConfig 存入对象 Redis工具类(常用API) 以 ...

最新文章

  1. Confluence 6 其他需要备份和恢复的地方
  2. C++ 实现带权有向图的单源点最短路径Dijkstra算法(完整代码)
  3. C#.NET Thread多线程并发编程学习与常见面试题解析-1、Thread使用与控制基础
  4. 用计算机求函数公式,计算机常用的函数公式有哪些?
  5. 使用JDBC来连接数据库
  6. php jwt token刷新方案,解决使用jwt刷新token带来的问题
  7. JAVA操作数据库调试经验
  8. ”三不跳“ - 再说跳槽
  9. java核心技术卷1 所有示例代码
  10. Duilib学习笔记(一)—— 环境搭建
  11. java 开根号函数_java如何开根号?
  12. 杂凑算法md5c语言代码,MD5杂凑算法
  13. Java、JSP报刊订阅管理系统的设计与实现
  14. Android下拉状态栏 快捷开关的添加与删除
  15. PV 和 UV 的区别
  16. 2020年Android GMS 认证 boot logo 最新要求
  17. 【评测】MP DNA提取试剂盒使用报告
  18. OpenCalib:自动驾驶多传感器开源标定工具箱
  19. 通过PowerShell管理Office 365的网站
  20. Framework学习(五)应用程序启动过程

热门文章

  1. java linux 服务_java项目部署Linux服务器几种启动方式总结经验
  2. java awt 按钮响应_Java AWT按钮
  3. php curl_error源码,PHP curl_error函数
  4. java split空字符_java split函数结尾空字符串被丢弃的问题
  5. python中assert_在Python中带有示例的assert关键字
  6. 聊聊并发编程的10个坑
  7. Spring Cloud Alibaba 深度解密!
  8. JS关键字和保留字汇总
  9. 如何利用shell脚本和client-go实现自己的k8s调度器
  10. nginx php mysql一些常用命令(windows linux)