Spring 采用純注解使用 RedisTemplate


我在前面的博客中介紹過采用 Jedis 操作 Redis,今天准備介紹 Spring 使用 RedisTemplate 操作 Redis。

Jedis 和 RedisTemplate 兩者之間的區別在於:Jedis 是 Redis 官方推薦的面向 Java 操作 Redis 的客戶端開發 Jar 包,而 RedisTemplate 是 Spring 框架對 Jedis API 的進行了高度封裝(也就是說 RedisTemplate 底層是通過 Jedis 來實現的)。RedisTemplate 能夠支持連接池自動管理,使用起來更加方便,實際上在大部分開發場景中,使用 RedisTemplate 會更多一些。

本篇博客的 Demo 基於之前 Jedis 操作 Redis 的 Demo 代碼進行簡單改造,實現 RedisTemplate 對 Redis 的操作,在博客最后會提供 Demo 源代碼。有關 RedisTemplate 的詳細內容,請查看 Spring 官網:https://spring.io/projects/spring-data-redis


一、搭建工程

新建一個 maven 項目,導入相關 jar 包,有關 Redis 相關的 jar 包不是最新的 jar 包,其它 jar 包都是最新的,內容如下:

有關具體的 jar 包地址,可以在 https://mvnrepository.com 上進行查詢。

<dependencies>
    <!--Spring 相關 jar 包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.17</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.3.17</version>
    </dependency>

    <!--單元測試 jar 包-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
    </dependency>

    <!--操作 Redis 的相關 jar 包-->
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
        <version>2.0.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.9.0</version>
    </dependency>

    <!--
    日志相關 jar 包,主要是上面的 Redis 相關的 jar 包,在運行時需要日志的 jar 包。
    日志的 jar 包也可以不導入,只不過運行過程中控制台總是有紅色提示,看着心煩。
    -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.21</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
</dependencies>

注意:本博客的 Demo 中有關 Redis 相關的 jar 包,不是導入最新的,使用的是經過測試無誤的穩定版本。另外 slf4j 和 log4j 相關的日志 jar 包,是 Redis 相關的 jar 所需要的,如果不導入的話,控制台上總是打印出相關的紅色提示信息,看着比較心煩。

配置好引用的 jar 包后,打開右側的 Maven 窗口,刷新一下,這樣 Maven 會自動下載所需的 jar 包文件。

搭建好的項目工程整體目錄比較簡單,具體如下圖所示:

image

項目工程結構簡單介紹:

com.jobs.config 包下存儲的是 Spring 相關的配置文件
resources 目錄下存儲的是相關的配置文件

test 目錄下的文件介紹:
com.jobs.RedisTest 類是專門用來編寫 junit 單元測試方法,用來測試操作 Redis 的方法


二、配置相關

resources 目錄下 redis.properties 是連接 Redis 的相關配置文件,log4j.properties 是日志相關的配置文件,內容分別如下:

redis.host=localhost
redis.port=6379

# 如果你的 redis 設置了密碼的話,可以使用密碼配置
# redis.password=123456

redis.maxActive=10
redis.maxIdle=5
redis.minIdle=1
redis.maxWait=3000
log4j.rootLogger=WARN, stdout

# 如果你既要控制台打印日志,也要文件記錄日志的話,可以使用下面這行配置
# log4j.rootLogger=WARN, stdout, logfile

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

RedisConfig 類主要實現的功能是讀取 Redis 配置信息,創建 RedisTemplate 對象並將其裝載到 Spring 容器中:

package com.jobs.config;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
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.PropertySource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
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.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPool;

@PropertySource("redis.properties")
public class RedisConfig {

    @Value("${redis.host}")
    private String host;
    @Value("${redis.port}")
    private Integer port;

    //@Value("${redis.password}")
    //private String password;

    @Value("${redis.maxActive}")
    private Integer maxActive;
    @Value("${redis.minIdle}")
    private Integer minIdle;
    @Value("${redis.maxIdle}")
    private Integer maxIdle;
    @Value("${redis.maxWait}")
    private Integer maxWait;

    //獲取RedisTemplate
    @Bean
    public RedisTemplate getRedisTemplate(
            @Autowired RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        //設置 Redis 生成的key的序列化器,這個很重要
        //RedisTemplate 默認使用 jdk 序列化器,會出現 Redis 的 key 保存成亂碼的情況
        //一般情況下 Redis 的 key 都使用字符串,
        //為了保障在任何情況下使用正常,最好使用 StringRedisSerializer 對 key 進行序列化
        RedisSerializer stringSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setHashKeySerializer(stringSerializer);
        return redisTemplate;
    }

    //獲取 Redis 連接工廠
    @Bean
    public RedisConnectionFactory getRedisConnectionFactory(
            @Autowired RedisStandaloneConfiguration redisStandaloneConfiguration,
            @Autowired GenericObjectPoolConfig genericObjectPoolConfig) {
        JedisClientConfiguration.JedisPoolingClientConfigurationBuilder builder
                = (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder)
                   JedisClientConfiguration.builder();
        builder.poolConfig(genericObjectPoolConfig);
        JedisConnectionFactory jedisConnectionFactory =
                new JedisConnectionFactory(redisStandaloneConfiguration, builder.build());
        return jedisConnectionFactory;
    }

    //獲取 Spring 提供的 Redis 連接池信息
    @Bean
    public GenericObjectPoolConfig getGenericObjectPoolConfig() {
        GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
        genericObjectPoolConfig.setMaxTotal(maxActive);
        genericObjectPoolConfig.setMinIdle(minIdle);
        genericObjectPoolConfig.setMaxIdle(maxIdle);
        genericObjectPoolConfig.setMaxWaitMillis(maxWait);
        return genericObjectPoolConfig;
    }

