本文档的副本可以供自己使用,也可以分发给别人,但是您不可以通过该文档或副本收取任何费用。使用电子版或者打印该文档需要包含版权声明。
原文链接:https://docs.spring.io/spring-data/data-redis/docs/current/reference/html/
1.简介
本文是 Spring Data Redis的参考文档。它解释了 Key Value模型的概念和响应的存储语法规则。
如需要 Spring 或 Spring Data 的例子,请参照其他的入门文档。本文档针对于熟悉 Key Value数据库和 Spring 框架的开发者
2.为什么使用 SpringData Redis
Spring是一个全栈的 JavaEE 开发框架,它通过 IOC、 AOP 和服务抽象提供了一个轻量级非入侵性的编程模型。
NoSQL存储可以在传统关系型数据库的基础上提供快速访问和水平可拓展。事实上, Key Value数据库在 NoSQL 数据库中有着巨大的发挥空间。
在 Spring 的基础之上, Spring Data Redis 可以很容易的编写,可以减少大量的冗余代码。
3 版本要求
1.Spring Data Redis1.x 需要 JDK6.0 以上、 Spring5.0.5 以上版本2.对于 Redis 存储而言,需要 2.6.x 以上的版本, Spring Data Redis 的测试主要针对于最新的3.2版本
4 入门指南
学习一个框架不可能一步到位。在本节中我们提供一个 Spring Data Redis模块的简单快速入门。当然,如果您有更佳的入门指导,您可以联系我们予以改进4.1第一步
SpringData Redis 在 Spring 和 Redis 之间提供了方便的集成。 因此首先您需要熟悉 Spring 框架和 Redis 存储。在整个SDR文档中,每个部分提供了与相关资源的链接,但最好事先熟悉这些主题。
4.1.1 了解 Spring
在 Spring Data 中大量使用到了 Spring 的 IOC、 AOP 和资源抽象等核心功能。 知道 Spring API并不重要,重要的是要理解上述功能的概念,至少应该理解 IOC 的概念。也就是说,如果你对 Spring 比较熟悉,你就可以更快的上手 Spring Data Redis。除了一些全面的文档,一些博客书籍等也很好的诠释了 Spring 框架,您也可以通过 Spring 官方文档了解更多的信息。 一般来说,本文档是比较全面的 SpringData Redis 的入门教程。
4.1.2 了解 NoSQL 和 Key Value 存储
NoSQL给存储世界带来了巨大的冲击。它有着广泛的应用前景而且可以提供一些优秀的解决方案。通常来说,对于熟悉 SDR(Spring Data Redis)所支持的存储是至关重要的。最佳的快速入门的方法就是查阅官方文档按照上面的 demo 做一遍。一般来说也就只需要 5-10 分钟的时间。如果你没接触过 Key Value 存储,这将会使你大开眼界。
4.1.3 尝试一个例子
您可以通过下面的网址(http://github.com/spring-projects/spring-data-keyvalue-examples),找到更多的 SDR 的相关例子。对于 SDR 来讲,最吸引人眼球的就是 retwisj 的例子。 它是一个可以部署在本地或者在云端的建立在 Redis 之上的 Twitter 克隆。
4.2 帮助信息
如果您遇到一些问题或者对我们有些建议,请点击下面的连接:
4.2.1社区支持
*对开发者而言是一个学习和分享的平台。注意,在使用 * 之前您需要先注册。
4.2.2 专业支持
在 Spring Data 和 Spring 的背后有着专业的团队(Pivotal Software, Inc.)支持。
4.3 后续
1.您可以在* 的 Spring Data 或者Spring Data Redis 板块上面与其他的开发者交流.从而可以改进 Spring Data 框架。
2. 对于 Spring Data 的源代码仓库,详情请参见 Spring Data 的主页(上面有各种不同的版本)。
3. 如果您遇到了 bug 并且想予以改进,请在 Spring Data 的相关网站上面提出。
4. 如需了解更多更新的 Spring相关资讯,请订阅 Spring CommunityPortal。
5. 最后您可以关注 Spring 在 Twitter 上面的技术博客(Thomas 和 Christoph)。
参考文档
下面这部分文档解释了 SDR 的核心功能。 Redis 支持介绍 Redis 一系列的特性
5 Redis 支持
Redis是 Spring Data 所支持的 Key Value 数据存储之一。 下面是引用项目主页的信息: “Redis是一种先进的 Key Value 数据存储。它非常类似于 memcached,但是它的存储不是瞬时的。Redis可以有像 memcached 的 string 类型的存储,同时还有 list、 set 和有序 set 等。所有的这些数据都可以使用原子操作,如入栈/出栈、添加/删除、交集、并集、区别集等。 Redis 还支持不同类型的排序。 ”Spring Data Redis 提供了一种简单明了的访问 Redis 存储的配置方式。 它提供了底层和高层的抽象,从而使开发者从底层的 API 中解放出来。
5.1 Redis 版本需求
SpringRedis 需要 Redis2.6 以上和 JDK8.0 以上的版本支持。针对于不同的连接器(驱动),Spring Redis 支持两个流行的Redis开源Java库 Jedis和Lettuce.
5.2 Redis 的高级视图
为 Redis 提供了几个组件:
对于大多数的任务,高层次的抽象和服务支持是最佳选择。请注意,在任何时候开发者都可以利用封装的底层 API 连接 Redis。
5.3 连接 Redis
第一个任务是我们在连接到 Redis 时,需要通过 Spring 的 IOC 容器。 这时会用到一个 Java 连接器(Redis 驱动)。 不论底层连接到 Redis 的 Java 驱动是什么, SDR 都会使用统一的对象RedisConnection和 RedisConnectionFactory (在 org.springframework.data.redis.connection包下面)去连接 Redis。
5.3.1 RedisConnection 和RedisConnectionFactory
RedisConnection提供了与 Redis 后端通信的构件。 SDR 统一封装了 Redis 底层连接器的异常信息, 从而在切换底层连接器的时候不用修改任何上层代码。
注意:对于需要本机库API的情况,RedisConnection提供了专用方法getNativeConnection,它犯规用于通信的原始基础对象。
RedisConnection通 过 RedisConnectionFactory 创 建 。 例如,通过@Repository 注解和 AOP 进行异常转换。
注意:RedisConnectionFactory 返回的连接类型取决于底层的配置。(使用连接池或者新连接)
使用RedisConnectionFactory的最简单方法是通过IoC容器配置适当的连接器,并将其注入到使用的类中
注意:不幸的是,目前并非所有连接器都支持所有Redis功能。 在基础库不支持的Connection API上调用方法时,会引发UnsupportedOperationException 。 随着各种连接器的成熟,这种情况在未来可能会得到解决。
5.3.2 配置 Jedis 连接器
Jedis是一种 Spring Data Redis 支持的连接器,在 org.springframework.data.redis.connection.jedis下面有相应入口。
下面是 Jedis 最简单的一种配置方式:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- Jedis ConnectionFactory --> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"/> </beans>
然而,实际应用当中我们需要配置相应的主机、端口等如下:
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="server" p:port="6379" /> </beans>
5.3.3 配置Lettuce连接器
Lettuce是Spring DataRedis通过org.springframework.data.redis.connection.lettuce包支持的基于netty的开源连接器。
它的配置可能很容易猜到:
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="lettuceConnectionFactory" class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory" p:host-name="server" p:port="6379"/> </beans>
Lettuce连接器有很多参数可以进行调整。 Lettuce 的连接在进行阻塞和非阻塞的事务操作时,共享线程安全的本地连接。 可以设置 shareNativeConnection 为 false,从而使每次得到的连接都为专有的。另外,可以为 LettuceConnectionFactory 可以为一个阻塞事务连接或者所有连接配置 LettucePool(前提是设置 shareNativeConnection 为 false)。
5.4 Redis Sentinel 支持
对于高可用的支持,为提供 Redis Sentinel 提供了RedisSentinelConfiguration
注意:目前只有 Jedis 和 Lettuce 支持Redis Sentinel
/** * jedis */ @Bean public RedisConnectionFactory jedisConnectionFactory() { RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration() .master("mymaster") .sentinel("127.0.0.1", 26379) .sentinel("127.0.0.1", 26380); return new JedisConnectionFactory(sentinelConfig); } /** * Lettuce */ @Bean public RedisConnectionFactory lettuceConnectionFactory() { RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration() .master("mymaster") .sentinel("127.0.0.1", 26379) .sentinel("127.0.0.1", 26380); return new LettuceConnectionFactory(sentinelConfig); }
提示: RedisSentinelConfiguration 可以通过PropertySource 定义。
配置属性:
1.spring.redis.sentinel.master: name of the master node.
2.spring.redis.sentinel.nodes: Comma delimited list of host:port pairs.
有时候需要直接与一个 Sentinel 交互。使用RedisConnectionFactory.getSentinelConnection()或者
RedisConnection.getSentinelCommands()可以获取第一个活动的Sentinel。
5.5 使用 RedisTemplate 处理对象
大部分用户更倾向于用 RedisTemplate 和其相关的包中的类org.springframework.data.redis.core。事实上, Template 是一个包含众多功能的核心类。 Template 模板为 Redis 集成提供了一个更高层次的抽象。一方面 RedisConnection 提供了更低层次的数据接口;另一方面,模板提供了序列化和连接管理,从而使开发者从底层的接口中解放出来。
除此之外,模板还提供了直接执行命令的入口。您可以在 Template 中直接执行一下的命令:
Table1. Operational views
Interface |
Description |
Key Type Operations |
|
GeoOperations |
Redis geospatial operations like GEOADD, GEORADIUS,…) |
HashOperations |
Redis hash operations |
HyperLogLogOperations |
Redis HyperLogLog operations like (PFADD, PFCOUNT,…) |
ListOperations |
Redis list operations |
SetOperations |
Redis set operations |
ValueOperations |
Redis string (or value) operations |
ZSetOperations |
Redis zset (or sorted set) operations |
Key Bound Operations |
|
BoundGeoOperations |
Redis key bound geospatial operations. |
BoundHashOperations |
Redis hash key bound operations |
BoundKeyOperations |
Redis key bound operations |
BoundListOperations |
Redis list key bound operations |
BoundSetOperations |
Redis set key bound operations |
BoundValueOperations |
Redis string (or value) key bound operations |
BoundZSetOperations |
Redis zset (or sorted set) key bound operations |
一旦配置完成,模板是线程安全的,可以跨多个实例重用。
开箱即用, RedisTemplate在其大部分操作中使用基于Java的序列化程序。这意味着模板写入或读取的任何对象都将通过Java进行序列化/反序列化。序列化机制可以很容易地在模板上进行更改,Redis模块在org.springframework.data.redis.serializer包中提供了多个可用org.springframework.data.redis.serializer - 请参阅序列化程序以获取更多信息。 您还可以将任何序列化程序设置为null,并通过将enableDefaultSerializer属性设置为false来对原始byte数组使用RedisTemplate。请注意,模板要求所有的键都是非空值 - 只要基础化序列化程序接受它们,值就可以为空; 阅读每个序列化程序的javadoc以获取更多信息。
对于需要特定模板视图的情况,将视图声明为依赖项并注入模板:容器将自动执行消除opsFor[X]调用的转换:
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:use-pool="true"/> <!-- redis template definition --> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="jedisConnectionFactory"/> ... </beans>
public class Example { // inject the actual template @Autowired private RedisTemplate<String, String> template; // inject the template as ListOperations @Resource(name="redisTemplate") private ListOperations<String, String> listOps; public void addLink(String userId, URL url) { listOps.leftPush(userId, url.toExternalForm()); } }
5.6 处理 String 类型
因为在 Redis 中存储 String 类型的数据非常常见,所以在 RedisConnection 和 RedisTemplate 两个模块的基础上提供了两个便捷的类: StringRedisConnection 和 StringRedisTemplate。除了绑定到 String 的 key, template 和 connection 在底层使用 StringRedisSerializer,从而可以在上层提
供容易阅读的编码方式。例如:
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:use-pool="true"/> <bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate" p:connection-factory-ref="jedisConnectionFactory"/> ... </beans>
public class Example { @Autowired private StringRedisTemplate redisTemplate; public void addLink(String userId, URL url) { redisTemplate.opsForList().leftPush(userId, url.toExternalForm()); } }
和其他的 Spring 模板一样, RedisTemplate 和 StringRedisTemplate 允许开发者直接通过RedisCallback 接口连接到 Redis。 这赋予了开发者完全控制的权利,因为可以直接连接到RedisConnection上 面 。 当 StringRedisTemplate 使 用 到 回 调 的 时 候 , 需 要传 入 一 个StringRedisConnection 类型的入参。
public void useCallback() { redisTemplate.execute(new RedisCallback<Object>() { public Object doInRedis(RedisConnection connection) throws DataAccessException { Long size = connection.dbSize(); // Can cast to StringRedisConnection if using a StringRedisTemplate ((StringRedisConnection)connection).set("key", "value"); } }); }
5.7 序列化
从框架的角度来看,存在 Redis 上的数据仅仅是字节。 尽管 Redis 支持不同的类型,在某些情况下我们需要考虑数据的存储方式,而不是它代表着什么。将字节数据转化为字符串或者其他对象,这取决于用户自己。 SDR 通过RedisSerializer(org.springframework.data.redis.serializer包下)接口在用户数据类型和原始数据之间转换, RedisSerializer 顾名思义,扮演着序列化处理的角色。 框架提供多种序列化的支持,在上面的文章中提及的有: StringRedisSerializer 和JdkSerializationRedisSerializer。您可以使用 OxmSerializer 来实现对象/XML 之间的转化,或者使用 JacksonJsonRedisSerializer/Jackson2JsonRedisSerializer 提供了 JSON 序列化。 一定要注意
的是存储的格式不局限于 Value 值,它还可以是 Key、hashes 等等。
5.8 Hash mapping
数据可以使用Redis中的各种数据结构进行存储。 您已经了解到可以转换JSON格式的对象的Jackson2JsonRedisSerializer 。 理想情况下,JSON可以使用普通键存储为值。使用Redis哈希可以实现更复杂的结构化对象映射。 Spring DataRedis提供了根据用例将数据映射到hash的各种策略。
1.使用HashOperations和序列化器直接映射
2.使用Redis存储库
3.使用HashMapper和HashOperations
5.8.1Hash mappers
Hashmappers是将对象映射到Map<K, V>和后面的转换器。 HashMapper适用于Redis Hashes。
开箱即可使用多种实施方式:
1.BeanUtilsHashMapper使用Spring的BeanUtils 。
2.使用Object到Hash映射的 ObjectHashMapper 。
3.Jackson2HashMapper使用FasterXMLJackson
public class Person { String firstname; String lastname; // … } public class HashMapping { @Autowired HashOperations<String, byte[], byte[]> hashOperations; HashMapper<Object, byte[], byte[]> mapper = new ObjectHashMapper(); public void writeHash(String key, Person person) { Map<byte[], byte[]> mappedHash = mapper.toHash(person); hashOperations.putAll(key, mappedHash); } public Person loadHash(String key) { Map<byte[], byte[]> loadedHash = hashOperations.entries("key"); return (Person) mapper.fromHash(loadedHash); } }
5.8.2Jackson2HashMapper
Jackson2HashMapper为使用FasterXMLJackson的域对象提供Redis Hash映射。Jackson2HashMapper可以将数据映射的*属性映射为哈希字段名称,并可选地将结构展平。 简单类型映射到简单值。 复杂类型(嵌套对象,集合,映射)表示为嵌套JSON。
展平会为所有嵌套属性创建单独的哈希条目,并尽可能将复杂类型解析为简单类型
Table 2. Normal Mapping |
|
Hash Field |
Value |
firstname |
Jon |
lastname |
Snow |
address |
{ "city" : "Castle Black", "country" : "The North" } |
Table 3. Flat Mapping |
|
Hash Field |
Value |
firstname |
Jon |
lastname |
Snow |
address.city |
Castle Black |
address.country |
The North |
展平需要所有属性名称不会干扰JSON路径。使用拼合不支持在地图键中或作为属性名称使用点或括号。 生成的散列无法映射回对象。
5.9Redis 消息/PubSub(发布/订阅)
SpringData 为 Redis 消息服务提供了专门的入口, 非常类似于 JMS 在 Spring 框架中的集成,因此熟悉 JMS 集成的开发者,更加容易上手。
Redis消息大概可以分为两大模块:生产、消费和订阅消息。 pubsub(生产/消费)RedisTemplate类用于消息生产。类似于 JavaEE 接收异步消息的风格的RedisConnection 订阅,
SpringData 提供了专有的消息侦听容器,用于创建消息驱动和同步接收消息。 Redis 消息的核
心包是
org.springframework.data.redis.connection
org.springframework.data.redis.listenerprovide。
5.9.1 发送/发布消息
发布一条消息,开发者可以像其他操作一样使用底层的 RedisConnection 或者更高层次的
RedisTemplate。两个实体都可以把参数中的消息发送到目标的管道中 。 不同的是 ,
RedisConnection需要原始的字节数据,而 RedisTemplate 则是可以接收任意对象的数据。
// send message through connection RedisConnection con = ... byte[] msg = ... byte[] channel = ... con.publish(msg, channel); // send message through RedisTemplate RedisTemplate template = ... template.convertAndSend("hello!", "world");
5.9.2 接收/订阅消息
在接收的一方,订阅者可以根据命名或者模式匹配来订阅一个或多个 channel。 模式匹配不仅可以通过一个命令进行多个订阅,而且可以监听其他的 channel (当新增的发布者匹配到 pattern时候,模式匹配一样可以匹配上)。在更低的层次, RedisConnection 为 pattern 模式提供了发布者和订阅者映射到 Redis 命令的方法入口。注意,可以使用多个通道或 pattern 模式作为参数。改变连接的订阅或简单地查询是否监听,可以使用 RedisConnection 的 providesgetSubscription 和 isSubscribed 方法。
注意:订阅命令在 Spring Data Redis 中是阻塞的。 也就是在一个Connection 上面调用订阅会使当前线程阻塞,因为它会等待消息的到来。当订阅撤销时(会在当前 Connection 上面另起一个线程),当前线程会被释放。可以通过下面的消息监听容器解决上述问题。
正如上面所述的那样,一但通过 Connection 发起一个订阅请求,线程就会阻塞等待消息到来。因此在它上面不可以再调用其他的命令,除非取消或者修改当前的请求。此时,如要调用其他的方法(如: thensubscribe、 pSubscribe、 unsubscribe、 pUnsubscribe)将会抛出异常。如果要订阅消息,您需要实现 MessageListener 中的回调方法: 每次新消息到达时,将会调用
回调接口 onMessage 方法执行用户代码。接口不仅为真正的消息提供入口,还为匹配上的channel提供入口。不仅可以通过这些信息区分各种消息内容,还通过数据区分。
消息监听容器
由于其阻塞的特点,低级的订阅对开发者没有什么吸引力,因为它需要连接和用线程去管理每一个侦听器。为了解决这个问题, Spring Data 提供了RedisMessageListenerContainer(熟悉 EJB和 JMS 的开发者会比较熟悉这个概念)。因为它的目的是尽可能的支持 Spring 框架及其消息驱动 pojo(mdp)。
RedisMessageListenerContainer充当消息侦听器容器的角色,它是用来接收 Redis 通道消息和驱动 MessageListeners 注入。 侦听器容器负责接收所有线程的消息和分配到侦听器进行处理。 消息侦听器容器是 MDP 和消息传递的中介,并负责登记接收消息, 资源的获取和释放, 异常转换等。这样可以是开发者把重点用在处理消息的业务逻辑上,这也是 Spring Data 框架的目的
之一。
此外,为了占用资源最小化, RedisMessageListenerContainer 允许一个连接和一个线程共享多个侦听器,尽管他们不共享一个订阅。因此不管有多少 listener 或 channel,它运行时的生命周期成本不变。此外,容器允许对运行时的配置更改,您可以在不重启的情况下添加或删除侦听器。此外,容器使用一种懒加载的订阅的方式, 当你需要使用 RedisConnection 的时候才创建。如果监听器没有对应的订阅,系统会自动释放其监听器线程。异步风格的消息,需要 java.util.concurrent.Executor ( 或Spring’sTaskExecutor)去委派消息。 根据负载、监听器的数量和运行时环境,您可以通过 executor 类型来满足需求,
MessageListenerAdapter
MessageListenerAdapter是 Spring 异步消息支持的最终组件: 简而言之,它允许您公开任何类作为 MDP(当然有一些限制)。
考虑下面的接口定义。注意,虽然接口扩展了 MessageListener,它仍然可以通过使用MDP MessageListenerAdapter类用做成一个 MDP。还要注意不同的消息处理方法是怎样不同 Message类型(可以接收和发出的消息)被强约束的。 除此之外, channel 或者 pattern 可以作为 String
类型传到方法的第二个参数中去:
public interface MessageDelegate { void handleMessage(String message); void handleMessage(Map message); void handleMessage(byte[] message); void handleMessage(Serializable message); // pass the channel/pattern as well void handleMessage(Serializable message, String channel); }
public class DefaultMessageDelegate implements MessageDelegate { // implementation elided for clarity... }
特别注意上述MessageDelegate 接口的实现(在 DefaultMessageDelegate 类的基础上)没有依赖Redis。 它是一个真正的 POJO,我们将通过以下将其配置成 MDP。
<?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:redis="http://www.springframework.org/schema/redis" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/redis http://www.springframework.org/schema/redis/spring-redis.xsd"> <!-- the default ConnectionFactory --> <redis:listener-container> <!-- the method attribute can be skipped as the default method name is "handleMessage" --> <redis:listener ref="listener" method="handleMessage" topic="chatroom" /> </redis:listener-container> <bean id="listener" class="redisexample.DefaultMessageDelegate"/> ... <beans>
注意:监听器要么是channel (e.g. topic="chatroom") ,要么是 pattern (e.g. topic="*room")。
上面的例子使用了 Redis 名称空间声明消息侦听器容器并自动注册侦听器的 pojo。 完整的 bean
定义如下所示:
<bean id="messageListener" class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter"> <constructor-arg> <bean class="redisexample.DefaultMessageDelegate"/> </constructor-arg> </bean> <bean id="redisContainer" class="org.springframework.data.redis.listener.RedisMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory"/> <property name="messageListeners"> <map> <entry key-ref="messageListener"> <bean class="org.springframework.data.redis.listener.ChannelTopic"> <constructor-arg value="chatroom"> </bean> </entry> </map> </property> </bean>
每次接收到消息后,适配器自动透明的执行将底层格式转换为对象。 (使用配置过的RedisSerializer)。 任何异常都会被容器捕获。
5.10 Redis 事务
Redis提供了支持事务的命令: multi、 exec 和discard 命令。 这些操作在 RedisTemplate 中都有提供。但是 RedisTemplate 不能保证事务的执行公用一个Connection。
当多个操作需要在同一个 Connection 中完成时,可以使用提供的 SessionCallback 接口。例如:
//execute a transaction List<Object> txResults = redisTemplate.execute(new SessionCallback<List<Object>>() { public List<Object> execute(RedisOperations operations) throws DataAccessException { operations.multi(); operations.opsForSet().add("key", "value1"); // This will contain the results of all ops in the transaction return operations.exec(); } }); System.out.println("Number of items added to set: " + txResults.get(0));
RedisTemplate会使用 Value、 hash key、hash Value 在返回之前进行串并转换。 另外还有一个可执行的方法,您还可以为事务的结果定制序列化器。
注意:一个重大的调整是在 1.1 版本的 RedisConnection 和 RedisTemplate 的 exec 方法上。之前,这些方法直接从 connectors 中返回事务结果。这意味着返回的数据类型不同于RedisConnection中返回的类型。例如,当 zadd 插入一个数据到有序集合中后返回一个布尔类型的值。 大多数Connection返回一个 Long 类型的数据,然后通过 Spring Data Redis 转化。另一个常见的区别就是 Connection 返回一个状态值(通常是“ok”)。这些信息通常情况下会被 Spring Data Redis丢弃。在 1.1 之前没有对 exec 执行的结果进行转换。 同时, RedisTemplate 没有对结果进行反序列化,因此结果通常包括原始字节数组。如果这样的改变破坏了你的程序结构,你可以将convertPipelineAndTxResults设置为 false 来禁用该功能。
5.10.1@Transactional 支持
事 务支 持 默 认 是 禁 用 的 , 在 使 用 时 需 要 显 式 地 为 每 个 RedisTemplate 启用 设 置
setEnableTransactionSupport。 这将强制RedisConnection 绑定到当前使用的 Threadtriggering
MULTI上去
/** Sample Configuration **/ @Configuration public class RedisTxContextConfiguration { @Bean public StringRedisTemplate redisTemplate() { StringRedisTemplate template = new StringRedisTemplate(redisConnectionFactory()); // explicitly enable transaction support template.setEnableTransactionSupport(true); return template; } @Bean public PlatformTransactionManager transactionManager() throws SQLException { return new DataSourceTransactionManager(dataSource()); } @Bean public RedisConnectionFactory redisConnectionFactory( // jedis || lettuce); @Bean public DataSource dataSource() throws SQLException { // ... } }
/** Usage Constrainsts **/ // executed on thread bound connection template.opsForValue().set("foo", "bar"); // read operation executed on a free (not tx-aware) connection template.keys("*"); // returns null as values set within transaction are not visible template.opsForValue().get("foo");