做网站实训心得,网络培训平台建设方案,上海全上海全国网站建设,徐州建设银行网上银行个人网站概述
使用Spring 提供的 Spring Data Redis 操作redis 必然要使用Spring提供的模板类 RedisTemplate#xff0c; 今天我们好好的看看这个模板类 。
RedisTemplate 看看4个序列化相关的属性 #xff0c;主要是 用于 KEY 和 VALUE 的序列化 。 举个例子#xff0c;比如说我们…概述
使用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
RedisTemplateK, 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 序列化方式JSON 序列化方式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 RedisTemplateString, Object redisTemplate() {// 创建 RedisTemplate 对象RedisTemplateString, 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 RedisTemplateString, Object redisTemplate() {// 创建 RedisTemplate 对象RedisTemplateString, 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三分钟快速入门
引入依赖
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId
/dependencyRedisTemplate五种数据结构的操作
redisTemplate.opsForValue(); //操作字符串redisTemplate.opsForHash(); //操作hashredisTemplate.opsForList(); //操作listredisTemplate.opsForSet(); //操作setredisTemplate.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() {ListString list1 new ArrayList();list1.add(a1);list1.add(a2);list1.add(a3);ListString list2 new ArrayList();list2.add(b1);list2.add(b2);list2.add(b3);redisTemplate.opsForList().leftPush(listkey1, list1);redisTemplate.opsForList().rightPush(listkey2, list2);ListString resultList1 (ListString) redisTemplate.opsForList().leftPop(listkey1);ListString resultList2 (ListString) redisTemplate.opsForList().rightPop(listkey2);System.out.println(resultList1: resultList1);System.out.println(resultList2: resultList2);return 成功;}Hash结构保存和读取map /*** Hash结构保存和读取map*/GetMapping(mapredisdemo)public String mapredisdemo() {MapString, 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);MapString, String resultMap redisTemplate.opsForHash().entries(map1);ListString reslutMapList redisTemplate.opsForHash().values(map1);SetString 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() {SetOperationsString, String set redisTemplate.opsForSet();set.add(key1, value1);set.add(key1, value2);set.add(key1, value3);SetString resultSet redisTemplate.opsForSet().members(key1);System.out.println(resultSet: resultSet);return resultSet: resultSet;}
保存和读取zset /*** 保存和读取zset*/GetMapping(zsetredisdemo)public String zsetredisdemo() {ZSetOperations.TypedTupleObject objectTypedTuple1 new DefaultTypedTuple(zset-5, 9.6);ZSetOperations.TypedTupleObject objectTypedTuple2 new DefaultTypedTuple(zset-6, 9.9);SetZSetOperations.TypedTupleObject 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() {ListString list1 new ArrayList();list1.add(a1);list1.add(a2);list1.add(a3);ListString list2 new ArrayList();list2.add(b1);list2.add(b2);list2.add(b3);redisTemplate.opsForList().leftPush(listkey1, list1);redisTemplate.opsForList().rightPush(listkey2, list2);ListString resultList1 (ListString) redisTemplate.opsForList().leftPop(listkey1);ListString resultList2 (ListString) redisTemplate.opsForList().rightPop(listkey2);System.out.println(resultList1: resultList1);System.out.println(resultList2: resultList2);return 成功;}/*** Hash结构保存和读取map*/GetMapping(mapredisdemo)public String mapredisdemo() {MapString, String map new HashMap();map.put(key1, value1);map.put(key2, value2);map.put(key3, value3);redisTemplate.opsForHash().putAll(map1, map);MapString, String resultMap redisTemplate.opsForHash().entries(map1);ListString reslutMapList redisTemplate.opsForHash().values(map1);SetString 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() {SetOperationsString, String set redisTemplate.opsForSet();set.add(key1, value1);set.add(key1, value2);set.add(key1, value3);SetString resultSet redisTemplate.opsForSet().members(key1);System.out.println(resultSet: resultSet);return resultSet: resultSet;}/*** 保存和读取zset*/GetMapping(zsetredisdemo)public String zsetredisdemo() {ZSetOperations.TypedTupleObject objectTypedTuple1 new DefaultTypedTuple(zset-5, 9.6);ZSetOperations.TypedTupleObject objectTypedTuple2 new DefaultTypedTuple(zset-6, 9.9);SetZSetOperations.TypedTupleObject 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 RedisTemplateString, Object redisTemplate(RedisConnectionFactory redisConnectionFactory){RedisTemplateString, Object redisTemplate new RedisTemplate();//参照StringRedisTemplate内部实现指定序列化器redisTemplate.setConnectionFactory(redisConnectionFactory);redisTemplate.setKeySerializer(keySerializer());redisTemplate.setHashKeySerializer(keySerializer());redisTemplate.setValueSerializer(valueSerializer());redisTemplate.setHashValueSerializer(valueSerializer());return redisTemplate;}private RedisSerializerString keySerializer(){return new StringRedisSerializer();}//使用Jackson序列化器private RedisSerializerObject valueSerializer(){return new GenericJackson2JsonRedisSerializer();}
}