    //獲取 Redis 配置對象
    @Bean
    public RedisStandaloneConfiguration getRedisStandaloneConfiguration() {
        RedisStandaloneConfiguration redisStandaloneConfiguration =
            new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName(host);
        redisStandaloneConfiguration.setPort(port);
        //redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
        return redisStandaloneConfiguration;
    }
}

下面列出 Spring 的啟動類配置類 SpringConfig 的詳細內容:

package com.jobs.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@ComponentScan("com.jobs")
@Import(RedisConfig.class)
public class SpringConfig {
}

三、使用 RedisTemplate 操作 Redis

我們編寫一個單元測試類 RedisTest 來演示 RedisTemplate 操作 Redis 的常見數據類型:

package com.jobs;

import com.jobs.config.SpringConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class RedisTest {

    @Autowired
    private RedisTemplate redisTemplate;

    //測試字符串 String 數據類型
    @Test
    public void testString() {

        //設置
        redisTemplate.opsForValue().set("name", "候胖胖");
        redisTemplate.opsForValue().set("age", "40");

        //獲取
        String name = redisTemplate.opsForValue().get("name").toString();
        String age = redisTemplate.opsForValue().get("age").toString();

        System.out.println("name:" + name + ",age:" + age);
    }

    //測試列表 List 數據類型
    @Test
    public void testList() {

        //redis 的 list 可以作為隊列使用
        //從列表右邊添加數據
        redisTemplate.opsForList().rightPush("fat", "任肥肥");
        redisTemplate.opsForList().rightPush("fat", "侯胖胖");
        redisTemplate.opsForList().rightPush("fat", "李墩墩");

        //獲取列表的容量大小
        long fatCount = redisTemplate.opsForList().size("fat");
        System.out.println("列表數量:" + fatCount);

        //從左側逐個取數據
        for (int i = 0; i < fatCount; i++) {
            String fatMan = redisTemplate.opsForList().leftPop("fat").toString();
            System.out.println(fatMan);
        }
    }

    //測試散列 Hash 數據類型
    @Test
    public void testHash() {

        //redis 的 hash 比較適合存儲對象數據
        Map<String, String> user1 = new HashMap<>();
        user1.put("name", "侯胖胖");
        user1.put("age", "40");
        user1.put("kg", "80");

        Map<String, String> user2 = new HashMap<>();
        user2.put("name", "任肥肥");
        user2.put("age", "38");
        user2.put("kg", "90");

        redisTemplate.opsForHash().putAll("user1", user1);
        redisTemplate.opsForHash().putAll("user2", user2);

        //修改第一個用戶的年齡
        redisTemplate.opsForHash().put("user1", "age", "45");
        //修改第二個用戶的體重
        redisTemplate.opsForHash().put("user2", "kg", "100");

        //獲取兩個對象的屬性值
        Map<String, String> user111 = redisTemplate.opsForHash().entries("user1");
        Map<String, String> user222 = redisTemplate.opsForHash().entries("user2");
        System.out.println(user111);
        System.out.println(user222);
    }

    //測試集合 Set 數據類型
    @Test
    public void testSet() {

        //redis 的 set 跟 java 的 set 使用方式一樣,重復的元素只保留一個
        redisTemplate.opsForSet().add("aaa", "a", "b", "c", "x", "y", "z", "a", "x");
        redisTemplate.opsForSet().add("bbb", "b", "c", "d", "e", "f", "y", "b", "e");

        //獲取交集
        Set<String> sinter = redisTemplate.opsForSet().intersect("aaa", "bbb");
        System.out.println("交集:" + sinter);

        //獲取並集
        Set<String> sunion = redisTemplate.opsForSet().union("aaa", "bbb");
        System.out.println("並集:" + sunion);

        //獲取 aaa 相對於 bbb 的差集(存在於 aaa 但不存在與 bbb 的元素)
        Set<String> sdiff = redisTemplate.opsForSet().difference("aaa", "bbb");
        System.out.println("aaa 相對於 bbb 的差集:" + sdiff);
    }

    //測試有序集合 Sorted Set (ZSet) 數據類型
    @Test
    public void testZset() {

        //redis 的 zSet 比較適合做排行榜

        //粉絲投票
        redisTemplate.opsForZSet().add("vote", "侯胖胖", 10d);
        redisTemplate.opsForZSet().add("vote", "李墩墩", 7d);
        redisTemplate.opsForZSet().add("vote", "任肥肥", 6d);
        redisTemplate.opsForZSet().add("vote", "喬豆豆", 12d);
        redisTemplate.opsForZSet().add("vote", "楊重重", 8d);

        //修改任肥肥的投票數
        redisTemplate.opsForZSet().add("vote", "任肥肥", 9d);

        //zSet 默認是按照分值的升序排列
        Set<String> vote1 = redisTemplate.opsForZSet().range("vote", 0, -1);
        System.out.println("投票數量升序排列:" + vote1);

        //獲取粉絲投票數量最多的前三個人
        Set<String> vote2 = redisTemplate.opsForZSet().reverseRange("vote", 0, 2);
        System.out.println("投票數量倒序前 3 個人:" + vote2);
    }
}


到此為止,已經快速搭建和演示了 Spring 采用純注解配置和使用 RedisTemplate 操作 Redis 常見數據類型的 Demo ,整體來說還是非常簡單的。更多 RedisTemplate 的使用方式,請參考 Spring 官網。

本博客的 Demo 源代碼為:https://files.cnblogs.com/files/blogs/699532/Spring_RedisTemplate.zip




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM