1. 程式人生 > 實用技巧 >Redis_整合SpringBoot

Redis_整合SpringBoot

SpringBoot整合Redis

目錄

1. 說明

  • 在SpringBoot 2.X 之後, 原來的 Jedis 被替換為了 lettuce

    • Jedis: 採用的是直連, 多個執行緒操作的話, 是不安全的, 如果想要避免不安全, 使用 Jedis pool 連線池, 更像BIO模式
    • Lettuce: 採用 Netty, 例項可以在多個執行緒中共享, 不存線上程不安全的情況! 可以減少執行緒資料了, 更像NIO模式
  • 原始碼分析

  • RedisAutoConfiguration

package org.springframework.boot.autoconfigure.data.redis;

import java.net.UnknownHostException;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {

   @Bean
    //如果redisTemplate存在, 則預設的模板不生效 ==> 我們可以自己定義一個 來替換這個預設的
   @ConditionalOnMissingBean(name = "redisTemplate")
   public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
         throws UnknownHostException {
      //預設的 RedisTemplate 沒有過多的設定, redis 物件都是需要序列化
      //兩個泛型都是 Object, 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;
   }

}

2. 整合測試

1. 匯入依賴

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

如果要使用連線池, 要匯入如下依賴

<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-pool2</artifactId>
</dependency>

2. 配置連線

# 配置Redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
# SpringBoot 2.X 版本使用Lettuce, 因此不要配置Jedis!
spring.redis.lettuce.pool.max-active=8

3. 測試

package com.wang.redis02srpingboot;

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 Redis02SrpingbootApplicationTests {

   @Autowired
   private RedisTemplate redisTemplate;

   @Test
   void contextLoads() {
      //操作不同的資料型別
      //opsForValue 操作字串 類似 String, 其中Bitmap也在這個方法下面, 可以.setBit()方法
      //opsForList list
      //opsForSet set
      //opsForHash hashmap
      //opsForZset Zset
      //opsForGeo geo
      //opsForHyperLogLog hyperloglog
      /*
      redisTemplate.opsForValue().setBit("sign",0, true);
       */

      //除了基本的操作, 我們常用的方法都可以直接通過RedisTemplate來操作, 比如事務和基本的CRUD

      //獲取Redis的連線物件
      /*
      RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
      connection.flushAll();
       */
      redisTemplate.opsForValue().set("myKey", "我的RedisValue");
      System.out.println(redisTemplate.opsForValue().get("myKey"));
   }

}

這裡有幾點需要注意

  • String在opsForValue()下, 同時, BitMap也被放在了這個方法下面!

  • 用getConnectionFactory().getConnection()獲得連線物件, 可以對資料庫進行清理或者關閉

  • 要使用連線池, 除了SpringBoot匯入的幾個依賴, 我們還要匯入 commons-pool2 這個依賴, 因為Lettuce和Jedis都使用了這個技術進行連線池的實現!

  • 預設的序列化方式是利用JDK進行序列化, 會導致中文顯示的問題, 因此我們有必要自定義RedisTemplate

3. 自定義RedisTemplate

1. 關於序列化

可以看出, 沒有序列化直接傳遞物件會報錯

  • 正確的寫法為
@Test
void test() throws JsonProcessingException {
   //真實的開發一般使用JSON傳遞物件, 這裡用SpringBoot自帶的Jackson
   User user = new User("測試使用者", 3);
   String jsonUser = new ObjectMapper().writeValueAsString(user);
   redisTemplate.opsForValue().set("user", jsonUser);
   System.out.println(redisTemplate.opsForValue().get("user"));
}

輸出了JSON字串

  • 或者將實體類序列化, 這樣就可以輸出JAVA物件了
package com.wang.redis02srpingboot.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;

}

2. 自定義RedisTemplate

由於SpringBoot預設實現的RedisTemplate使用的是JDK的序列化, 我們想用自己的序列化方法就要自定義自己的RedisTemplate

package com.wang.redis02srpingboot.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
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;

import java.net.UnknownHostException;

//固定的模板
@Configuration
public class RedisConfig {

    //編寫我們自己的RedisTemplate
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) throws UnknownHostException {
        // 為了我們自己開發方便, 一般直接使用 <String, Object>
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        // 序列化配置
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        //配置所有的成員變數無需註解就可以完成序列化, 這裡的 PropertyAccessor 和 Visibility 都是列舉型別
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //指定序列化的型別, 原來的enableDefaultTyping方法過期了, 這裡主要指定第二個引數
        //NON_FINAL ==> 整個類,除final外的的屬性資訊都需要被序列化和反序列化
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
        //使配置的ObjectMapper生效
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        //配置具體的序列化方式
        //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生效
        template.afterPropertiesSet();

        return template;
    }
}

4. 編寫Redis工具類

1. 工具類

為了簡化操作, 我們封裝工具類

注意, 要把這個類託管到SpringBoot中!

