我在前面的博客中介绍过采用 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 { }
我们编写一个单元测试类 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