使用Spring Redis发布/订阅

继续发现功能强大的Redis功能集,值得一提的是对发布/订阅消息的开箱即用支持。

发布/订阅消息传递是许多软件体系结构的重要组成部分。 某些软件系统要求消息传递解决方案提供高性能,可伸缩性,队列持久性和持久性,故障转移支持,事务以及许多其他令人敬畏的功能,在Java世界中,大多数情况下总是导致使用JMS实现之一提供者。 在我以前的项目中,我一直积极使用Apache ActiveMQ (现在转向Apache ActiveMQ Apollo )。 尽管这是一个很好的实现,但有时我只需要简单的排队支持,而Apache ActiveMQ看上去就显得过于复杂了。

备择方案? 请欢迎Redis pub / sub! 如果您已经在使用Redis作为键/值存储,那么很少的其他配置行将立即将发布/订阅消息传递到您的应用程序。

Spring Data Redis项目很好地抽象了Redis pub / sub API,并为使用Spring功能与JMS集成的每个人提供了如此熟悉的模型。

与往常一样,让我们​​从POM配置文件开始。 这是相当小的,简单的,包括必要的春天的依赖, 春天Redis的数据和Jedis ,伟大的Java客户端Redis的 。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelversion>4.0.0</modelversion><groupid>com.example.spring</groupid><artifactid>redis</artifactid><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><properties><project.build.sourceencoding>UTF-8</project.build.sourceencoding><spring.version>3.1.1.RELEASE</spring.version></properties><dependencies><dependency><groupid>org.springframework.data</groupid><artifactid>spring-data-redis</artifactid><version>1.0.1.RELEASE</version></dependency><dependency><groupid>cglib</groupid><artifactid>cglib-nodep</artifactid><version>2.2</version></dependency><dependency><groupid>log4j</groupid><artifactid>log4j</artifactid><version>1.2.16</version></dependency><dependency><groupid>redis.clients</groupid><artifactid>jedis</artifactid><version>2.0.0</version><type>jar</type></dependency><dependency><groupid>org.springframework</groupid><artifactid>spring-core</artifactid><version>${spring.version}</version></dependency><dependency><groupid>org.springframework</groupid><artifactid>spring-context</artifactid><version>${spring.version}</version></dependency></dependencies><build><plugins><plugin><groupid>org.apache.maven.plugins</groupid><artifactid>maven-compiler-plugin</artifactid><version>2.3.2</version><configuration><source>1.6<target>1.6</target></configuration></plugin></plugins></build>
</project>

继续配置Spring上下文,让我们了解为了使发布者发布一些消息并让消费者使用它们而需要的内容。 了解有关JMS的相应Spring抽象将对此有很大帮助。

  • 我们需要连接工厂-> JedisConnectionFactory
  • 我们需要一个模板供发布者发布消息-> RedisTemplate
  • 我们需要一个消息监听器供使用者使用消息-> RedisMessageListenerContainer

使用Spring Java配置,让我们描述一下上下文:

package com.example.redis.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scheduling.annotation.EnableScheduling;import com.example.redis.IRedisPublisher;
import com.example.redis.impl.RedisMessageListener;
import com.example.redis.impl.RedisPublisherImpl;@Configuration
@EnableScheduling
public class AppConfig {@BeanJedisConnectionFactory jedisConnectionFactory() {return new JedisConnectionFactory();}@BeanRedisTemplate< String, Object > redisTemplate() {final RedisTemplate< String, Object > template =  new RedisTemplate< String, Object >();template.setConnectionFactory( jedisConnectionFactory() );template.setKeySerializer( new StringRedisSerializer() );template.setHashValueSerializer( new GenericToStringSerializer< Object >( Object.class ) );template.setValueSerializer( new GenericToStringSerializer< Object >( Object.class ) );return template;}@BeanMessageListenerAdapter messageListener() {return new MessageListenerAdapter( new RedisMessageListener() );}@BeanRedisMessageListenerContainer redisContainer() {final RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory( jedisConnectionFactory() );container.addMessageListener( messageListener(), topic() );return container;}@BeanIRedisPublisher redisPublisher() {return new RedisPublisherImpl( redisTemplate(), topic() );}@BeanChannelTopic topic() {return new ChannelTopic( 'pubsub:queue' );}
}

非常简单明了。 @EnableScheduling批注不是必需的,并且仅对于我们的发布者实现是必需的:发布者将每100毫秒发布一次字符串消息。

package com.example.redis.impl;import java.util.concurrent.atomic.AtomicLong;import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.scheduling.annotation.Scheduled;import com.example.redis.IRedisPublisher;public class RedisPublisherImpl implements IRedisPublisher {private final RedisTemplate< String, Object > template;private final ChannelTopic topic; private final AtomicLong counter = new AtomicLong( 0 );public RedisPublisherImpl( final RedisTemplate< String, Object > template, final ChannelTopic topic ) {this.template = template;this.topic = topic;}@Scheduled( fixedDelay = 100 )public void publish() {template.convertAndSend( topic.getTopic(), 'Message ' + counter.incrementAndGet() + ', ' + Thread.currentThread().getName() );}
}

