Spring Data Redis实现订阅与发布
参考:
【Spring Data Redis实现一个订阅/发布系统】--
https://my.oschina.net/zhzhenqin/blog/85422
【Spring Data Redis
】--
https://docs.spring.io/spring-data/redis/docs/1.7.8.RELEASE/reference/html/#redis:pubsub:subscribe
1、redis.propertie配置
![](https://i-blog.csdnimg.cn/blog_migrate/770864924d93dfeadf0187325b12a4bb.png)
2、spring-pool.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 加载jdbc.properties文件(一般加载多个文件时
可考虑使用此方式) -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
<value>classpath:redis.properties</value>
</list>
</property>
</bean>
<!-- 配置DRUID连接池(这个连接池的说明:
http://github.com 在搜索栏输入druid查找)
-->
<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter"
lazy-init="true">
<description>状态过滤器</description>
<!-- 通过slowSqlMillis用来配置SQL慢的标准 -->
<property name="slowSqlMillis" value="3000" />
<!-- 以日志形式输出执行效率慢的SQL -->
<property name="logSlowSql" value="true" />
<!-- 通过mergeSql属性,合并SQL -->
<property name="mergeSql" value="true" />
</bean>
<!--配置DruidDataSource连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close" init-method="init" lazy-init="true">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="${jdbc.initialSize}" />
<!-- 连接池最大数量 -->
<property name="maxActive" value="${jdbc.maxActive}" />
<!-- 连接池最小空闲 -->
<property name="minIdle" value="${jdbc.minIdle}" />
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="${jdbc.maxWait}" />
<!--配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。 -->
<property name="useUnfairLock" value="true" />
<property name="defaultReadOnly" value="false" />
<!-- 通过配置StatFilter,打开监控台统计功能 -->
<property name="proxyFilters">
<list>
<ref bean="stat-filter" />
</list>
</property>
<!--<property name="connectionProperties" value="password=${username}"/>-->
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<property name="validationQuery" value="SELECT 1 from DUAL" />
<property name="timeBetweenLogStatsMillis" value="${jdbc.timeBetweenLogStatsMillis}" />
</bean>
</beans>
3、spring-redis.xml配置
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:redis="http://www.springframework.org/schema/redis"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/redis
http://www.springframework.org/schema/redis/spring-redis-1.0.xsd"
default-autowire="byName"
default-lazy-init="true">
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<!-- redis服务器中心 -->
<bean id="connectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="poolConfig" ref="poolConfig" />
<property name="port" value="${redis.port}" />
<property name="hostName" value="${redis.host}" />
<property name="password" value="${redis.password}" />
<property name="timeout" value="${redis.timeout}"></property>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<!-- 如果不配置Serializer,那么存储的时候只能使用String,如果用对象类型存储,那么会提示错误 can't cast to String!!!-->
<property name="keySerializer">
<!--对key的默认序列化器。默认值是StringSerializer-->
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<!--是对value的默认序列化器,默认值是取自DefaultSerializer的JdkSerializationRedisSerializer。-->
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
</property>
<!--存储Map时key需要的序列化配置-->
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<!--存储Map时value需要的序列化配置-->
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
</property>
</bean>
<bean id="redisUtil" class="com.csun.dryer.utils.RedisUtil">
<property name="redisTemplate" ref="redisTemplate" />
</bean>
<bean id="messageListener" class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter">
<constructor-arg>
<bean class="com.csun.dryer.service.impl.MessageDelegateImpl"/>
<!-- <bean class="com.csun.dryer.device.MyRedisKeyExpiredMessageDelegate"/> -->
</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">
<list>
<!-- 频道订阅 -->
<bean class="org.springframework.data.redis.listener.ChannelTopic">
<constructor-arg value="ChatRoom" />
</bean>
<!-- 模式订阅 -->
<!--
<bean class="org.springframework.data.redis.listener.PatternTopic">
<constructor-arg value="__key*__:expired" />
</bean> -->
</list>
</entry>
</map>
</property>
</bean>
</beans>
4、监听器接口MessageDelegate
public interface MessageDelegate {
void handleMessage(String message);
void handleMessage(Map message);
void handleMessage(byte[] message);
void handleMessage(Serializable message);
void handleMessage(Serializable message, String channel);
}
5、监听器实现类MessageDelegateImpl
public class MessageDelegateImpl implements MessageDelegate {
/* (non-Javadoc)
* @see com.csun.dryer.service.MessageDelegate#handleMessage(java.lang.String)
*/
@Override
public void handleMessage(String message) {
// TODO Auto-generated method stub
System.out.println("handleMessage 1 : " + message);
}
/* (non-Javadoc)
* @see com.csun.dryer.service.MessageDelegate#handleMessage(java.util.Map)
*/
@Override
public void handleMessage(Map message) {
// TODO Auto-generated method stub
System.out.println("handleMessage 2 : " + message.toString());
}
/* (non-Javadoc)
* @see com.csun.dryer.service.MessageDelegate#handleMessage(byte[])
*/
@Override
public void handleMessage(byte[] message) {
// TODO Auto-generated method stub
System.out.println("handleMessage 3 : " + message.toString());
}
/* (non-Javadoc)
* @see com.csun.dryer.service.MessageDelegate#handleMessage(java.io.Serializable)
*/
@Override
public void handleMessage(Serializable message) {
// TODO Auto-generated method stub
System.out.println("handleMessage 4 : " + message.toString());
}
/* (non-Javadoc)
* @see com.csun.dryer.service.MessageDelegate#handleMessage(java.io.Serializable, java.lang.String)
*/
@Override
public void handleMessage(Serializable message, String channel) {
// TODO Auto-generated method stub
System.out.println("handleMessage 5 : " + ((String)message) + "channel: " + channel);
}
}
6、订阅程序SubMain
public class SubMain {
public static void main(String[] args) {
new ClassPathXmlApplicationContext("spring-pool.xml","spring-redis.xml");
while (true) { //这里是一个死循环,目的就是让进程不退出,用于接收发布的消息
try {
System.out.println("current time: " + new Date());
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
7、发布程序PubMain
public class PubMain {
private RedisUtil redisUtil;
@Before
public void before() {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring-pool.xml","spring-redis.xml");
redisUtil = (RedisUtil)ac.getBean("redisUtil", RedisUtil.class);
}
@Test
public void testPublishMessage() throws Exception {
String msg = "Hello, Redis!";
redisUtil.sendMessage("ChatRoom", msg);
}
}
8、测试结果
先运行订阅程序
![](https://i-blog.csdnimg.cn/blog_migrate/dc86e4df1c86cafede74a157a0713d55.png)
运行发布程序
![](https://i-blog.csdnimg.cn/blog_migrate/44068f70ab8d37b69211682426a53015.png)