redis有一个key失效监听,当你的key失效时触发,但这与我想要的效果不一样,我要的是有消息立即触发。这就是redis的另一种监听 pub/sub消息订阅,我在网上的一篇文章里看到了相关介绍,
package com.xmpp.redis.service;
import com.xmpp.connector.util.Convertor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class ReminderBroadcastEventListener implements MessageListener {
private Log logger = LogFactory.getLog(ReminderBroadcastEventListener.class);
@Autowired
private RedisTemplate redisTemplate;
/**
* 监听redis消息
*
* @param message
* @param bytes
*/
@Override
public void onMessage(Message message, byte[] bytes) {
try {
byte[] body = message.getBody();
//反序列化
String str = (String) redisTemplate.getValueSerializer().deserialize(body);
String channel=redisTemplate.getValueSerializer().deserialize(bytes);
logger.info("redis监听到消息内容:" + str);
logger.info("消息监听通道:" + channel);
} catch (Exception e) {
logger.error("-----------------------消息提醒redis监听处理失败-------------------------");
logger.error(e.getMessage(), e);
}
}
}
需要注意的是监听到消息后的处理,redis会对发送的消息进行序列化,所以这里要用redis的序列化工具反序列化。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:redis="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">
<bean id="jedisConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="#{redis.maxIdle}"/>
<property name="maxTotal" value="#{redis.maxTotal}"/>
<property name="maxWaitMillis" value="#{redis.maxWaitMillis}"/>
<property name="minEvictableIdleTimeMillis" value="#{redis.minEvictableIdleTimeMillis}"/>
<property name="numTestsPerEvictionRun" value="#{redis.numTestsPerEvictionRun}"/>
<property name="timeBetweenEvictionRunsMillis" value="#{redis.timeBetweenEvictionRunsMillis}"/>
<property name="testOnBorrow" value="#{redis.testOnBorrow}"/>
<property name="testWhileIdle" value="#{redis.testWhileIdle}"/>
bean>
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
<property name="poolConfig" ref="jedisConfig"/>
<property name="hostName" value="#{redis.hostName}"/>
<property name="port" value="#{redis.port}"/>
<property name="password" value="#{redis.password}"/>
<property name="timeout" value="#{redis.timeout}"/>
<property name="database" value="#{redis.database}"/>
bean>
<bean id="messageListener" class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter">
<constructor-arg>
<bean class="com.xmpp.redis.service.KeyExpiredListener"/>
constructor-arg>
bean>
<bean id="remindListener" class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter">
<constructor-arg>
<bean class="com.xmpp.redis.service.ReminderBroadcastEventListener"/>
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.PatternTopic">
<constructor-arg value="__keyevent@0__:expired"/>
bean>
entry>
<entry key-ref="remindListener">
<bean class="org.springframework.data.redis.listener.ChannelTopic">
<constructor-arg value="remind:topic"/>
bean>
entry>
map>
property>
bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
property>
bean>
<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="myBatisConnection"/>
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
property>
bean>
<bean id="cacheTransfer" class="com.xmpp.redis.cache.RedisCacheTransfer">
<property name="redisTemplate" ref="stringRedisTemplate" />
bean>
beans>
大部分的配置都是之前配置,我添加的监听部分如下:
将监听类bean至remindListener,然后添加到监听集合里。需要注意的是PatternTopic是用来监听key失效的。ChannelTopic才是我们想要的有消息立即触发的监听。另外
监听通道好像是可以写通配符的,但我这里只需要固定的就可以满足需求了。
String channel = "remind:topic";
//其中channel必须为string,而且“序列化”策略也是StringSerializer
//消息内容,将会根据配置文件中指定的valueSerializer进行序列化
//本例中,默认全部采用StringSerializer
//那么在消息的subscribe端也要对“发序列化”保持一致。
redisTemplate.convertAndSend(channel, "from app 1");
到这里就完成了。关于websocket相关的代码我这里没有贴出来,网上有很多相关的文章。