最后是我们的消息侦听器实现(仅在控制台上打印消息)。

package com.example.redis.impl;import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;public class RedisMessageListener implements MessageListener {@Overridepublic void onMessage( final Message message, final byte[] pattern ) {System.out.println( 'Message received: ' + message.toString() );}
}

太棒了,只有两个小类,一个配置用于将事物连接在一起,并且我们的应用程序中具有完整的发布/订阅消息支持! 让我们以独立方式运行应用程序…

package com.example.redis;import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;import com.example.redis.config.AppConfig;public class RedisPubSubStarter {public static void main(String[] args) {new AnnotationConfigApplicationContext( AppConfig.class );}
}

…并在控制台中查看以下输出:

...
Message received: Message 1, pool-1-thread-1
Message received: Message 2, pool-1-thread-1
Message received: Message 3, pool-1-thread-1
Message received: Message 4, pool-1-thread-1
Message received: Message 5, pool-1-thread-1
Message received: Message 6, pool-1-thread-1
Message received: Message 7, pool-1-thread-1
Message received: Message 8, pool-1-thread-1
Message received: Message 9, pool-1-thread-1
Message received: Message 10, pool-1-thread-1
Message received: Message 11, pool-1-thread-1
Message received: Message 12, pool-1-thread-1
Message received: Message 13, pool-1-thread-1
Message received: Message 14, pool-1-thread-1
Message received: Message 15, pool-1-thread-1
Message received: Message 16, pool-1-thread-1
...

大! Redis pub / sub可以做很多事情, Redis官方网站上提供了出色的文档 。

参考:我们的JCG合作伙伴 Andrey Redko在Andriy Redko {devmind}博客上使用Spring从Redis发布/ 订阅 。


翻译自: https://www.javacodegeeks.com/2012/10/redis-pubsub-using-spring.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/371223.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python在律师上作中的实例_python-基础面试题

深拷贝1.对象A拷贝&#xff0c;生成对象B&#xff0c;且我们修改对象B(对象A)中的数据或方法&#xff0c;对象A(对象B)不会受影响&#xff0c;这就是深拷贝2.对于可变与不可变类型对于不可变类型&#xff0c;深拷贝会和浅拷贝一样&#xff0c;拷贝的是引用&#xff0c;不会创建…

2017 校招华为上机题

1. 给定一个字符串&#xff0c;把字符串内的字母转换成该字母的下一个字母&#xff0c; a 换成b&#xff0c;z 换成a&#xff0c;Z 换成A&#xff0c;如aBf 转换成bCg&#xff0c;字符串内的其他字符不改变&#xff0c;给定函数&#xff0c;编写函数void Stringchang&#xff0…

JSON –拯救杰克逊

有时您必须使用JavaScript从服务器中获取一些数据&#xff0c; JSON是完成此任务的不错选择。 让我们玩一下JPA揭秘&#xff08;第1集&#xff09;-OneToMany和ManyToOne映射中的“雇主-雇员-福利”示例。 我们将在基于Spring Framework的Web应用程序中使用它。 我们的第一个…

maven 使用记录之修改 maven默认jdk版本

maven package执行的时候会遇到jdk版本不对的问题 &#xff1a;原因是 maven所指定的jdk版本与项目使用的jdk版本不一致1.项目属性的 java compiler可以设置2.直接修改 maven 的 settings.xml 一劳永逸settiings.xml <profiles>标签内加入<profile> <id>j…

java默认值_Java中八种基本数据类型的默认值

