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 包文件。
搭建好的项目工程整体目录比较简单,具体如下图所示:
项目工程结构简单介绍:
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