本文所用技术简单,如有错误,对各位造成的误导,请及时联系系作者本身修正。如需转载,请注明出处,谢谢!
Redis是天生支持订阅/发布的,本文使用的技术是基于spring-redis的MessageListenerAdapter。MessageListenerAdapter的设计思路是使用代理来实现MessageListener的onMessage方法。下面先上配置:
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans" 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">
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}"/>
<property name="maxTotal" value="${redis.maxTotal}"/>
<property name="testOnBorrow" value="true"/>
bean>
<bean id="connectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${redis.conn.host}"/>
<property name="port" value="${redis.conn.port}"/>
<property name="poolConfig" ref="jedisPoolConfig"/>
<property name="password" value="${redis.password}"/>
bean>
<bean id="keySerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
<bean id="valueSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="keySerializer" ref="keySerializer"/>
<property name="valueSerializer" ref="valueSerializer"/>
bean>
<bean id="messageDelegateListener" class="org.hoffman.learning.common.redis.mq.RedisMessageDelegateListener">
bean>
<bean id="messageListener"
class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter">
<property name="delegate" ref="messageDelegateListener"/>
<property name="stringSerializer" ref="keySerializer"/>
<property name="defaultListenerMethod" value="handleMessage"/>
<property name="serializer" ref="valueSerializer"/>
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="test4RedisMessage"/>
bean>
entry>
map>
property>
bean>
beans>
方法很简单,主要是一个sendMessage方法。当然你可以根据自己的需要,抽象出一个接口来根据不同的序列化机制,用途来实现这个发布方:
public class RedisMessageSender {
private RedisTemplate redisTemplate;
public void sendMessage(String channel, Serializable message) {
redisTemplate.convertAndSend(channel, message);
}
public RedisTemplate getRedisTemplate() {
return redisTemplate;
}
public void setRedisTemplate(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
}
RedisMessageDelegateListener实现了接口MessageDelegate 。作为例子,本文主要实现第四个接口,其形式如下:
public interface MessageDelegate {
// public void handleMessage(String message);
//
// public void handleMessage(Map, ?> message);
//
// public void handleMessage(byte[] message);
//
// public void handleMessage(Serializable message);
// pass the channel/pattern as well
public void handleMessage(Serializable message, String channel);
}
MessageDelegate 的默认实现给一个:
@Service
public class RedisMessageDelegateListener implements MessageDelegate {
@Override
public void handleMessage(Serializable message, String channel) {
//什么都不做,只输出
if(message == null){
System.out.println("null");
} else if(message.getClass().isArray()){
System.out.println(Arrays.toString((Object[]) message));
} else if(message instanceof List>) {
System.out.println(message);
} else if(message instanceof Map , ?>) {
System.out.println(message);
} else {
System.out.println(ToStringBuilder.reflectionToString(message));
}
}
}
写一个测试类,来测试一把
public class RedisMessagerMainThread {
public static Logger logger = LoggerFactory.getLogger(RedisMessagerMainThread.class);
public static void main(String[] args) {
new ClassPathXmlApplicationContext("classpath:/applicationContext.xml");;
while (true) {
try {
System.out.println("current time: " + new Date());
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:/applicationContext.xml"})
public class RedisMessageSenderTest {
@Autowired
RedisMessageSender redisMessageSender;
@Test
public void testPublishMessage() throws Exception {
String msg = "Hello,Redis!";
redisMessageSender.sendMessage("test4RedisMessage", msg); //发布字符串消息
Integer[] values = new Integer[]{21341,123123,12323};
//这里使用的redisContainer里的topic
redisMessageSender.sendMessage("test4RedisMessage", values); //发布一个数组消息
}
}
测试结果
current time: Mon May 15 11:04:17 CST 2017
[21341, 123123, 12323]
java.lang.String@39f3e025[value={H,e,l,l,o,,,R,e,d,i,s,!},hash=938209376]
current time: Mon May 15 11:04:20 CST 2017