通过一段代码来测试一下 8种基本数据类型的默认值package dierge;public class Ceshi {int a;double b;boolean c;char d;float f;byte e;long h;short j;public static void main(String args[]){Ceshi anew Ceshi();System.out.println("整型的默认值是&#xff1a;&quo…

HDU - 1024 Max Sum Plus Plus 最大m段子段和+滚动数组优化

给定n个数字&#xff0c;求其中m段的最大值&#xff08;段与段之间不用连续&#xff0c;但是一段中要连续&#xff09; 例如&#xff1a;2 5 1 -2 2 3 -1五个数字中选2个&#xff0c;选择1和2 3这两段。 dp[i][j]从前j个数字中选择i段&#xff0c;然后根据第j个数字是否独立成一…

JavaFX教程–基础

JavaFX似乎正在RIA领域获得发展。 有了正确的工具和开发支持&#xff0c;它肯定会在下一个最佳技术“物”上付出巨大的代价。 我没有在这里写任何JavaFX评论&#xff0c;因为有很多技术评论可能对它进行了广泛的评论&#xff0c;但是&#xff0c;我将编写一个简单的教程&#x…

java script this_JavaScript this 关键字

JavaScript this 关键字面向对象语言中 this 表示当前对象的一个引用。但在 JavaScript 中 this 不是固定不变的&#xff0c;它会随着执行环境的改变而改变。在方法中&#xff0c;this 表示该方法所属的对象。如果单独使用&#xff0c;this 表示全局对象。在函数中&#xff0c;…

trim函数的作用 $.trim(str)

去掉字符序列左边和右边的空格转载于:https://www.cnblogs.com/dandeliongogo/p/6610890.html

php数据库备份脚本

// 备份数据库 $host "localhost"; $user "root"; //数据库账号 $password ""; //数据库密码 $dbname "mysql"; //数据库名称 // 这里的账号、密码、名称都是从页面传过来的 if (!mysql_connect($host, $user, $password)) // 连接…

java swing 案例详解_《Java Swing图形界面开发与案例详解》PDF_IT教程网

资源名称&#xff1a;《Java Swing图形界面开发与案例详解》PDF内容简介&#xff1a;《Java Swing图形界面开发与案例详解》全书共20章&#xff0c;其中第1&#xff5e;2章主要介绍有关Swing的基础知识&#xff0c;包括Swing的基本概述、如何使用IDE开发Swing程序&#xff1b;第…

水晶球错觉

我注意到人们有时会避免进行彻底的测试。 对于某些人来说&#xff0c;这听起来像是伪造的&#xff0c;但是请听我说……我确实理解为什么会这样。 测试会产生被困的感觉&#xff0c;每引入一个新的测试&#xff0c;负担就会加重。 建立稳定&#xff0c;无干扰且质量保证的测试套…

Python—day3

1、字符串在C里边就是字符数组 Python里边一切事物都是对象&#xff0c;对象则是类创建的 2、set集合 set是一个无序且不能重复的元素集合 #!/usr/bin/env python# encoding: utf-8#set对象不能有重复s1 set()s1.add(alex)print(s1)s1.add(alex)print(s1)s1.add(shidong)print…

iOS - The file “XXX.app” couldn’t be opened because you don’t have permission to view it.

当引入第三方的框架的时候 容易产生以下问题&#xff1a; The file “XXX.app” couldn’t be opened because you don’t have permission to view it. 如图&#xff1a; 造成的原因&#xff1a; info文件中的字段Executable file 与 build settings栏中的Packaging中的Produc…

Google Guava v07范例

我们在TouK举办了一个名为“每周技术研讨会”的活动&#xff0c;即每个星期五的16:00&#xff0c;每个愿意参加的人都有一个演讲。 我们展示了我们在家学习和学习的东西&#xff0c;但是我们也设有一个公告板&#xff0c;上面有人们想听的话题。 上周MaciejPrchniak谈论了Cloju…

推荐一些经过实践检验的学习方法

作者做了多年的Java培训教师&#xff0c;也接触过不少初学者&#xff0c;根据多年的教学互动经验&#xff0c;总结了一些能少走弯路的学习方法&#xff0c;供大家参考。 第一&#xff0c;是要多学多练&#xff0c;这似乎是废话&#xff0c;但真正能非常上心学习的人还真是少数&…

使JFrame透明

首先创建一个带有滑块的框架&#xff0c;该滑块将用于设置透明度量。 import javax.swing.JFrame; import javax.swing.JSlider;public class TransparentFrame extends JFrame {public TransparentFrame() {setTitle(Transparent Frame);setSize(400,400);setDefaultCloseOper…

第一次作业之成员介绍

Lab205的新鲜血液 很理所当然的&#xff0c;实验室的4枚“小鲜肉”在现代软工的课程上组成了一个team&#xff0c;作为一个负责的team长&#xff0c;我当然要放上组员们的自述啦&#xff01;&#xff08;为什么不是他述&#xff0c;╭(╯^╰)╮&#xff0c;谁让我是个傲娇的组长…

java自定义分页标签_自定义分页标签--仿javaeye分页效果

效果如图&#xff1a;1、JSP规范1.1版本后增加了自定义标签库。实现自定义标签的步骤(1)开发自定义标签处理类。(2)建立*.tld文件。(3)在web.xml中增加自定义标签的定义。(4)在jsp中使用自定义标签。2、自定义标签类(1)继承javax.servlet.jsp.tagext.TagSupport(2)标签类属性&a…

Java隐藏代码

不久前&#xff0c;我遇到了字符串中不可见字符的问题。 因为它们是不可见的&#xff0c;所以它们确实会引起混乱。 String a "Hello\u200e";String b "Hello\u200f";System.out.println(\ a " and " b " are length " a.length…