Redis消息的发布/订阅

以前使用redis只是用来当做非关系型数据库来使用,提高查询的效率。最近使用到了redis的一个新功能,redis的发布订阅模式。
“发布/订阅”(publish/subscribe)模式可以实现进程间通信,订阅者可以订阅一个或多个频道(channel),而发布者可以向指定的频道发送消息,所有订阅此频道的订阅者都会收到此消息并执行相应的操作。
redis使用RedisMessageListenerContainer进行消息监听,客户程序需要自己实现MessageListener,并以指定的topic注册到RedisMessageListenerContainer,这样,在指定的topic上如果有消息,RedisMessageListenerContainer便会通知该MessageListener。下边演示在ssm框架下如何使用redis进行消息的发布/订阅。
1、spring配置文件中的配置
<?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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd ">
    <!-- jedis pool配置 --> 
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="${redis.maxActive}"/>
        <property name="maxIdle" value="${redis.maxIdle}"/>
        <property name="maxWaitMillis" value="${redis.maxWait}"/>
        <property name="testOnBorrow" value="${redis.testOnBorrow}"/>
    </bean>
    
    <!-- spring data redis -->  
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">  
        <property name="poolConfig" ref="jedisPoolConfig"></property>
		<property name="hostName" value="${redis.host}"></property>
		<property name="port" value="${redis.port}"></property>
		<property name="timeout" value="${redis.timeout}"></property>
		<property name="usePool" value="${redis.usePool}"></property> 
    </bean>  
    
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">  
        <property name="connectionFactory" ref="jedisConnectionFactory"/> 
        <property name="keySerializer">
			<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
		</property>
		<property name="valueSerializer">
			<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
		</property> 
    </bean>
    <!-- 消息接受类 -->
    <bean id="redisTestMessageListener" class="com.dongao.job.service.impl.RedisTestMessageListener"></bean>  
    <bean id="redisContainer" class="org.springframework.data.redis.listener.RedisMessageListenerContainer">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
        <property name="taskExecutor"><!-- 此处有个奇怪的问题,无法正确使用其他类型的Executor -->  
            <bean class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler">  
                <property name="poolSize" value="2"></property>  
            </bean>  
        </property>
        <property name="messageListeners">
            <map>
                <entry key-ref="redisTestMessageListener">
                    <list>
                        <!-- 普通订阅,订阅具体的频道 -->
                        <bean class="org.springframework.data.redis.listener.ChannelTopic">
                            <constructor-arg value="${redis.test.channel1}" />
                        </bean>
                        <bean class="org.springframework.data.redis.listener.ChannelTopic">
                            <constructor-arg value="${redis.test.channel2}" />
                        </bean>                       
                    </list>
                </entry>
            </map>
        </property>
    </bean> 
</beans>
配置文件中配置的是订阅了两个频道。如果是3个,上边的poolSize 配置为3,相应的list中的bean配置为三个。
2、发布消息的两个方法(频道):
@Controller
@RequestMapping(value="demo")
public class DemoController {
	//注入redis客户端jedis
	/*@Autowired
	private ShardJedisUtil jedisUtil;*/
	
	@SuppressWarnings("rawtypes")
	@Resource(name="redisTemplate")
	private RedisTemplate redisTemplate;
	
	@RequestMapping("/test")
	@ResponseBody
	public String test1(){
		String str="消息1";
		redisTemplate.convertAndSend(Config.redis_channel1, str);
		return "消息1发送成功!";
	}
	@RequestMapping("/test")
	@ResponseBody
	public String test2(){
		String str2="消息2";
		redisTemplate.convertAndSend(Config.redis_channel2, str2);
		return "消息2发送成功!";
	}
}
3、接收消息,执行操作的方法类:
@Component
public class RedisTestMessageListener implements MessageListener {
	@Override
	public void onMessage(Message message, byte[] pattern) {
		System.out.println("接受消息:"+message.toString());
	}
}
message中包含发送消息的频道和消息的内容,这个时候运行的结果会直接显示乱码:
把接受消息的方法类修改一下,把message中的内容进行序列化,就可以显示频道和内容了:
@Component
public class RedisTestMessageListener implements MessageListener {
	@SuppressWarnings("rawtypes")
	@Resource(name="redisTemplate")
	private RedisTemplate redisTemplate;
	
	@Override
	public void onMessage(Message message, byte[] pattern) {
		String topic = (String)redisTemplate.getStringSerializer().deserialize(message.getChannel());
		Object body = redisTemplate.getValueSerializer().deserialize(message.getBody());  
		String msg = String.valueOf(body);
		System.out.println(topic);
		System.out.println("接受消息:"+msg);
		
	}
}
显示结果:

  以上就是redis发布/订阅的简单使用,举个简单的应用场景的话,以门户网站为例, 当编辑更新了某推荐板块的内容后:CMS发布 清除缓存的消息到channel (推送者推送消息)门户网站的缓存系统通过channel收到 清除缓存的消息 (订阅者收到消息),更新了推荐板块的缓存。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值