package com.wang.redis02srpingboot.Utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtil {

    @Autowired
    @Qualifier("redisTemplate")
    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 可以傳一個或者多個值
     */
    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));
            }
        }
    }

    /**
     * 清除當前資料庫的快取
     */
    public void flushdb() {
        redisTemplate.getConnectionFactory()
                .getConnection()
                .flushDb();
    }

    /**
     * 清空全部資料庫
     */
    public void flushall() {
        redisTemplate.getConnectionFactory()
                .getConnection()
                .flushAll();
    }

    /**
     * 切換資料庫
     * @param dbindex   資料庫的編號
     */
    public void select(int dbindex) {
        redisTemplate.getConnectionFactory()
                .getConnection()
                .select(dbindex);
    }

    // ===================== 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
     * @return 值
     */

    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 設定一個或者多個map
     * @param key 鍵
     * @param map 對應多個鍵值
     * @return true 成功 false 失敗
     */
    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 設定一個或者多個map並設定時間
     * @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 hexists(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    /**
     * hash遞增 如果不存在,就會建立一個 並把新增後的值返回
     * @param key  鍵
     * @param item 項
     * @param by   要增加幾(大於0)
     * @return 274
     */
    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 sexists(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 sadd(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 sadd(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 scard(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除值為value的元素
     * @param key    鍵
     * @param values 值 可以是多個
     * @return 移除的個數
     */

    public long srem(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> lrange(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 llen(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 lindex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * rpush 將元素插入隊尾
     * @param key   鍵
     * @param value 值
     */
    public boolean rpush(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 將元素插入隊尾,並設定時間
     * @param key   鍵
     * @param value 值
     * @param time  時間(秒)
     */
    public boolean rpush(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;
        }

    }

    /**
     * 將元素插入隊尾
     * @param key   鍵
     * @param value 值, list型別
     */
    public boolean rpush(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 將元素插入隊尾,並設定時間
     * @param key   鍵
     * @param value 值
     * @param time  時間(秒)
     */
    public boolean rpush(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;
        }
    }

    /**
     * lpush 將元素插入隊頭
     * @param key   鍵
     * @param value 值
     */
    public boolean lpush(String key, Object value) {
        try {
            redisTemplate.opsForList().leftPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 將元素插入隊頭,並設定時
     * @param key   鍵
     * @param value 值
     * @param time  時間(秒)
     */
    public boolean lpush(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().leftPush(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 將元素插入隊頭
     * @param key   鍵
     * @param value 值, list型別
     */
    public boolean lpush(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().leftPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 將元素插入隊頭,並設定時間
     * @param key   鍵
     * @param value 值
     * @param time  時間(秒)
     */
    public boolean lpush(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().leftPushAll(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根據索引修改list中的某條資料
     * @param key   鍵
     * @param index 索引
     * @param value 值
     */

    public boolean lset(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 lrem(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    // ============================Zset=============================
    /**
     * 新增一個Zset
     * @param key   鍵
     * @param value 值
     * @param score 編號
     * @return      成功 true, 失敗false
     */
    public boolean zadd (String key, Object value, Double score) {
        try {
            redisTemplate.opsForZSet().add(key, value, score);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 批量新增Zset
     * @param key   鍵
     * @param map   value-score鍵值對
     * @return      新增的個數
     */
    public long zadd (String key, Map<Object, Double> map) {
        try {
            Set<ZSetOperations.TypedTuple<Object>> set = new HashSet<>();
            for (Map.Entry<Object, Double> entry : map.entrySet()) {
                DefaultTypedTuple defaultTypedTuple = new DefaultTypedTuple(entry.getKey(), entry.getValue());
                set.add(defaultTypedTuple);
            }
            Long count = redisTemplate.opsForZSet().add(key, set);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
}

2. 測試

package com.wang.redis02srpingboot;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wang.redis02srpingboot.Utils.RedisUtil;
import com.wang.redis02srpingboot.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.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class Redis02SrpingbootApplicationTests {

   @Autowired
   @Qualifier("redisTemplate")
   private RedisTemplate redisTemplate;

   @Autowired
   private RedisUtil redisUtil;

   @Test
   void contextLoads() {
      //操作不同的資料型別
      //opsForValue 操作字串 類似 String, 其中Bitmap也在這個方法下面, 可以.setBit()方法
      //opsForList list
      //opsForSet set
      //opsForHash hashmap
      //opsForZset Zset
      //opsForGeo geo
      //opsForHyperLogLog hyperloglog
      /*
      redisTemplate.opsForValue().setBit("sign",0, true);
       */

      //除了基本的操作, 我們常用的方法都可以直接通過RedisTemplate來操作, 比如事務和基本的CRUD

      //獲取Redis的連線物件
      /*
      RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
      connection.flushAll();
       */
      redisTemplate.opsForValue().set("myKey", "我的RedisValue");
      System.out.println(redisTemplate.opsForValue().get("myKey"));
   }

   @Test
   void test() throws JsonProcessingException {
      //真實的開發一般使用JSON傳遞物件, 這裡用SpringBoot自帶的Jackson
      User user = new User("測試使用者", 3);
      String jsonUser = new ObjectMapper().writeValueAsString(user);
      redisTemplate.opsForValue().set("user", jsonUser);
      System.out.println(redisTemplate.opsForValue().get("user"));
   }

   //利用我們自己封裝的工具類測試
   @Test
   void test1() {
      redisUtil.set("name", "測試使用者2");
      System.out.println(redisUtil.get("name"));
   }

}