java redis sub_基于Spring+redis实现pub/sub

该博客介绍了如何在Java应用中利用Spring框架与Redis实现发布订阅功能。通过配置JedisConnectionFactory、RedisTemplate、RedisMessageListenerContainer和MessageListenerAdapter,创建了一个发布者和监听者。发布者每隔100ms发布一个字符串消息,监听者接收到消息后在控制台打印。

基于Spring+redis实现pub/sub

Pub / Sub(publisher/subcriber发布和订阅)消息是许多软件架构的重要组成部分。消息传递解决方案提供了高性能,可扩展性,队列持久性和耐用性,故障转移支持等,以及许多更漂亮具备的功能,在Java世界中大多总是使用JMS实现。后来使用Apache ActiveMQ的,有时只是需要简单的排队支持,而Apache ActiveMQ显得过于复杂。

在这个案例中,使用Redis作为pub/sub的队列,将消息存放在Redis内存中。

首先,配置Maven:

4.0.0

com.example.spring

redis

0.0.1-SNAPSHOT

jar

UTF-8

3.1.1.RELEASE

org.springframework.data

spring-data-redis

1.0.1.RELEASE

cglib

cglib-nodep

2.2

log4j

log4j

1.2.16

redis.clients

jedis

2.0.0

jar

org.springframework

spring-core

${spring.version}

org.springframework

spring-context

${spring.version}

org.apache.maven.plugins

maven-compiler-plugin

2.3.2

1.6

1.6

使用 Jedis作为Java客户端,需要三个组件:

连接Redis的工厂 -> JedisConnectionFactory

redis操作模板-> 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 {

@Bean

JedisConnectionFactory jedisConnectionFactory() {

return new JedisConnectionFactory();

}

@Bean

RedisTemplate< 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;

}

@Bean

MessageListenerAdapter messageListener() {

return new MessageListenerAdapter( new RedisMessageListener() );

}

@Bean

RedisMessageListenerContainer redisContainer() {

final RedisMessageListenerContainer container = new RedisMessageListenerContainer();

container.setConnectionFactory( jedisConnectionFactory() );

container.addMessageListener( messageListener(), topic() );

return container;

}

@Bean

IRedisPublisher redisPublisher() {

return new RedisPublisherImpl( redisTemplate(), topic() );

}

@Bean

ChannelTopic topic() {

return new ChannelTopic( 'pubsub:queue' );

}

}

下面做一个消息发布在Producer,每100ms发布一个字符串消息:

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 {

@Override

public void onMessage( final Message message, final byte[] pattern ) {

System.out.println( 'Message received: ' + message.toString() );

}

}

客户端调用运行:

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

...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值