第125天学习打卡(Redis Jedis 常用的API 事务 springboot整合)

### Jedis

我们要使用Java来操作Redis

> 什么是Jedis 是Redis官方推荐的Java连接的开发工具,使用Java操作Redis中间件!如果使用Java操作redis,一定要对Jedis十分熟悉。

> 测试

**在java中建立空项目要注意把这几个地方进行配置:**

![image-20210513144405445](https://gitee.com/doudoutj111/tj/raw/master/img/image-20210513144405445.png)

![image-20210513144519686](https://gitee.com/doudoutj111/tj/raw/master/img/image-20210513144519686.png)

![image-20210513144858849](https://gitee.com/doudoutj111/tj/raw/master/img/image-20210513144858849.png)

 

1.导入对应 的依赖

pom.xml

```xml
<dependencies>
<!-- 导入jedis的包-->

<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.6.0</version>
</dependency>

<!-- 导入fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
```

2.编码测试:

- 连接数据库
- 操作命令
- 断开连接

**测试连接:**

首先开启redis:

![image-20210513152253674](https://gitee.com/doudoutj111/tj/raw/master/img/image-20210513152253674.png)

然后在IDEA中测试连接:

```java
package com.kuang;

import redis.clients.jedis.Jedis;

public class TestPing {
public static void main(String[] args) {
//1. new Jedis
Jedis jedis = new Jedis("127.0.0.1",6379);
//jedis 所有的命令就是我们之前学习的所有指令!
System.out.println(jedis.ping());


}
}

```

**输出为:PONG则表示连接成功!**

### 常用的API

#### Key

```java
package com.kuang;

import redis.clients.jedis.Jedis;

import java.util.Set;

public class TestKey {
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1",6379);
System.out.println("清空数据:" + jedis.flushDB());
System.out.println("判断某个键是否存在:" + jedis.exists("username"));
System.out.println("新增<'username', 'kuangshen'>的键值对:" + jedis.set("username","kuangshen"));
System.out.println("新增<'password','password'>的键值对:" + jedis.set("password","password"));
System.out.println("系统中的所有的键如下:");
Set<String> keys = jedis.keys("*");
System.out.println(keys);
System.out.println("删除键password:" + jedis.del("password"));
System.out.println("判断建password是否存在:" + jedis.exists("password"));
System.out.println("查看键username所存储的值的类型:" + jedis.type("username"));
System.out.println("随机返回key空间的一个:" + jedis.randomKey());
System.out.println("重命名key:" + jedis.rename("username", "name"));
System.out.println("取出改后的name:" + jedis.get("name"));
System.out.println("按索引查询:" + jedis.select(0));
System.out.println("删除当前选择数据库中的所有key:" + jedis.flushDB());
System.out.println("返回当前数据库中的key的数目:" + jedis.dbSize());
System.out.println("删除所有数据库中的所有key:" + jedis.flushAll());


}
}

```

**输出的结果:**

```java
清空数据:OK
判断某个键是否存在:false
新增<'username', 'kuangshen'>的键值对:OK
新增<'password','password'>的键值对:OK
系统中的所有的键如下:
[password, username]
删除键password:1
判断建password是否存在:false
查看键username所存储的值的类型:string
随机返回key空间的一个:username
重命名key:OK
取出改后的name:kuangshen
按索引查询:OK
删除当前选择数据库中的所有key:OK
返回当前数据库中的key的数目:0
删除所有数据库中的所有key:OK

Process finished with exit code 0
```

#### String

```java
package com.kuang;

import redis.clients.jedis.Jedis;

import java.util.concurrent.TimeUnit;

public class TestString {
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.flushDB();
System.out.println("=================增加数据=====================");
System.out.println(jedis.set("key1", "value1"));
System.out.println(jedis.set("key2", "value2"));
System.out.println(jedis.set("key3", "value3"));
System.out.println("删除键key2:" + jedis.del("key2"));
System.out.println("获取键key2:" + jedis.get("key2"));
System.out.println("修改key1:" + jedis.set("key1", "value1Changed"));
System.out.println("获取key1的值:" + jedis.get("key1"));
System.out.println("在key3后面加入值:" + jedis.append("key3", "End"));
System.out.println("key3的值:" + jedis.get("key3"));
System.out.println("增加多个键值对:" + jedis.mset("key01", "value01", "key02", "value02", "key03", "value03"));
System.out.println("获取多个键值对:" + jedis.mget("key01", "key02", "key03"));
System.out.println("获取多个键值对:" + jedis.mget("key01", "key02", "key03", "key04"));
System.out.println("删除多个键值对:" + jedis.del("key01", "key02"));
System.out.println("获取多个键值对:" + jedis.mget("key01", "key02", "key03"));
jedis.flushDB();
System.out.println("===============新增键值对防止覆盖原先值======================");
System.out.println(jedis.setnx("key1", "value1"));
System.out.println(jedis.setnx("key2", "value2"));
System.out.println(jedis.setnx("key2", "value2-new"));
System.out.println(jedis.get("key1"));
System.out.println(jedis.get("key2"));

System.out.println("==================新增键值对并设置有效时间===================");
System.out.println(jedis.setex("key3", 2, "value3"));
System.out.println(jedis.get("key3"));
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(jedis.get("key3"));

System.out.println("=================获取原值,更新为新值==============");
System.out.println(jedis.getSet("key2", "ke2GetSet"));
System.out.println(jedis.get("key2"));
System.out.println("获得key2的值的字符串:" + jedis.getrange("key2", 2, 4));

 

}
}

```

**输出结果:**

```java
=================增加数据=====================
OK
OK
OK
删除键key2:1
获取键key2:null
修改key1:OK
获取key1的值:value1Changed
在key3后面加入值:9
key3的值:value3End
增加多个键值对:OK
获取多个键值对:[value01, value02, value03]
获取多个键值对:[value01, value02, value03, null]
删除多个键值对:2
获取多个键值对:[null, null, value03]
===============新增键值对防止覆盖原先值======================
1
1
0
value1
value2
==================新增键值对并设置有效时间===================
OK
value3
null
=================获取原值,更新为新值==============
value2
ke2GetSet
获得key2的值的字符串:2Ge

Process finished with exit code 0

```

#### List

```java
package com.kuang;

import redis.clients.jedis.Jedis;

public class TestList {
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.flushDB();
System.out.println("====================添加一个list================");
jedis.lpush("collections", "ArrayList", "Vector", "Stack", "HashMap", "WeakHashMap", "LinkedHashMap", "EnumMap");
jedis.lpush("collections", "HashSet");
jedis.lpush("collections", "TreeSet");
jedis.lpush("collections", "TreeMap");
System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
System.out.println("collections区间0-3的元素:" + jedis.lrange("collections", 0, 3));
System.out.println("==========================");
//删除列表指定的值,第二个参数为删除个数(有重复时),后add进去的值先被删除,类似于出栈
System.out.println("删除指定元素的个数:" + jedis.lrem("collections", 2, "HashMap"));
System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
System.out.println("删除下标0-3区间之外的元素:" + jedis.ltrim("collections", 0, 3));
System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
System.out.println("collections列表出栈(左端):" + jedis.lpop("collections"));
System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
System.out.println("collections添加内容, 从列表右端,与lpush相对应:" + jedis.rpush("collections", "kuangshenshuo"));
System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
System.out.println("collections列表出栈(右端):" + jedis.rpop("collections"));
System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
System.out.println("修改collections指定下标1的内容:" + jedis.lset("collections", 1,"LinkedHashMap"));
System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
System.out.println("=======================================");
System.out.println("collections的长度:" + jedis.llen("collections"));
System.out.println("获取collections下标为2的元素:" + jedis.lindex("collections", 2));
System.out.println("===========================");
jedis.lpush("sortedList", "3", "6", "2", "5", "7", "0", "4");
System.out.println("sortedList排序前:" + jedis.lrange("sortedList", 0, -1));
System.out.println(jedis.sort("sortedList"));
System.out.println("sortedList排序后:" + jedis.lrange("sortedList", 0, -1));

}
}

```

**输出结果:**

```java
====================添加一个list================
collections的内容:[TreeMap, TreeSet, HashSet, EnumMap, LinkedHashMap, WeakHashMap, HashMap, Stack, Vector, ArrayList]
collections区间0-3的元素:[TreeMap, TreeSet, HashSet, EnumMap]
==========================
删除指定元素的个数:1
collections的内容:[TreeMap, TreeSet, HashSet, EnumMap, LinkedHashMap, WeakHashMap, Stack, Vector, ArrayList]
删除下标0-3区间之外的元素:OK
collections的内容:[TreeMap, TreeSet, HashSet, EnumMap]
collections列表出栈(左端):TreeMap
collections的内容:[TreeSet, HashSet, EnumMap]
collections添加内容, 从列表右端,与lpush相对应:4
collections的内容:[TreeSet, HashSet, EnumMap, kuangshenshuo]
collections列表出栈(右端):kuangshenshuo
collections的内容:[TreeSet, HashSet, EnumMap]
修改collections指定下标1的内容:OK
collections的内容:[TreeSet, LinkedHashMap, EnumMap]
=======================================
collections的长度:3
获取collections下标为2的元素:EnumMap
===========================
sortedList排序前:[4, 0, 7, 5, 2, 6, 3]
[0, 2, 3, 4, 5, 6, 7]
sortedList排序后:[4, 0, 7, 5, 2, 6, 3]

Process finished with exit code 0

```

#### Set

```java
package com.kuang;

import redis.clients.jedis.Jedis;

public class TestSet {
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.flushDB();
System.out.println("===================向集合中添加元素(不重复)============");
System.out.println(jedis.sadd("eleSet", "e1", "e2", "e4", "e3", "e0", "e7", "e8", "e5"));
System.out.println(jedis.sadd("eleSet", "e6"));
System.out.println(jedis.sadd("eleSet", "e6"));
System.out.println("eleSet的所有的元素为:" + jedis.smembers(("eleSet")));
System.out.println("删除一个元素e0:" + jedis.srem("eleSet", "e0"));
System.out.println("eleSet的所有的元素为:" + jedis.smembers(("eleSet")));
System.out.println("删除两个元素e7和e6:" + jedis.srem("eleSet", "e7", "e6"));
System.out.println("eleSet的所有的元素为:" + jedis.smembers(("eleSet")));
System.out.println("随机的移除集合中的一个元素:" + jedis.spop("eleSet"));
System.out.println("随机的移除集合中的一个元素:" + jedis.spop("eleSet"));
System.out.println("eleSet的所有的元素为:" + jedis.smembers(("eleSet")));
System.out.println("eleSet中包含元素的个数:" + jedis.scard("eleSet"));
System.out.println("e3是否在eleSet中:" + jedis.sismember("eleSet", "e3"));
System.out.println("e1是否在eleSet中:" + jedis.sismember("eleSet", "e1"));
System.out.println("e5是否在eleSet中:" + jedis.sismember("eleSet", "e5"));
System.out.println("========================================");
System.out.println(jedis.sadd("eleSet1", "e1", "e2", "e4", "e3", "e0", "e7", "e8", "e5"));
System.out.println(jedis.sadd("eleSet2", "e1", "e2", "e4", "e3", "e0", "e8"));
System.out.println("将eleSet1中删除e1并存入eleSet3中:" + jedis.smove("eleSet1", "eleSet3","e1"));
System.out.println("将eleSet1中删除e2并存入eleSet3中:" + jedis.smove("eleSet1", "eleSet3","e2"));
System.out.println("eleSet1中的元素:" + jedis.smembers("eleSet1"));
System.out.println("eleSet3中的元素:" + jedis.smembers("eleSet3"));
System.out.println("================集合运算====================");
System.out.println("eleSet1中的元素:" + jedis.smembers("eleSet1"));
System.out.println("eleSet2中的元素:" + jedis.smembers("eleSet2"));
System.out.println("eleSet1和eleSet2的交集:" + jedis.sinter("eleSet1", "eleSet2"));
System.out.println("eleSet1和eleSet2的并集:" + jedis.sunion("eleSet1", "eleSet2"));
System.out.println("eleSet1和eleSet2的差集:" + jedis.sdiff("eleSet1", "eleSet2"));//eleSet1中有,eleSet2中没有
jedis.sinterstore("eleSet4", "eleSet1", "eleSet2");//求交集并将交集保存到dstkey中
System.out.println("eleSet4中的元素:" + jedis.smembers("eleSet4"));

 

 

}
}

```

**输出结果:**

```java
===================向集合中添加元素(不重复)============
8
1
0
eleSet的所有的元素为:[e2, e8, e3, e4, e7, e0, e1, e6, e5]
删除一个元素e0:1
eleSet的所有的元素为:[e8, e3, e4, e7, e1, e2, e6, e5]
删除两个元素e7和e6:2
eleSet的所有的元素为:[e4, e1, e2, e8, e5, e3]
随机的移除集合中的一个元素:e5
随机的移除集合中的一个元素:e3
eleSet的所有的元素为:[e2, e8, e4, e1]
eleSet中包含元素的个数:4
e3是否在eleSet中:false
e1是否在eleSet中:true
e5是否在eleSet中:false
========================================
8
6
将eleSet1中删除e1并存入eleSet3中:1
将eleSet1中删除e2并存入eleSet3中:1
eleSet1中的元素:[e5, e8, e3, e4, e7, e0]
eleSet3中的元素:[e2, e1]
================集合运算====================
eleSet1中的元素:[e5, e8, e3, e4, e7, e0]
eleSet2中的元素:[e2, e3, e1, e8, e4, e0]
eleSet1和eleSet2的交集:[e3, e8, e4, e0]
eleSet1和eleSet2的并集:[e8, e3, e4, e0, e7, e1, e2, e5]
eleSet1和eleSet2的差集:[e5, e7]
eleSet4中的元素:[e4, e0, e8, e3]

Process finished with exit code 0
```

#### Hash中也要把下面这些配置好,不然hashmap不能成功

![image-20210513185115579](https://gitee.com/doudoutj111/tj/raw/master/img/image-20210513185115579.png)

![image-20210513185154467](https://gitee.com/doudoutj111/tj/raw/master/img/image-20210513185154467.png)

![image-20210513185233326](https://gitee.com/doudoutj111/tj/raw/master/img/image-20210513185233326.png)

```java
package com.kuang;

import redis.clients.jedis.Jedis;

import java.util.HashMap;

public class TestHash {
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1",6379);
jedis.flushDB();
HashMap<String, String> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.put("key4", "value4");
//添加名称为hash(key)的hash元素
jedis.hmset("hash", map);
//向名称为hash的hash中添加key 为key5, value为value5的元素
jedis.hset("hash", "key5","value5");
System.out.println("散列hash的所有键值对为:" + jedis.hgetAll("hash"));
System.out.println("散列hash的所有键为:" + jedis.hkeys("hash"));
System.out.println("散列hash的所有值为:" + jedis.hvals("hash"));
System.out.println("将key6保存的值加上一个整数, 如果key6不存在则添加key6:" + jedis.hincrBy("key6","key6", 6));
System.out.println("散列hash的所有键值对为:" + jedis.hgetAll("hash"));
System.out.println("将key6保存的值加上一个整数, 如果key6不存在则添加key6:" + jedis.hincrBy("hash","key6", 6));
System.out.println("散列hash的所有键值对为:" + jedis.hgetAll("hash"));
System.out.println("删除一个或者多个键值对:" + jedis.hdel("hash", "key2"));
System.out.println("散列hash的所有键值对为:" + jedis.hgetAll("hash"));
System.out.println("散列hash中键值对的个数:" + jedis.hlen("hash"));
System.out.println("判断hash中是否存在Key2:" + jedis.hexists("hash", "key2"));
System.out.println("判断hash中是否存在Key3:" + jedis.hexists("hash", "key3"));
System.out.println("获取hash中的值:" + jedis.hmget("hash", "key3"));
System.out.println("获取hash中的值:" + jedis.hmget("hash", "key3", "key4"));

 

 

}
}

```

**输出的结果为:**

```java
散列hash的所有键值对为:{key1=value1, key2=value2, key5=value5, key3=value3, key4=value4}
散列hash的所有键为:[key1, key2, key5, key3, key4]
散列hash的所有值为:[value3, value2, value1, value4, value5]
将key6保存的值加上一个整数, 如果key6不存在则添加key6:6
散列hash的所有键值对为:{key1=value1, key2=value2, key5=value5, key3=value3, key4=value4}
将key6保存的值加上一个整数, 如果key6不存在则添加key6:6
散列hash的所有键值对为:{key1=value1, key2=value2, key5=value5, key6=6, key3=value3, key4=value4}
删除一个或者多个键值对:1
散列hash的所有键值对为:{key1=value1, key5=value5, key6=6, key3=value3, key4=value4}
散列hash中键值对的个数:5
判断hash中是否存在Key2:false
判断hash中是否存在Key3:true
获取hash中的值:[value3]
获取hash中的值:[value3, value4]

Process finished with exit code 0
```

#### 事务

执行成功案例:

```java
package com.kuang;

import com.alibaba.fastjson.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

public class TestTX {
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
JSONObject jsonObject = new JSONObject();
jsonObject.put("hello", "world");
jsonObject.put("name", "kuangshen");

//开启事务
Transaction multi = jedis.multi();
String result = jsonObject.toJSONString();
try {
multi.set("user1", result);
multi.set("user2", result);
multi.exec();//成功就执行事务
} catch (Exception e) {
multi.discard();//失败就放弃事务
e.printStackTrace();
} finally {
System.out.println(jedis.get("user1"));
System.out.println(jedis.get("user2"));

jedis.close();//关闭连接
}

 

}
}

```

**输出值:**

```java
{"name":"kuangshen","hello":"world"}
{"name":"kuangshen","hello":"world"}

Process finished with exit code 0
```

执行失败案例:

```java
package com.kuang;

import com.alibaba.fastjson.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

public class TestTX {
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.flushDB();
JSONObject jsonObject = new JSONObject();
jsonObject.put("hello", "world");
jsonObject.put("name", "kuangshen");

//开启事务
Transaction multi = jedis.multi();
String result = jsonObject.toJSONString();
try {
multi.set("user1", result);
multi.set("user2", result);
int i = 1 / 0; //代码抛出异常事务,执行失败
multi.exec();//成功就执行事务
} catch (Exception e) {
multi.discard();//失败就放弃事务
e.printStackTrace();
} finally {
System.out.println(jedis.get("user1"));
System.out.println(jedis.get("user2"));

jedis.close();//关闭连接
}

 

}
}

```

**输出结果:**

```java
java.lang.ArithmeticException: / by zero
at com.kuang.TestTX.main(TestTX.java:21)
null
null

Process finished with exit code 0
```

### SpringBoot整合

SpringBoot操作数据: spring-data jpa jdbc mongodb redis!
SpringData也是和SpringBoot齐名的项目

说明:在SpringBoot2.x之后,原来使用的jedis被替换为了lettuce?

jedis:底层采用的是直连,多个线程操作的话,是不安全的,如果想要避免不安全的,使用jedis pool连接池! BIO阻塞连接

lettuce: 采用netty,实例可以在多个线程中进行共享,不存在线程不安全的情况!可以减少线程数据,更像NIO模式

**源码分析:**

```java
@Bean
@ConditionalOnMissingBean(
name = {"redisTemplate"}//我们可以自定义一个redisTemplate来替换这个默认的
)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
// 默认的 RedisTemplate 没有过多的设置,redis对象都是需要序列化的!
//两个泛型都是<Object, Object> 的类型,我们后面使用的话需要强转<String, Object>
RedisTemplate<Object, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}

@Bean
@ConditionalOnMissingBean //由于String 是redis中最常使用的类型,所以说单独提出来了一个bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
```

 

> 整合测试

![image-20210513193402584](https://gitee.com/doudoutj111/tj/raw/master/img/image-20210513193402584.png)

1.导入依赖

**pom.xml**

```xml
<!--操作redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
```

 

2.配置连接

**application.properties**

```properties
# SpringBoot所有的配置类, 都有一个自动配置类 RedisAutoConfiguration
# 自动配置类都会绑定一个properties配置文件 RedisProperties
#配置redis
spring.redis.host=127.0.0.1
spring.redis.port=6379


```

 

3.测试

```java
package com.kuang;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class Redis02SpringbootApplicationTests {
@Autowired
private RedisTemplate redisTemplate;

@Test
void contextLoads() {
// redisTemplate 操作不同的数据类型, api和我们的指令是一样的
// opsForValue:操作字符串, 类似String类型
//opsForList 操作list 类似list
//opsForSet
//opsForHash
//opsForGeo
//opsForZSet
//除了基本的操作,我们常用的方法都可以通过redisTemplate操作, 比如事务和基本的CRUD

//获取redis的连接对象
// RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
// connection.flushDb();
// connection.flushAll();
redisTemplate.opsForValue().set("mykey", "kuangshen");
System.out.println(redisTemplate.opsForValue().get("mykey"));


}

}

```

 

**源码分析: 序列化配置**

```java
@Nullable
private RedisSerializer keySerializer = null;
@Nullable
private RedisSerializer valueSerializer = null;
@Nullable
private RedisSerializer hashKeySerializer = null;
@Nullable
private RedisSerializer hashValueSerializer = null;
```

**默认的序列化方式是JDK序列化,我们可能会使用JSON来序列化**

```java
if (this.defaultSerializer == null) {
this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());
}
```

**没有序列化的测试**

**pojo User.java**

```java
package com.kuang.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
private String name;
private int age;

}

```

 

![image-20210513204638975](https://gitee.com/doudoutj111/tj/raw/master/img/image-20210513204638975.png)

**有序列化的测试**

**pojo User.java**

```java
package com.kuang.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

import java.io.Serializable;

@Component
@AllArgsConstructor
@NoArgsConstructor
@Data
//在企业中, 我们所有的pojo都会序列化
public class User implements Serializable {
private String name;
private int age;

}

```

 

![image-20210513205605101](https://gitee.com/doudoutj111/tj/raw/master/img/image-20210513205605101.png)

 

**编写的RedisTemplate**

```java
package com.kuang.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
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.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {
//这是一个固定的模板,拿去就可以直接使用
//自己定义的RedisTemplate
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
//为了开发方便 一般使用<string,Object>
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);

//Json序列化 new Jackson2JsonRedisSerializer(Object.class) 首先是Json去解析任意的对象
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//ObjectMapper进行转义
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);

//String的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();

return template;
}

}


```

**测试:**

```java
package com.kuang;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.kuang.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class Redis02SpringbootApplicationTests {
@Autowired
@Qualifier("redisTemplate") //存在多个redisTemplate 所以用@Qualifier("redisTemplate") 进行指定
private RedisTemplate redisTemplate;

@Test
public void test() throws JsonProcessingException {
//真实的开发一般都是以json来传递对象
User user = new User("狂神说", 3);
// String jsonUser = new ObjectMapper().writeValueAsString(user); //ObjectMapper json对象 传json字符串
redisTemplate.opsForValue().set("user", user);
System.out.println(redisTemplate.opsForValue().get("user"));
}

 

}

```

**utils 工具封装**

**RedisUtil.java**

```java
package com.kuang.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
// 在真实的开发中, 一般都可以看到一个公司自己封装的RedisUtil
@Component
public final class RedisUtil {

@Autowired
private RedisTemplate<String, Object> redisTemplate;

// =============================common============================
/**
* 指定缓存失效时间
* @param key 键
* @param time 时间(秒)
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}

/**
* 根据key 获取过期时间
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}


/**
* 判断key是否存在
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}


/**
* 删除缓存
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}


// ============================String=============================

/**
* 普通缓存获取
* @param key 键
* @return 值
*/
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}

/**
* 普通缓存放入
* @param key 键
* @param value 值
* @return true成功 false失败
*/

public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}


/**
* 普通缓存放入并设置时间
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/

public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}


/**
* 递增
* @param key 键
* @param delta 要增加几(大于0)
*/
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}


/**
* 递减
* @param key 键
* @param delta 要减少几(小于0)
*/
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}


// ================================Map=================================

/**
* HashGet
* @param key 键 不能为null
* @param item 项 不能为null
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}

/**
* 获取hashKey对应的所有键值
* @param key 键
* @return 对应的多个键值
*/
public Map<Object, Object> hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}

/**
* HashSet
* @param key 键
* @param map 对应多个键值
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}


/**
* HashSet 并设置时间
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
* @return true成功 false失败
*/
public boolean hmset(String key, Map<String, Object> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}


/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}

/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}


/**
* 删除hash表中的值
*
* @param key 键 不能为null
* @param item 项 可以使多个 不能为null
*/
public void hdel(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}


/**
* 判断hash表中是否有该项的值
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return true 存在 false不存在
*/
public boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}


/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
*
* @param key 键
* @param item 项
* @param by 要增加几(大于0)
*/
public double hincr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, by);
}


/**
* hash递减
*
* @param key 键
* @param item 项
* @param by 要减少记(小于0)
*/
public double hdecr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}


// ============================set=============================

/**
* 根据key获取Set中的所有值
* @param key 键
*/
public Set<Object> sGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}


/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}


/**
* 将数据放入set缓存
*
* @param key 键
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}


/**
* 将set数据放入缓存
*
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0)
expire(key, time);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}


/**
* 获取set缓存的长度
*
* @param key 键
*/
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}


/**
* 移除值为value的
*
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/

public long setRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}

// ===============================list=================================

/**
* 获取list缓存的内容
*
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1代表所有值
*/
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}


/**
* 获取list缓存的长度
*
* @param key 键
*/
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}


/**
* 通过索引 获取list中的值
*
* @param key 键
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
*/
public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}


/**
* 将list放入缓存
*
* @param key 键
* @param value 值
*/
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}


/**
* 将list放入缓存
* @param key 键
* @param value 值
* @param time 时间(秒)
*/
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0)
expire(key, time);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}

}


/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}

}


/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0)
expire(key, time);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}


/**
* 根据索引修改list中的某条数据
*
* @param key 键
* @param index 索引
* @param value 值
* @return
*/

public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}


/**
* 移除N个值为value
*
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/

public long lRemove(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
}


```

**测试:**

```java
@Autowired
@Qualifier("redisTemplate") //存在多个redisTemplate 所以用@Qualifier("redisTemplate") 进行指定
private RedisTemplate redisTemplate;
@Autowired
private RedisUtil redisUtil;

@Test
public void test1(){
redisUtil.set("name", "kuangshen");
System.out.println(redisUtil.get("name"));
}

```

![image-20210513212330582](https://gitee.com/doudoutj111/tj/raw/master/img/image-20210513212330582.png)

B站学习网址:[【狂神说Java】Redis最新超详细版教程通俗易懂_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili](https://www.bilibili.com/video/BV1S54y1R7SB)

posted @ 2021-05-13 21:30  豆豆tj  阅读(99)  评论(0)    收藏  举报