【SpringBoot】SpringBoot 整合Redis

  Redis安装参考:【Redis】安装及简单使用

一、Redis整合

1、创建SpringBoot项目

  引入SpringBoot的redis启动器:

1 <!-- SpringBoot整合redis -->
2 <dependency>
3     <groupId>org.springframework.boot</groupId>
4     <artifactId>spring-boot-starter-data-redis</artifactId>
5 </dependency>

  查看依赖,SpringBoot默认使用的是Lettuce作为Redis客户端(可以自己修改引入Jedis作为Redis客户端)

  

  完整pom文件如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6 
 7     <groupId>com.test.redis</groupId>
 8     <artifactId>test-springboot-redis</artifactId>
 9     <version>1.0-SNAPSHOT</version>
10 
11     <parent>
12         <groupId>org.springframework.boot</groupId>
13         <artifactId>spring-boot-starter-parent</artifactId>
14         <version>2.2.5.RELEASE</version>
15     </parent>
16 
17     <properties>
18         <maven.compiler.source>8</maven.compiler.source>
19         <maven.compiler.target>8</maven.compiler.target>
20     </properties>
21 
22 
23     <dependencies>
24         <dependency>
25             <groupId>org.springframework.boot</groupId>
26             <artifactId>spring-boot-starter</artifactId>
27         </dependency>
28 
29         <!-- SpringBoot整合redis -->
30         <dependency>
31             <groupId>org.springframework.boot</groupId>
32             <artifactId>spring-boot-starter-data-redis</artifactId>
33         </dependency>
34 
35         <!-- Redis客户端lettuce 连接池依赖项 -->
36         <dependency>
37             <groupId>org.apache.commons</groupId>
38             <artifactId>commons-pool2</artifactId>
39         </dependency>
40 
41         <!-- Json Jar包 -->
42         <dependency>
43             <groupId>com.fasterxml.jackson.core</groupId>
44             <artifactId>jackson-databind</artifactId>
45             <version>2.10.2</version>
46         </dependency>
47 
48         <dependency>
49             <groupId>org.springframework.boot</groupId>
50             <artifactId>spring-boot-starter-test</artifactId>
51             <scope>test</scope>
52         </dependency>
53 
54     </dependencies>
55 
56 </project>
View Code

2、application.yml配置redis连接地址

  redis单机配置

1 spring:
2   redis:
3     # 主机地址
4     host: 127.0.0.1
5     # 默认端口
6     port: 6379
7     # 密码
8     password:123456

  redis哨兵模式配置

 1 spring:
 2   redis:
 3     database: 0 # Redis数据库索引(默认为0)
 4     #host: 192.168.1.8
 5     #port: 6379
 6     password: 123456
 7     sentinel:
 8       master: mymaster # Redis配置的 master名称
 9       nodes:
10       - 192.168.1.8:9001
11       - 192.168.1.8:9002
12       - 192.168.1.8:9003
13       # 或者
14       # 192.168.1.8:9001,192.168.1.8:9002,192.168.1.8:9003
View Code

  redis集群模式配置

 1 spring:
 2   redis:
 3     database: 0 # Redis数据库索引(默认为0)
 4     #host: 192.168.1.8
 5     #port: 6379
 6     password: 123456
 7     cluster:
 8       nodes:
 9       - 192.168.1.8:9001
10       - 192.168.1.8:9002
11       - 192.168.1.8:9003
12       # 或者
13       # 192.168.1.8:9001,192.168.1.8:9002,192.168.1.8:9003
View Code

  redis连接池配置

 1 spring:
 2   redis:
 3     database: 0
 4     timeout: 3000
 5     password: 123456
 6     # 单节点模式
 7     host: 127.0.0.1
 8     port: 6379
 9 
10     # 连接池,默认使用lettuce客户端redis连接池
11     lettuce:
12       pool:
13         max-idle: 8 # 连接池中的最大空闲连接数
14         min-idle: 0 # 连接池中的最小空闲连接数
15           max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
16           max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
17 
18 #    jedis:
19 #      pool:
20 #        max-idle: 8 # 连接池中的最大空闲连接数
21 #        min-idle: 0 # 连接池中的最小空闲连接数
22 #          max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
23 #          max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
View Code 

3、Redis自动配置原理

  由于SpringBoot引入了 RedisAutoConfiguration 类,此类事redis的自动配置来,可以看到它自动注册了 RedisTemplateStringRedisTemplate,2个类

  所以在SpringBoot项目中就可以使用 redisTemplate和stringRedisTemplate 2个对象来操作Redis

 1 @Configuration(proxyBeanMethods = false)
 2 @ConditionalOnClass(RedisOperations.class)
 3 @EnableConfigurationProperties(RedisProperties.class)
 4 @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
 5 public class RedisAutoConfiguration {
 6 
 7     @Bean
 8     @ConditionalOnMissingBean(name = "redisTemplate")
 9     public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
10             throws UnknownHostException {
11         RedisTemplate<Object, Object> template = new RedisTemplate<>();
12         template.setConnectionFactory(redisConnectionFactory);
13         return template;
14     }
15 
16     @Bean
17     @ConditionalOnMissingBean
18     public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
19             throws UnknownHostException {
20         StringRedisTemplate template = new StringRedisTemplate();
21         template.setConnectionFactory(redisConnectionFactory);
22         return template;
23     }
24 
25 }

  创建2个模版对象, 需要 RedisConnectionFactory 连接工厂对象, 这个对象是在 RedisAutoConfiguration 上 @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class }) 的 LettuceConnectionConfiguration 配置类中导入的, 查看连接配置类

 1 @Configuration(proxyBeanMethods = false)
 2 @ConditionalOnClass(RedisClient.class)
 3 class LettuceConnectionConfiguration extends RedisConnectionConfiguration {
 4 
 5     @Bean
 6     @ConditionalOnMissingBean(RedisConnectionFactory.class)
 7     LettuceConnectionFactory redisConnectionFactory(
 8             ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
 9             ClientResources clientResources) throws UnknownHostException {
10         LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(builderCustomizers, clientResources,
11                 getProperties().getLettuce().getPool());
12         return createLettuceConnectionFactory(clientConfig);
13     }
14 
15     private LettuceConnectionFactory createLettuceConnectionFactory(LettuceClientConfiguration clientConfiguration) {
16         if (getSentinelConfig() != null) {
17             return new LettuceConnectionFactory(getSentinelConfig(), clientConfiguration);
18         }
19         if (getClusterConfiguration() != null) {
20             return new LettuceConnectionFactory(getClusterConfiguration(), clientConfiguration);
21         }
22         return new LettuceConnectionFactory(getStandaloneConfig(), clientConfiguration);
23     }
24     ......
25 }

  

 

 

4、使用redisTemplate和stringRedisTemplate操作Redis

  编写测试类

 1 package com.test.redis;
 2 
 3 import com.test.redis.entity.Employee;
 4 import org.junit.Test;
 5 import org.junit.runner.RunWith;
 6 import org.springframework.beans.factory.annotation.Autowired;
 7 import org.springframework.boot.test.context.SpringBootTest;
 8 import org.springframework.context.ApplicationContext;
 9 import org.springframework.data.redis.core.RedisTemplate;
10 import org.springframework.data.redis.core.StringRedisTemplate;
11 import org.springframework.test.context.junit4.SpringRunner;
12 
13 import java.util.HashMap;
14 import java.util.Map;
15 
16 @RunWith(SpringRunner.class)
17 @SpringBootTest
18 public class TestApplication {
19 
20     @Autowired
21     ApplicationContext context;
22 
23     // 处理Object类型的key和value数据
24     @Autowired
25     RedisTemplate redisTemplate;
26 
27     // 处理String类型的key和value数据
28     @Autowired
29     StringRedisTemplate stringRedisTemplate;
30 
31     // 使用 redisTemplate 处理对象
32     @Test
33     public void terst1(){
34         Employee emp = new Employee(1, "小明");
35         redisTemplate.opsForValue().set("emp", emp);
36         Employee emp2 = (Employee) redisTemplate.opsForValue().get("emp");
37         System.out.println(emp2);
38     }
39 
40     // 使用 stringRedisTemplate 处理字符串
41     @Test
42     public void test2(){
43         stringRedisTemplate.opsForValue().set("msg", "hello world");
44         String msg = stringRedisTemplate.opsForValue().get("msg");
45         System.out.println(msg);
46     }
47 }

  在redis服务器上查看

  

  测试方法test01中,

  保存对象时,会对key进行序列化, "emp" ==> "xacxedx00x05tx00x03emp"

  而且也会对value(Employee对象)序列化,所以Employee类必须实现Serializable接口,否则会报错,下图为emp对象保存在redis中的数据。

