zoukankan      html  css  js  c++  java
  • 【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",...)
  • 相关阅读:
    2019 上海网络赛 J stone name (01背包)
    CodeForces
    2019 年百度之星·程序设计大赛
    CodeForces
    POJ 3728 The merchant (树形DP+LCA)
    HihoCoder
    HihoCoder 1055 刷油漆 (树上背包)
    HI3518E平台ISP调试环境搭建
    有用的调节
    【HI3520DV200】sample
  • 原文地址:https://www.cnblogs.com/h--d/p/14855872.html
Copyright © 2011-2022 走看看