Spring MVC + redis 消息的订阅发布

发布订阅(pub/sub)是一种消息通信模式,主要的目的是解耦消息发布者和消息订阅者之间的耦合,这点和设计模式中的观察者模式比较相似。pub /sub不仅仅解决发布者和订阅者直接代码级别耦合也解决两者在物理部署上的耦合。redis作为一个pub/sub server,在订阅者和发布者之间起到了消息路由的功能。订阅者可以通过subscribe和psubscribe命令向redis server订阅自己感兴趣的消息类型,redis将消息类型称为通道(channel)。当发布者通过publish命令向redis server发送特定类型的消息时。订阅该消息类型的全部client都会收到此消息。这里消息的传递是多对多的。一个client可以订阅多个 channel,也可以向多个channel发送消息。

初次使用redis的消息订阅发布,在网上搜了一圈发现都是比较笨的在配置文件配置消息的形式,自己折腾着换了种方法实现,贴出来自己记录一下。

先在maven引入对应的jar,注意版本问题,版本不对应会出很多奇奇怪怪的问题。

<dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-redis</artifactId>
	<version>1.6.2.RELEASE</version>
</dependency>
<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>2.8.2</version>
</dependency>
然后是redis的配置文件redis-context.xml。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.zavfwei.redis" />

    <!-- scanner redis properties  -->
    <context:property-placeholder location="classpath:config/redis.properties" file-encoding="utf-8" ignore-unresolvable="true"/>

       <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
              <property name="maxIdle" value="${cache.redis.maxIdle}" />
              <property name="maxTotal" value="${cache.redis.maxTotal}" />
              <property name="testOnBorrow" value="${cache.redis.testOnBorrow}" />
       </bean>

       <bean id="redisConnectionFactory"
             class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
              <property name="usePool" value="true"></property>
              <property name="hostName" value="${cache.redis.host}" />
              <property name="port" value="${cache.redis.port}" />
              <property name="password" value="${cache.redis.password}" />
              <property name="timeout" value="${cache.redis.timeout}" />
              <property name="database" value="${cache.redis.db}"></property>
              <constructor-arg index="0" ref="jedisPoolConfig" />
       </bean>

       <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
              <property name="connectionFactory" ref="redisConnectionFactory" />
              <property name="keySerializer" ref="stringRedisSerializer" />
              <property name="valueSerializer" ref="stringRedisSerializer" />
              <property name="hashKeySerializer" ref="stringRedisSerializer" />
              <property name="hashValueSerializer" ref="stringRedisSerializer" />
       </bean>

    <bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
        <property name="connectionFactory" ref="redisConnectionFactory" />
        <property name="keySerializer" ref="stringRedisSerializer" />
        <property name="valueSerializer" ref="stringRedisSerializer" />
        <property name="hashKeySerializer" ref="stringRedisSerializer" />
        <property name="hashValueSerializer" ref="stringRedisSerializer" />
    </bean>

       <bean id="stringRedisSerializer"
             class="org.springframework.data.redis.serializer.StringRedisSerializer" >
       </bean>
</beans>

消息订阅发布的一个工具类RedisCacheDao。

package com.zavfwei.redis.core;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;

import javax.annotation.Resource;

/**
 * Created by winton on 2017/3/21 0021.
 */
@Service
public class RedisCacheDao<T> {

    @Resource(name = "redisTemplate")
    public RedisTemplate redisTemplate;

    /**
     * 发布消息到指定的频道
     *
     * @param channel
     * @param message
     */
    public void publish(final String channel, final String message) {
        redisTemplate.execute(new RedisCallback<Object>() {
            public Object doInRedis(final RedisConnection connection)
                    throws DataAccessException {
                ((Jedis) connection.getNativeConnection()).publish(channel, message);
                return null;
            }
        });
    }

    /**
     * 订阅给定的一个或多个频道的信息
     *
     * @param jedisPubSub
     * @param channels
     */
    public void subscribe(final JedisPubSub jedisPubSub, final String... channels) {
        redisTemplate.execute(new RedisCallback<Object>() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                ((Jedis) connection.getNativeConnection()).subscribe(jedisPubSub, channels);
                return null;
            }
        });
    }
}

测试消息的订阅发布类。

package com.zavfwei.service.other;

import com.zavfwei.RedisKey;
import com.zavfwei.redis.core.RedisCacheDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.JedisPubSub;

import javax.annotation.PostConstruct;

/**
 * Created by winton on 2017/3/15 0015.
 */
@Service
public class WithdrawService {

    @Autowired
    private RedisCacheDao redisCacheDao;

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @PostConstruct
    public void init(){
        new Thread(){
            @Override
            public void run() {
                redisCacheDao.subscribe(new JedisPubSub() {
                    @Override
                    public void onMessage(String channel, String message) {
                        log.debug("redis通知,channel={},message={}",channel,message);
                        if(channel.equals(RedisKey.TXAPPLY_CHANNEL)){

                        }
                    }
                },RedisKey.TXAPPLY_CHANNEL);
            }
        }.start();
    }

    public void publish(){
        redisCacheDao.publish(RedisKey.TXAPPLY_CHANNEL,"massage");
    }
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值