5、将数据以json的方式保存

  a、自己将对象转为json(此种就时将对象转成json字符串)

  b、redisTmplate默认规则

  分析redisTmplate默认规则:在RedisAutoConfiguration类中,RedisTemplate是通过简单的new出来的,其中defaultSerializer默认序列化器是使用JDK自带的,查看RedisTemplate类

 1 public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
 2     ...
 3 
 4     public RedisTemplate() {}
 5 
 6     @Override
 7     public void afterPropertiesSet() {
 8 
 9         super.afterPropertiesSet();
10         boolean defaultUsed = false;
11 
12         if (defaultSerializer == null) {
13             // 使用jdk自带的解析器
14             defaultSerializer = new JdkSerializationRedisSerializer(
15                     classLoader != null ? classLoader : this.getClass().getClassLoader());
16         }
17 
18         if (enableDefaultSerializer) {
19 
20             if (keySerializer == null) {
21                 // key序列化器
22                 keySerializer = defaultSerializer;
23                 defaultUsed = true;
24             }
25             if (valueSerializer == null) {
26                 // value序列化器
27                 valueSerializer = defaultSerializer;
28                 defaultUsed = true;
29             }
30             if (hashKeySerializer == null) {
31                 hashKeySerializer = defaultSerializer;
32                 defaultUsed = true;
33             }
34             if (hashValueSerializer == null) {
35                 hashValueSerializer = defaultSerializer;
36                 defaultUsed = true;
37             }
38         }
39 
40         ...
41     }
42     ...
43 }

  查看RedisTemplate类,使用的序列化器是从RedisSerializer这个类中得到的

 1 public class StringRedisTemplate extends RedisTemplate<String, String> {
 2 
 3     
 4     public StringRedisTemplate() {
 5         // 设置序列化器
 6         setKeySerializer(RedisSerializer.string());
 7         setValueSerializer(RedisSerializer.string());
 8         setHashKeySerializer(RedisSerializer.string());
 9         setHashValueSerializer(RedisSerializer.string());
10     }
11     ......
12 }

  查看RedisSerializer类-Redis序列化类,这个使用引入spring-boot-starter-data-redis的jar包提供的

 1 // Redis序列化器
 2 public interface RedisSerializer<T> {
 3 
 4     static RedisSerializer<Object> java() {
 5         return java(null);
 6     }
 7 
 8     static RedisSerializer<Object> java(@Nullable ClassLoader classLoader) {
 9         return new JdkSerializationRedisSerializer(classLoader);
10     }
11     // json序列化器,使用ObjectMapper对象处理json,需要引入依赖
12     static RedisSerializer<Object> json() {
13         return new GenericJackson2JsonRedisSerializer();
14     }
15     // string序列化器
16     static RedisSerializer<String> string() {
17         return StringRedisSerializer.UTF_8;
18     }
19 
20     static RedisSerializer<byte[]> byteArray() {
21         return ByteArrayRedisSerializer.INSTANCE;
22     }
23 }

自己注入一个redisTemplate

  如果想将数据以json的方式保存在redis中,需要自己注入一个redisTemplate,且此redisTemplate使用json的序列化器。

  1、修改默认序列化器

 1     @Bean
 2     public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
 3             throws UnknownHostException {
 4         RedisTemplate<Object, Object> template = new RedisTemplate<>();
 5         template.setConnectionFactory(redisConnectionFactory);
 6 
 7         // 设置默认的序列化器,修改默认的序列化器,会对所有的key和value有效
 8         template.setDefaultSerializer(RedisSerializer.json());
 9 //        // 设置key的序列化器
10 //        template.setKeySerializer(RedisSerializer.string());
11 //        // 设置value的序列化器
12 //        template.setValueSerializer(RedisSerializer.json());
13 
14         return template;
15     }

  结果: 值转化成json了,当是key包含了冒号,而普通的key没有包含

  

  2、key使用字符串序列化器,值使用json序列化器

 1     @Bean
 2     public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
 3             throws UnknownHostException {
 4         RedisTemplate<Object, Object> template = new RedisTemplate<>();
 5         template.setConnectionFactory(redisConnectionFactory);
 6 
 7         // 设置默认的序列化器,修改默认的序列化器,会对所有的key和value有效
 8 //        template.setDefaultSerializer(RedisSerializer.json());
 9         // 设置key的序列化器为字符串序列化器
10         template.setKeySerializer(RedisSerializer.string());
11         template.setHashKeySerializer(RedisSerializer.string());
12         
13         // 设置value的序列化器为json序列化器
14         template.setValueSerializer(RedisSerializer.json());
15         template.setHashValueSerializer(RedisSerializer.json());
16 
17         return template;
18     }

  结果: key与普通的key相同,值也为json格式

  

