我在前面的博客中介紹過采用 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 包文件。
搭建好的項目工程整體目錄比較簡單,具體如下圖所示:
項目工程結構簡單介紹:
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