开发者学堂课程【使用 Redis 消息队列完成秒杀过期订单处理 :SpringDataRedis 的介绍与基本操作】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/729/detail/13016
SpringDataRedis 的介绍与基本操作
内容介绍
一、整合 SpringData Redis 开发
二、SpringData Redis 的介绍
之前课程一直在 redis 提供的命令行下完成的一个测试操作,而在企业开发中往往是通过 java 代码的形式去操作 redis 服务器,所以接下来讲解目前较为流行的操作redis 的 API。
一、整合 SpringData Redis 开发
我们使用 redis 解决过期优惠券和红包等问题,并且在 java 环境中使用 redis 的消息通知。目前世面比较流行的 java 代码操作 redis 的 AIP 有:Jedis 和 RedisTemplate。
1.Jedis
Jedis 是 Redis 官方推出的一款面向 Java 的客户端,其中集成了 Rdies 中的大部分命令,提供了很多接口供 Java 语言调用,同时它的使用较为简单。
2.SpringData Redis
SpringData Redis 是 Spring 官方推出,可以算是 Spring 框架集成 Redis 操作的一个子框架,封装了 Redis 的很多命令,可以很方便的使用 Spring 操作 Redis 数据库,进行集成开发。同时由于现代企业开发中都使用 Spring 整合开发管理项目,所以在 API 的选择上我们推荐使用 Spring 提供的 SpringData Redis 来开发,因为其能够更好的与Spring 结合进行开发
二、SpringData Redis 的介绍
(官网概念图)
重点说明 Spring Data Redis 是 Spring 全家桶的一员,相当于 Spring 提供的一个子集或是子框架,重点是为了解决访问 Redis 服务器的一些操作,同时它也具有一些很好的特性,如:连接工厂,连接池的特性,操作起来的特性,同时支持 Pubsub 的模型。
1.特性:
- Connection package as low-level abstraction across multiple Redis drivers/connectors (Jedisand Lettuce. Support for JRedis and SRP is deprecated.)
- Exception translation to Spring's portable Data Access exception hierarchy for Redis driverexceptions
- RedisTemplate that provides a high level abstraction for performing various Redis operations,exception translation and serialization support
- Pubsub,support (such as a MessageListenerContainer for message-driven POJOs)
支持 pubsub 消息通知 - Redis Sentinel and Redis Cluster support
- JDK, String, JSON and Spring Object/XML mapping serializersJDK Collection implementations on top of Redis
- Atomic counter support classes
- Sorting and Pipelining functionality
- Dedicated support for SORT, SORT/GET pattern and returned bulk valuesRedis implementation for Spring 3.1 cache abstraction
- Automatic implementation of Repository interfaces including support for custom findermethods using @EnableRedisRepositories
- CDl support for repositories
Ø 总结
以上英文概念不过多介绍,总之只需知晓 Spring Data Redis 是 Spring 提供的一个子框架,用于操控 Redis 的,并且可以和 Spirng 的很好的结合到一起,同时操作起来十分简便就行。
2. 搭建环境
(1)maven 工程
在搭建 SpringData Redis 环境时,操作使用的 java 代码都是通过 mave工程统一管理的,所以在工程中右键->new->创建 Maven Project 工程即可。
创建后勾选,Create a simple project 创建一个简单的项目结构。
点击 Next 后,创建一个测试,给 Group id 输入 cn.itcast,Artifact id 输入 spring-data-redis-test,version 版本选择 0.01-SNAPSHOT,Packaging 选择 Jar,点击 finish 即可完成工程的创建。
工程创建完毕后,打开 pom.xml 文件,导入依赖的坐标。
(2)maven 工程坐标如下:
根据以下工程坐标导入相应依赖,同时注意-<finalName>的名称要和<artifactId>的名称一样。
我们之前设置的名称为 spring-data-redis-test 所以-<finalName>和<artifactId>对应也要更改为 spring-data-redis-test。将坐标导入之后。
①Spring data redis 相关依赖包
<!--spring data redis 相关坐标 beg -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</ artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactid>commons-pool2</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactid>spring-data-redis</artifactId>
<version>${springdataredis.version}</version>
</dependency>
<l-- spring data redis相关坐标end -->
<dependencies>
②Spring 相关依赖包,核心就是一些 org 组件
<!-- spring 相关坐标 beg -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<l-- spring 相关坐标 end -->
③日志 log 相关内容依赖包
<!--日志相关坐标 beg -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</ artifactId>
<version>${slf4j. version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<l--日志相关坐标 end -->
④单元测试相关内容依赖包
<l--单元测试相关坐标 beg -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
<l--单元测试相关坐标end -->
⑤单元测试相关内容依赖包
因为项目最后需要实现过期优惠卷的功能,所以还需要引入 druid 数据库连接池的依赖
<l-- druid 数据库连接池 beg -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</ artifactId>
<version>1.1.9</version>
</dependency>
<!-- druid 数据库连接池e nd -->
⑥mysql 数据库依赖包
而案例中使用的是mysql,所以还要导入 mysql 的数据库驱动依赖包。
<I-- mysql 驱动 beg-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<l-- mysql 驱动 end -->
⑦mybatis 依赖包
而持久层框架选择的是 mybatis 来做的,同时不管是 mybatis 还是 hibernate 原生 jdbc 的驱动都可以,在此使用mybatis 来做,所以导入 mybatis 的依赖包。
<l-- mybatis 核心包-->
<dependency>
<groupid>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
⑧mybatis 整合 spring
<l-- mybatis 整合 spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
⑨配置信息
<finalName>的名称要和<artifactId>的名称一样,其中<source>1.7</source>表示 jdk 的版本男士1.7。
<build>
<finalName>redis_test</finalName><pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
<showwarnings>true</showwarnings>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
(3)项目出现报错
当工程创建,同时配置 pom.xml 完成之后,会发现工程项目出现了报错,是因为 pom.xml 文件的内容是复制过来,只需右键工程项目选择 Maven 中的 Update project 即可。
之后查看 Maven Depedencies 就可以查看到所有被加入进去的依赖包。
(4)整合 springData redis 配置
架包导入进去后开始集成测试操作,开始整合 Spring data redis,而整合的过程就是结合 spring 的配置文件,因为Spring data redis 就是 Spirng 提供的一套服务。
而 Spirng 最大的好处就是将所有的 API 交给了容器去进行管理,所以此时需要在 resources 目录下创建一个配置文件,叫做 applacationContext-redis.xml 即可。创建完成后将相关的依赖代码添加进去。
Ø 整合 springData redis 配置相关的部分依赖代码
<!--整合 springDataRedis
其中含有一个核心的 API:redisTemplate,是用来操作 redis 服务器的,而该 API 需要交给容器去控制,所以需要创建容器交给 redisTemplate 管理。
-->
</beans>
①设置 key 的序列化方式
添加一个<bean>标签创建 redisTemplate 对象交给容器去管理,其中的 id 设为 redisTemplate,而 class 通过ctrl+shift+p搜索rediste,然后点击进入在类名处copy即可,为org.springframework.data.redis.core.RedisTemplatecK,V 其中 KV 为需要提供的两个泛型,暂时不需要,删除即可。到此就成功的创建了一个对象。
- 代码如下:
<bean id="redisTemplate" class= "org.springframework.data.redis.core.RedisTemplate”>
</bean>
还需要配置keySerializer,因为采用了property的set方法注入,可以直接按住ctrl再点击org.springframework.data.redis.core.RedisTemplate 进入源码中查找到 set 方法中的 keySerializer。
- setKeySerializer 方法
public void setKeySerializer(RedisSerializer<?> serializer){
this.keySerializer = serializer;
}
- 代码如下:
<bean id="redisTemplate" class="org.springframework. data.redis.core.RedisTemplate">
<!--设器 key 的序列化方式-->
<property name="keySerializer">
</property>
</bean>
同时注意首字母需要改为小写。根据源码的 keySerializer 方法知晓需要传入两个参数接口,按住ctrl点击进入接口对应的实现类,可以查看除了原生的之外还有 jackson 类型的序列化方式都含有,此处选择 StringRedisSerializer 类型即可。
点击之后在源码内点击类名右键复制,再次定义一个bean结点,设置class为org.springframework.data.redis.serializer.StringRedisSerializer,以此通过注入的方式,将自己写的对象注入。
<bean id="redisTemplate" class="org.springframework. data.redis.core.RedisTemplate">
<!--设器 key 的序列化方式-->
<property name="keySerializer">
<bean class=”org.springframework.data.redis.serializer.StringRedisSerializer“>
</property>
</bean>
②设置 value 的序列化方式
设置 key 的序列化方式之后,还需设置 value 的序列化方式,其过程与 key 的序列化方式设置类似。首先 ctrl+o 找到 setValueSerializer 方法,将 set 后的 ValueSerializer 粘贴复制至注入的 name 中,再将首字母变为小写,再编写一个<bean></bean>的节点,同时 class 中采用与 key 序列化一致的 StringRedisSerializer 即可。
l setValueSerializer方法
public void setValueSerializer(RedisSerializer<?> serializer) {
this.valueSerializer = serializer;
}
- 代码如下:
<bean id="redisTemplate" class="org.springframework. data.redis.core.RedisTemplate">
<!--设器 key 的序列化方式-->
<property name="keySerializer">
<bean class=”org.springframework.data.redis.serializer.StringRedisSerializer“>
</property>
<!--设置 value 的序列化-->
<property name="valueSerializer">
<bean class=”org.springframework.data.redis.serializer.StringRedisSerializer“>
</property>
</bean>
由以上代码可以知道 redisTemplate 只能操作 String 类型的 key 和 value 参数。
③注入和 redis 服务器创建连接的方式
同时 redisTemplate 重点是用于操纵 redis 服务器的,而操作 redis 服务器首先应该和 redis 服务器通过 java 代码创建一个连接,所以需要将创建连接的方式也注入到 redisTemplate 中来。
方法为:首先在源码中 ctrl+o 查找连接的方式,同时如果在本类中没有找到可以去父类中寻找,继续输入 ctrl+o,输入 set,就会出现我们需要寻找的 setConnectionFactory 方法,而父类含有该方法,就可以在配置中也将其注入进来。
- 源码中 setConnectionFactory 方法代码如下:
public void setConnectionFactory(RedisConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
通过<property>标签注入连接工厂,name 设为 connectionFactory,同时因为 connectionFactory 并不存在于本类,所以还需要创建 connectionFactory 交给 spring 容器管理,因而设置一个 bean 结点,class 为connectionFactory,同时根据源码中的 setConnectionFactory 方法可以得知参数为 RedisConnectionFactory,ctrl+p 查看 RedisConnectionFactory 接口中的类,可以看到有一个叫 JedisConnectionFactory 的类,点进去后右键类名 Copy Qualified Name,将其 Qualified Name 设为 class 的值。
之后在配置连接工厂中。在源码中 ctrl+o 可以查找到 setHostName(设置主机名),setPort(设置连接地址),同时其中的 setDatabase(int):void 需要注意 Redis 中默认有16个数据库,而此时的s etAatabase 接受的是 int 类型的参数,表示的就是需要操控的 redis 中哪个数据库仓库。
知晓以上概念后,依次配置 hostName 主机号为127.0.0.1,port 端口号为 redis 默认的6379,dataBase 同时设置value 为0,表示向0号仓库赋值。最后还要配置连接池的最大参数 poolConfig,以此设置最大连接数和最小连接数等等,同时 poolConfig 是一个对象,所以采用 ref 而不用 value。
- setPoolconfig(JedisPoolConfig poolConfig)方法代码如下:
public void setPoolconfig(JedisPoolConfig poolConfig){
this.poolConfig = poolConfig;
}
- 代码如下:
<bean id="redisTemplate" class="org.springframework. data.redis.core.RedisTemplate">
<!--设器 key 的序列化方式-->
<property name="keySerializer">
<bean class=”org.springframework.data.redis.serializer.StringRedisSerializer“>
</property>
<!--设置 value 的序列化-->
<property name="valueSerializer">
<bean class=”org.springframework.data.redis.serializer.StringRedisSerializer“>
</property>
<!--注入连接工厂-->
<property name="connectionFactory" ref="connectionFactory"></property></bean>
<! --创建 connectionFactory 交给 spring 容器管理-->
<beanid="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="127.0.0.1"></property>
<property name="port" value="6379"></property>
<property name="dataBase" value="O"></property>
<property name="pooLConfig" ref="pooLConfig"></property></bean>
</bean>
④创建连接池的基本配置
创建 bean 结点,而 class 的值为 redis.clients.jedis.JedisPoolConfig 是在源码中通过 ctrl+JedisPoolConfig 来找,可以看出 Config 中就是 jedis 的操作,将其右键 Copy Qualified Name 将其复制过来。
最大连接的值是 JedisPoolConfig 的父类 GenericObjectPoolConfig 中通过 ctrl+o查 找 set,会发现一个 setMaxTotal 最大连接方法,最后使用 property 来进行注入,再设置一个随机值,同时还可以配置最大限时连接
- setMaxTotal(int maxTotal)方法
p
ubli
c void setMaxTotal[int maxTotal){
this.maxTotal = maxTotal;
}
- 代码如下:
<bean id="redisTemplate" class="org.springframework. data.redis.core.RedisTemplate">
<!--设器 key 的序列化方式-->
<property name="keySerializer">
<bean class=”org.springframework.data.redis.serializer.StringRedisSerializer“>
</property>
<!--设置v alue 的序列化-->
<property name="valueSerializer">
<bean class=”org.springframework.data.redis.serializer.StringRedisSerializer“>
</property>
<!--注入连接工厂-->
<property name="connectionFactory" ref="connectionFactory"></property></bean>
<! --创建 connectionFactory 交给 spring 容器管理-->
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="127.0.0.1"></property>
<property name="port" value="6379"></property>
<property name="dataBase" value="O"></property>
<property name="pooLConfig" ref="pooLConfig"></property>
</bean>
<!--创建连接池的基本配置-->
<bean id=”poolConfig”class=”redis.clients.jedis.JedisPoolConfig”>
<!--最大连接-->
<property name=”maxTotal” value=”10”></property>
<bean>
</bean>
至此整合 springData redis 配置就全部完成了,接下来开始测试。
(5)总结-applicationContext-redis.xml 配置文件代码
全部代码如下:
<?xml version="1.0"encoding="UTF-8"?>
<beans xmlns ="http://www .springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"xmlns :jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework. org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task"xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www. springframework
Jorg/schema/aop
http://www.springframework.org/schema/
aop/spring-aop.xsd
http://www.springframework. org/schema/
context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
">
<!--整合 springDataRedis
其中含有一个核心的 API:redisTemplate,是用来操作 redis 服务器的,而该 API 需要交给容器去控制,所以需要创建容器交给 redisTemplate 管理。
-->
<bean id="redisTemplate" class="org.springframework. data.redis.core.RedisTemplate">
<!--设器key的序列化方式-->
<property name="keySerializer">
<bean class=”org.springframework.data.redis.serializer.StringRedisSerializer“>
</property>
<!--设置 value 的序列化-->
<property name="valueSerializer">
<bean class=”org.springframework.data.redis.serializer.StringRedisSerializer“>
</property>
<!--注入连接工厂-->
<property name="connectionFactory" ref="connectionFactory"></property></bean>
<! --创建 connectionFactory 交给 spring 容器管理-->
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="127.0.0.1"></property>
<property name="port" value="6379"></property>
<property name="dataBase" value="O"></property>
<property name="pooLConfig" ref="pooLConfig"></property>
</bean>
<!--创建连接池的基本配置-->
<bean id=”poolConfig”class=”redis.clients.jedis.JedisPoolConfig”>
<!--最大连接-->
<property name=”maxTotal” value=”10”></property>
<bean>
</bean>
</beans>
3. 测试案例
将配置整合完毕后,在 java 文件夹下右键创建一个 cn.itcast.redis.test 包下的 RedisTest 测试类。将 spring 测试写入,其中 locations 的配置就写需要测试的 xml 文件名
- RedisTest 代码
package cn.itcast.redis.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;
@Runwith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext-redis.xml")
public class RedisTest {
@Autowired
//其中的形参都为 String 类型
private RedisTemplate<String,string> redisTemplate;
@Test
public void testRedis() {
//给 key 和 value 分别赋值为 itcast001和 itcast001
redisTemplate.opsForValue().set("itcast001", "itcast001);
}
}
代码完成后运行,出现报错后提示 dataBase 错误,改为 database 小写的形式即可。更改再次运行后提示运行成功,说明成功向 key 服务器中放了值 itcase001
打开一个 redis 服务客户端,输入命令:get itcast001 后显示 itcast001 证明可以从服务器中获取数据,则说明Spring-data-redis 和 redis 服务器成功产生交互。