二、StringRedisTemplate与RedisTemplate操作

  spring 封装了 RedisTemplate 对象来进行对redis的各种操作,它支持所有的 redis 原生的 api。在RedisTemplate中提供了几个常用的接口方法的使用,分别是:
1 private ValueOperations<K, V> valueOps; 
2 private HashOperations<K, V> hashOps;
3 private ListOperations<K, V> listOps; 
4 private SetOperations<K, V> setOps; 
5 private ZSetOperations<K, V> zSetOps;

  RedisTemplate中定义了对5种数据结构操作

1 redisTemplate.opsForValue();  // 操作字符串
2 redisTemplate.opsForHash();  // 操作hash
3 redisTemplate.opsForList();  // 操作list
4 redisTemplate.opsForSet();   // 操作set
5 redisTemplate.opsForZSet();  // 操作有序set

  StringRedisTemplate继承自RedisTemplate,也一样拥有上面这些操作。

  StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。

  RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。

  Redis客户端命令对应的RedisTemplate中的方法列表:

String类型结构
Redis
RedisTemplate rt
set key value
rt.opsForValue().set("key","value")
get key
rt.opsForValue().get("key")
del key
rt.delete("key")
strlen key
rt.opsForValue().size("key")
getset key value
rt.opsForValue().getAndSet("key","value")
getrange key start end
rt.opsForValue().get("key",start,end)
append key value
rt.opsForValue().append("key","value")
   
Hash结构
hmset key field1 value1 field2 value2...
rt.opsForHash().putAll("key",map) //map是一个集合对象
hset key field value
rt.opsForHash().put("key","field","value")
hexists key field
rt.opsForHash().hasKey("key","field")
hgetall key
rt.opsForHash().entries("key")  //返回Map对象
hvals key
rt.opsForHash().values("key") //返回List对象
hkeys key
rt.opsForHash().keys("key") //返回List对象
hmget key field1 field2...
rt.opsForHash().multiGet("key",keyList)
hsetnx key field value
rt.opsForHash().putIfAbsent("key","field","value"
hdel key field1 field2
rt.opsForHash().delete("key","field1","field2")
hget key field
rt.opsForHash().get("key","field")
 
 
List结构
lpush list node1 node2 node3...
rt.opsForList().leftPush("list","node") 
rt.opsForList().leftPushAll("list",list) //list是集合对象
rpush list node1 node2 node3...
rt.opsForList().rightPush("list","node") 
rt.opsForList().rightPushAll("list",list) //list是集合对象
lindex key index
rt.opsForList().index("list", index)
llen key
rt.opsForList().size("key")
lpop key
rt.opsForList().leftPop("key")
rpop key
rt.opsForList().rightPop("key")
lpushx list node
rt.opsForList().leftPushIfPresent("list","node")
rpushx list node
rt.opsForList().rightPushIfPresent("list","node")
lrange list start end
rt.opsForList().range("list",start,end)
lrem list count value
rt.opsForList().remove("list",count,"value")
lset key index value
rt.opsForList().set("list",index,"value")
   
Set结构
sadd key member1 member2...
rt.boundSetOps("key").add("member1","member2",...)
rt.opsForSet().add("key", set) //set是一个集合对象
scard key
rt.opsForSet().size("key")
sidff key1 key2
rt.opsForSet().difference("key1","key2") //返回一个集合对象
sinter key1 key2
rt.opsForSet().intersect("key1","key2")//同上
sunion key1 key2
rt.opsForSet().union("key1","key2")//同上
sdiffstore des key1 key2
rt.opsForSet().differenceAndStore("key1","key2","des")
sinter des key1 key2
rt.opsForSet().intersectAndStore("key1","key2","des")
sunionstore des key1 key2
rt.opsForSet().unionAndStore("key1","key2","des")
sismember key member
rt.opsForSet().isMember("key","member")
smembers key
rt.opsForSet().members("key")
spop key
rt.opsForSet().pop("key")
srandmember key count
rt.opsForSet().randomMember("key",count)
srem key member1 member2...
rt.opsForSet().remove("key","member1","member2",...)
原文地址:https://www.cnblogs.com/h--d/p/14855872.html