Spring Data 操作 Redis

前言

安裝 Redis

首先確認你的 Redis 服務已經啓動了。

這裏我在客戶端設置密碼爲 root。若不輸入密碼,是不能進行操作的,使用 auth root之後就能進行操作了。

具體操作請參考:https://www.jianshu.com/p/0b03a3e05e1d

注意,我這裏的操作是沒有使用 auth 的。

redis 127.0.0.1:6379> config set requirepass root
OK
redis 127.0.0.1:6379> get *
(error) ERR operation not permitted
redis 127.0.0.1:6379> auth root
OK
redis 127.0.0.1:6379> get *
(nil)
redis 127.0.0.1:6379>

回顧一下Redis的存儲數據類型

結構類型 結構存儲的值 結構的讀寫能力
String 可以是字符串、整數或者浮點數 對整個字符串或者字符串的其中一部分執行操作;對象和浮點數執行自增(increment)或者自減(decrement)
List 一個鏈表,鏈表上的每個節點都包含了一個字符串 從鏈表的兩端推入或者彈出元素;根據偏移量對鏈表進行修剪(trim);讀取單個或者多個元素;根據值來查找或者移除元素
Set 包含字符串的無序收集器(unorderedcollection),並且被包含的每個字符串都是獨一無二的、各不相同 添加、獲取、移除單個元素;檢查一個元素是否存在於某個集合中;計算交集、並集、差集;從集合裏賣弄隨機獲取元素
Hash 包含鍵值對的無序散列表 添加、獲取、移除單個鍵值對;獲取所有鍵值對
Zset 字符串成員(member)與浮點數分值(score)之間的有序映射,元素的排列順序由分值的大小決定 添加、獲取、刪除單個元素;根據分值範圍(range)或者成員來獲取

創建項目

然後在 idea 中創建一個 SpringBoot 項目,選擇NoSQL組件。

在這裏插入圖片描述

項目內容

在這裏插入圖片描述

resources 中

這個裏邊本來是要配置信息的,可本案例中使用代碼配置的方式。因此,這裏的配置信息就沒寫。

pom.xml 文件

本案例使用了 jedis 連接的方式,因爲 SpringData2.x中默認使用的是其他的連接方式,因此需要將其默認配置排除掉。再加入 jedis 的依賴,而 jedis 的依賴又需要 commons 這個依賴,所以這裏一併引入。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.feng</groupId>
    <artifactId>springdata-redis</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springdata-redis</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>redis.clients</groupId>
                    <artifactId>jedis</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

RedisConfig

package org.feng.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

/**
 * Redis 配置類
 */
@Configuration
public class RedisConfig {

    /**
     * 創建JedisPoolConfig對象,在該對象中完成一些連接池配置
     */
    @Bean
    public JedisPoolConfig jedisPoolConfig () {
        JedisPoolConfig config = new JedisPoolConfig();
        // 配置最大空閒數
        config.setMaxIdle(10);
        // 配置最小空閒數
        config.setMinIdle(5);
        // 配置最大連接數
        config.setMaxTotal(20);
        return config;
    }


    @Bean
    public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory jedisConnectionFactory){
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(jedisConnectionFactory);

        // 設置 key 的序列化方式爲 String序列化器
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        return redisTemplate;
    }

    @Autowired
    public JedisConnectionFactory jedisConnectionFactory (JedisPoolConfig jedisPoolConfig) {
        //單機版jedis
        RedisStandaloneConfiguration redisStandaloneConfiguration =
                new RedisStandaloneConfiguration();
        //設置redis服務器的host或者ip地址
        redisStandaloneConfiguration.setHostName("localhost");
        //設置redis的服務的端口號
        redisStandaloneConfiguration.setPort(6379);
        //設置默認使用的數據庫
        redisStandaloneConfiguration.setDatabase(0);
        //設置密碼
        // redisStandaloneConfiguration.setPassword("root");

        //獲得默認的連接池構造器(怎麼設計的,爲什麼不抽象出單獨類,供用戶使用呢)
        JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcb =
                (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder)JedisClientConfiguration.builder();
        //指定jedisPoolConifig來修改默認的連接池構造器(真麻煩,濫用設計模式!)
        jpcb.poolConfig(jedisPoolConfig);
        //通過構造器來構造jedis客戶端配置
        JedisClientConfiguration jedisClientConfiguration = jpcb.build();
        //單機配置 + 客戶端配置 = jedis連接工廠
        return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
    }
}

