springboot操作redis笔记
RedisTemplate&StringRedisTemplate
一.springboot整合redis
-
string Redis template是Redis template的子类,也就是说Redis template里有的成员方法string redis template中都有,而且string Redis template 中还包括自己的成员方法;两个的操作数据类型不同
-
string redis template 的传入键值类型是string类型,意味着StringRedisTemplate的key和value都只能是字符串。
-
redis template传入的泛型是object类型,意味着存储的key和value都可以是一个对象。
1.配置环境
1.首先配置redis环境,这里选用插件Spring Initializr进入
![image-20220816145659255]()
2.然后选择组件的时候

3.进入配置好的项目,首先查看maven的架包是否有错,接着引入redis依赖,这里不指定版本号
--redis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
4.配置application.yml文件
spring.redis.host=192.168.253.10 #ip地址
spring.redis.port=7000 #redis端口号
spring.redis.database=0 #指定数据库
使用StringRedisTemplate
package com.shujia.SpringBootRedis.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
@RestController//返回页面用controller,返回数据用@RestController,或者使用@Controller和@ResponseBody效果也是一样的
public class String_RedisTemplateController {
//springboot操作redis可以使用自己提供的redis依赖对象,父工程中已经从定义好了两个类供我们使用
//RedisTemplate和StringRedisTemplate
//通过对象注入的方式,使用该类的对象
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private StringRedisTemplate stringredisTemplate;
@RequestMapping("testkey")
public String test(){
//获取当前库中所有的键
// Set<String> keys = stringredisTemplate.keys("*");
//
// if (keys != null) {
// for (String key : keys) {
// System.out.println(key);
// }
// }else {
// System.out.println("数据库为空!!!!");
// }
//给键设置过期时间
// stringredisTemplate.expire("age", Duration.ofSeconds(20));
// stringredisTemplate.expire("age", Duration.ofDays(7));
// stringredisTemplate.expire("age", Duration.ofHours(6));
// stringredisTemplate.expire("age", Duration.ofMinutes(30));
// stringredisTemplate.expire("age", Duration.ofMillis(54));
// stringredisTemplate.expire("age", Duration.ofNanos(6));
//判断key是否存在
// Boolean name = stringredisTemplate.hasKey("name");
// System.out.println(name);
//将键移动到其他库中
// Boolean name = stringredisTemplate.move("name", 1);
// System.out.println(name);
//返回随机key
// String s = stringredisTemplate.randomKey();
// System.out.println(s);
//将key改名
// stringredisTemplate.rename("sal","newsal");
//返回key所存储的值的存储
// DataType newsal = stringredisTemplate.type("newsal");
// System.out.println(newsal);
//删除key
// Boolean sal = stringredisTemplate.delete("sal");
// System.out.println(sal);
//删除多个键,通过集合传值
// ArrayList<String> arrayList = new ArrayList<>();
// arrayList.add("name");
// arrayList.add("age");
// arrayList.add("sal");
// stringredisTemplate.delete(arrayList);
return "测试与键相关的操作成功!!!";
}
@RequestMapping("stringtest")
public String teststring(){
// set 设置一个key/value
// get 根据key获得对应的value
// stringredisTemplate.opsForValue().set("name","tgf");
// String name = stringredisTemplate.opsForValue().get("name");
// System.out.println(name);
// mset 一次设置多个keyvalue
// HashMap<String, String > hm = new HashMap<>();
// hm.put("age","18");
// hm.put("sal","18000");
// hm.put("like","睡觉");
// hm.put("weight","160");
// hm.put("hight","191");
// stringredisTemplate.opsForValue().multiSet(hm);
// mget 一次获得多个key的value
// ArrayList<String> arrayList = new ArrayList<>();
// arrayList.add("name");
// arrayList.add("sal");
// arrayList.add("like");
// arrayList.add("weight");
// arrayList.add("hight");
// List<String> strings = stringredisTemplate.opsForValue().multiGet(arrayList);
// for (String string : strings) {
// System.out.println(string);
// }
// getset 获得原始key的值,同时设置新值
// String andSet = stringredisTemplate.opsForValue().getAndSet("name", "tangguangfeng");
// System.out.println(andSet);
// strlen 获得对应key存储value的长度
// Long name = stringredisTemplate.opsForValue().size("name");
// System.out.println(name);
// append 为对应key的value追加内容
// stringredisTemplate.opsForValue().append("sal","900");
// getrange 索引0开始截取value的内容到末尾-1
// setex 设置一个key存活的有效期(秒)
// psetex 设置一个key存活的有效期(毫秒)
// setnx 存在不做任何操作,不存在添加
// msetnx原子操作(只要有一个存在不做任何操作)可以同时设置多个key,只有有一个存在都不保存
// decr 进行数值类型的-1操作
// decrby 根据提供的数据进行减法操作
// Incr 进行数值类型的+1操作
// incrby 根据提供的数据进行加法操作
// I ncrbyfloat 根据提供的数据加入浮点数(不是四舍五入)
return "String测试成功!!";
}
@RequestMapping("listest")
public String listtest(){
// lpush 将某个值加入到一个key列表头部, 当列表不存在的时候会进行创建
// stringredisTemplate.opsForList().leftPush("list","1");
// lpushx 同lpush,但是必须要保证这个key存在 必须在列表进行存在的情况下从左插入
// stringredisTemplate.opsForList().leftPush("list","1","88");
// rpush 将某个值加入到一个key列表末尾
// stringredisTemplate.opsForList().rightPush("list","78");
// rpushx 同rpush,但是必须要保证这个key存在
// stringredisTemplate.opsForList().rightPush("list","78","90");
// lpop 返回和移除列表左边的第一个元素
// stringredisTemplate.opsForList().leftPop("list");
// rpop 返回和移除列表右边的第一个元素
// stringredisTemplate.opsForList().rightPop("list");
// lrange 获取某一个下标区间内的元素 lrange list 0 -1
// stringredisTemplate.opsForList().range("list",0,-1);
// llen 获取列表元素个数
// stringredisTemplate.opsForList().size("list");
// lset 设置某一个指定索引的值(索引必须存在)
// lindex 获取某一个指定索引位置的元素
// stringredisTemplate.opsForList().index("list",0);
// lrem 删除重复元素
// linsert 在某一个元素之前,之后插入新元素
// ltrim 保留列表中特定区间内的元素
// stringredisTemplate.opsForList().trim("list",0,-1);
// 查看是否存在这个key
// Long list = stringredisTemplate.opsForList().leftPushIfPresent("list", "90");
return "listtest测试成功!!!";
}
@RequestMapping("setest")
public String settest() {
// sadd 为集合添加元素
stringredisTemplate.opsForSet().add("set","20","30","40","10","88","56");
// smembers 显示集合中所有元素 无序
stringredisTemplate.opsForSet().members("set");
// scard 返回集合中元素的个数
stringredisTemplate.opsForSet().size("set");
// spop 随机返回一个元素 并将元素在集合中删除
stringredisTemplate.opsForSet().pop("set");
// smove 从一个集合中向另一个集合移动元素 必须是同一种类型
stringredisTemplate.opsForSet().move("set","30","newset");
// srem 从集合中删除一个元素
stringredisTemplate.opsForSet().remove("set","20");
// sismember 判断一个集合中是否含有这个元素
stringredisTemplate.opsForSet().isMember("set","20");
// srandmember 随机返回元素 后面可以加数字 表示每次返回的个数
stringredisTemplate.opsForSet().distinctRandomMembers("set",1);
// sdiff 去掉第一个集合中其它集合含有的相同元素
stringredisTemplate.opsForSet().difference("set","newset");
// sinter 求交集
stringredisTemplate.opsForSet().intersect("set","newwset");
// sunion 求和集
stringredisTemplate.opsForSet().union("set","newset");
return "settest测试成功!!!";
}
@RequestMapping("zsetest")
public String zsettest() {
// zadd 添加一个有序集合元素 zadd zset 2 xiaohu 3 xiaohu2
stringredisTemplate.opsForZSet().add("zset","张三",80.0);
stringredisTemplate.opsForZSet().add("zset","李四",97.0);
stringredisTemplate.opsForZSet().add("zset","王五",100.0);
stringredisTemplate.opsForZSet().add("zset","赵六",40.0);
stringredisTemplate.opsForZSet().add("zset","武器",70.0);
stringredisTemplate.opsForZSet().add("zset","李八",90.0);
stringredisTemplate.opsForZSet().add("zset","汤九",89.0);
stringredisTemplate.opsForZSet().add("zset","卜十",76.0);
//2.集合插入
/**
* 添加多个数据值
* public Long add(K key, Set<TypedTuple<V>> tuples) {
* byte[] rawKey = rawKey(key);
* Set<Tuple> rawValues = rawTupleValues(tuples);
* return execute(connection -> connection.zAdd(rawKey, rawValues));
* }
*/
HashSet<ZSetOperations.TypedTuple<String>> myTypedTuples = new HashSet<>();
myTypedTuples.add(new MyTypedTuple("aa", 100.0));
myTypedTuples.add(new MyTypedTuple("bb", 200.0));
myTypedTuples.add(new MyTypedTuple("cc", 300.0));
myTypedTuples.add(new MyTypedTuple("dd", 150.0));
stringredisTemplate.opsForZSet().add("zset",myTypedTuples);
// zcard 返回集合的元素个数
Long zset = stringredisTemplate.opsForZSet().size("zset");
Long zset3 = stringredisTemplate.opsForZSet().zCard("zset");
System.out.println(zset3);
System.out.println(zset);
// zrange 升序
// zrevrange 降序返回一个范围内的元素 如果想看看分数 withscores
stringredisTemplate.opsForZSet().reverseRange("zset",0,-1);
// zrangebyscore 按照分数查找一个范围内的元素 zrangebyscore zset 0 20 withscores limit 0 2zrank返回排名
Set<String> zset1 = stringredisTemplate.opsForZSet().rangeByScore("zset", 40, 70);
for (String s : zset1) {
System.out.println(s);
}
// zrevrank 倒序排名
stringredisTemplate.opsForZSet().removeRangeByScore("zset",0,100);
// zscore 显示某一个元素的分数
String zset2 = stringredisTemplate.opsForZSet().randomMember("zset");
System.out.println(zset2);
// zrem 移除某一个元素
stringredisTemplate.opsForZSet().remove("zset","80");
// zincrby 给某个特定元素加分
stringredisTemplate.opsForZSet().incrementScore("zset","80",80l);
return "zsettest测试成功!!!";
}
@RequestMapping("hashtest")
public String hashtest() {
// hset 设置一个key/value对
HashMap<String, String> map = new HashMap<>();
map.put("name","tgf");
map.put("age","18");
map.put("sal","20000");
map.put("weight","150");
map.put("height","191");
map.put("like","sleep");
map.put("drink","coco");
stringredisTemplate.opsForHash().putAll("hash",map);
// hget 获得一个key对应的value
stringredisTemplate.opsForHash().get("hash","name");
// hgetall 获得所有的key/value对
ArrayList<Object> list = new ArrayList<>();
list.add("name");
list.add("age");
list.add("sal");
list.add("like");
list.add("height");
list.add("weight");
list.add("drink");
List<Object> hash = stringredisTemplate.opsForHash().multiGet("hash", list);
for (Object o : hash) {
System.out.println(o);
}
// hdel 删除某一个key/value对
stringredisTemplate.opsForHash().delete("hash","weight");
// hexists 判断一个key是否存在
stringredisTemplate.opsForHash().hasKey("hash","name");
// hkeys 获得所有的key
stringredisTemplate.opsForHash().keys("*");
// hvals 获得所有的value
stringredisTemplate.opsForHash().values("hash");
// hmset 设置多个key/value
stringredisTemplate.opsForHash().putAll("hash1",map);
// hmget 获得多个key的value
stringredisTemplate.opsForHash().multiGet("hash1",list);
// hsetnx 设置一个不存在的key的值
stringredisTemplate.opsForHash().putIfAbsent("hash1","hahah","89");
// hincrby 为value进行加法运算(只能针对数值做运行)
stringredisTemplate.opsForHash().increment("hash1","sal",9000000l);
// hincrbyfloat 为value加入浮点值
return "hashtest测试成功!!!";
}
@RequestMapping("bittest")
public String bit(){
return "bittest测试成功!!!!";
}
@RequestMapping("test")
public String hello(){
return "测试模板springboot成功!!!";
}
}
这里的zset创建了实体类,进行传值
package com.shujia.SpringBootRedis.entity;
import org.springframework.data.redis.core.ZSetOperations;
public class MyTypedTuple<String> implements ZSetOperations.TypedTuple<String> {
private String value;
private Double score;
public MyTypedTuple(String value,Double score){
this.value = value;
this.score = score;
}
@Override
public String getValue() {
return value;
}
@Override
public Double getScore() {
return score;
}
@Override
public int compareTo(ZSetOperations.TypedTuple<String> o) {
return 0;
}
}
使用RedisTemplate
RedisTemplate:Key和Object类型都是Object类型,将key和value当作对象来看待
既然将key和value当作对象来看待,那么存储的时候,就是存一个对象
对象存储到数据库中,是一个持久化的过程,对象持久化到数据库中,需要对对象进行序列化
分析为什么是null?
首先,name我们使用StringRedisTemplate,而我们现在用RedisTemplate去读,两个类都不一样,可能读不到
我们回想一下刚刚提到的一点,RedisTemplate会将key和value当作对象来看待,所以需要对key和value做序列化
那么RedisTemplate就应该把我们传进去的name做序列化,”name“ --->"namexxxx",然后拿着序列化后的值去 redis中找,而redis中并没有namexxxx,所以结果为null
String类刚刚才看的,已经实现了serializable接口,为什么不行呢?
所以这里,用的应该不是 jdk自己序列化,而是redis中特有的序列化方式
我们使用了redis特有的序列化方式后,结果却依旧没有出来。
序列化ID,再次插入一次,让两次序列化ID保持一直就可以了。
1.首先如果是存储出一个对象,这个类有没有实现序列化接口?
2.有没有实现redis特有的序列化实现方式?
3.有没有保持插入和取出的序列化id是一致的?
只有这三点都保证的情况下,数据才能出来
package com.shujia.SpringBootRedis.controller;
import com.shujia.SpringBootRedis.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Redis_TemplateController {
//通过对象注入的方式,使用该类的对象
@Autowired
private RedisTemplate<Object,Object> redisTemplate;
@RequestMapping("stringtest1")
public String stringtest(){
//先将stringredis进行序列化,设置键序列化
redisTemplate.setKeySerializer(new JdkSerializationRedisSerializer());
Object name1 = redisTemplate.opsForValue().get("name");
System.out.println(name1);//NULL
return "stringtest测试成功";
}
@RequestMapping("stringtest11")
//可以通过序列化先传入,再get
public String stringtest1(){
//如果传入的是对象,使用JdkSerializationRedisSerializer进行序列化
redisTemplate.setKeySerializer(new JdkSerializationRedisSerializer());
// redisTemplate.opsForValue().set("name1","tgf");
Object name1 = redisTemplate.opsForValue().get("name1");
System.out.println(name1);
return "stringtest测试成功";
}
@RequestMapping("stringtest2")
public String stringtest2(){
// Student student = new Student("汤光峰","18","hahah");
// redisTemplate.opsForValue().set("1001",student);
// Object o = redisTemplate.opsForValue().get("1001");
// System.out.println(o);
//字符串使用StringRedisSerializer进行序列化,这样的好处是redis可视化工具里可以看懂
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
redisTemplate.opsForHash().put("1002","tgf","80");
return "stringtest测试成功";
}
}
............实现方法与StringRedisTemplate一致
这边如果创建对象进行传值的话,对象要实现serializable接口,并分配序列化ID
package com.shujia.SpringBootRedis.entity;
import java.io.Serializable;
public class Student implements Serializable {
private static final long serialVersionUID = 6547839622554453185L;
private String name;
private String age;
private String like;
public Student(String name, String age, String like) {
this.name = name;
this.age = age;
this.like = like;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getLike() {
return like;
}
public void setLike(String like) {
this.like = like;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
", like='" + like + '\'' +
'}';
}
}
二.连接池(是基于jedis的)
添加依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
具体代码
//构建redis资源连接池配置
JedisPoolConfig poolConfig = new JedisPoolConfig();
//给定个数
poolConfig.setMaxTotal(100);
//根据这个配置来创建redis连接池
JedisPool jedisPool = new JedisPool(poolConfig, "192.168.253.10", 6888);
//在连接池中构建redis连接
Jedis jedis = jedisPool.getResource();
//拿着这个连接操作redis
String name1 = jedis.get("name");
System.out.println(name1);
//操作完后将连接归还给连接池
jedis.close();


浙公网安备 33010602011771号