RedisUtil

package org.feng.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.Arrays;
import java.util.List;

/**
 * RedisTemplate 的封裝類
 */
@Component
public class RedisUtil {
    private final RedisTemplate<String, Object> redisTemplate;

    @Autowired
    public RedisUtil(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 判斷redis中是否有 key
     * @param key 目標key
     * @return 存在時返回true
     */
    public boolean hasKey(String key){
        Boolean hasKey = redisTemplate.hasKey(key);
        if(hasKey != null){
            return hasKey;
        }
        return false;
    }

    /**
     * 存儲 set
     * @param key 鍵
     * @param value 值
     * @return 存儲成功返回 true
     */
    public boolean set(String key, Object value){
        boolean flag = false;
        try{
            redisTemplate.opsForValue().set(key, value);
            flag = true;
        }catch (Exception e){
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 更新緩存
     * @return 更新成功時返回 true
     */
    public boolean getAndSet(String key, Object value){
        boolean flag = false;
        try {
            redisTemplate.opsForValue().getAndSet(key, value);
            flag = true;
        } catch (Exception e){
            e.printStackTrace();
        }

        return flag;
    }

    /**
     * 刪除
     * @param key
     * @return
     */
    public boolean delete(String key){
        Boolean delete = false;
        try{
            delete = redisTemplate.delete(key);
        } catch (Exception e){
            e.printStackTrace();
        }
        return delete;
    }

    /**
     * 存儲 set 並設置超時時長
     * @param key 鍵
     * @param value 值
     * @param timeout 超時時間(超過該時間,redis 會自動刪除 key)
     */
    public void setWithTime(String key, Object value, Duration timeout){
        redisTemplate.opsForValue().set(key, value, timeout);
    }

    /**
     * 獲取 key 對應的值
     * @param key 鍵
     * @return value
     */
    public Object get(String key){
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 查詢多個結果:傳入多個key即可
     * @param key 鍵
     * @return 多個 value
     */
    public List<Object> getList(String...key){
        return redisTemplate.opsForValue().multiGet(Arrays.asList(key));
    }


    /**
     * 獲取 redisTemplate 對象
     * @return RedisTemplate 實例
     */
    public RedisTemplate<String, Object> getRedisTemplate(){
        return redisTemplate;
    }
}

測試

package org.feng;

import org.feng.util.RedisUtil;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.time.Duration;
import java.time.LocalDate;

@SpringBootTest
class SpringdataRedisApplicationTests {

    @Autowired
    private RedisUtil redisUtil;

    @Test
    void contextLoads() throws InterruptedException {
        String key1 = "first";
        String value1 = "1234567";
        redisUtil.setWithTime(key1, value1, Duration.ofSeconds(3));

        Assert.isTrue(redisUtil.hasKey(key1), key1 + " is must exist !");

        // 自定義對象
        Person value2  = new Person();
        value2.setName("小鳳");
        value2.setPassword("123445");
        value2.setAge(10);
        value2.setRegisterDay(LocalDate.of(2020,2, 21));
        String key2 = "second";
        redisUtil.set(key2, value2);
        Assert.isTrue(redisUtil.hasKey(key2), key2 + " is must exist !");

        // 輸出結果
        redisUtil.getList(key1, key2).forEach(System.out::println);
        // 3s 之後
        Thread.sleep(3000);
        Assert.isTrue(!redisUtil.hasKey(key1), key1 + " is must not exist !");
    }


    private static class Person implements Serializable {

        private static final long serialVersionUID = 7813755876899907524L;

        private String name;
        private String password;
        private Integer age;
        private LocalDate registerDay;

        public Person() {
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) {
            this.age = age;
        }

        public LocalDate getRegisterDay() {
            return registerDay;
        }

        public void setRegisterDay(LocalDate registerDay) {
            this.registerDay = registerDay;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", password='" + password + '\'' +
                    ", age=" + age +
                    ", registerDay=" + registerDay +
                    '}';
        }
    }
}

測試結果

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章