SpringBoot集成Redis消息订阅发布

转自 https://blog.csdn.net/myNameIssls/article/details/75471012

参考 http://tramp.cincout.cn/2017/07/03/spring-nosql-2017-07-03-spring-boot-redis-pubsub/


SpringBoot集成Redis消息订阅发布

1. pom.xml文件添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2. 创建一个Redis消息接收器

package cn.tyrone.springboot.redis.message;

import java.util.concurrent.CountDownLatch;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

public class Receiver {
    private static final Logger LOGGER = LoggerFactory.getLogger(Receiver.class);

    private CountDownLatch latch;

    @Autowired
    public Receiver(CountDownLatch latch) {
        this.latch = latch;
    }

    public void receiveMessage(String message) {
        LOGGER.info("Received <" + message + ">");
        latch.countDown();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

Receiver这是一个定义了一个接收消息的方法的类。当你把这个类作为一个消息监听器来注册后,你可以自定义消息接收的方法名。本例中采用“receiveMessage”作为接收消息的方法。

3. 注册一个监听器并发送消息

Spring Data Redis 提供了使用Redis发送和接收的消息的所有的组件。我们只需要做以下配置: 
- 一个Redis连接工厂(A connection factory) 
- 一个消息监听器的容器(A message listener container) 
- 一个Redis模板(A redis template) 
我们使用redis template发送消息,把Receiver类注册为一个消息监听器以使它可以接收消息。Connection factory是授权它们连接Redis服务的。 
本例中采用的是SpringBoot默认的RedisConnectionFactory,这是一个基于jedis Redis库的JedisConnectionFactory的实例。它被注入到消息监听器和redis模板中。

编写SpringBoot启动类并注入本例需要的对象实例

package cn.tyrone.springboot.redis.message;

import java.util.concurrent.CountDownLatch;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

//https://spring.io/guides/gs/messaging-redis/

@SpringBootApplication
public class Application {
    public static final Logger LOGGER = LoggerFactory.getLogger(Application.class);

    /*
     * Redis消息监听器容器
     * 这个容器加载了RedisConnectionFactory和消息监听器
     */
    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, 
            MessageListenerAdapter listenerAdapter){
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.addMessageListener(listenerAdapter, new PatternTopic("sprinboot-redis-messaage"));
        return container;
    }

    /*
     * 将Receiver注册为一个消息监听器,并指定消息接收的方法(receiveMessage)
     * 如果不指定消息接收的方法,消息监听器会默认的寻找Receiver中的handleMessage这个方法作为消息接收的方法
     */
    @Bean
    MessageListenerAdapter listenerAdapter(Receiver receiver){
        return new MessageListenerAdapter(receiver, "receiveMessage");
    }

    /*
     * Receiver实例
     */
    @Bean
    Receiver receiver(CountDownLatch latch){
        return new Receiver(latch);
    }

    @Bean
    CountDownLatch latch(){
        return new CountDownLatch(1);
    }

    /*
     * Redis Template 用来发送消息
     */
    @Bean
    StringRedisTemplate template(RedisConnectionFactory connectionFactory){
        return new StringRedisTemplate(connectionFactory);
    }

    /*
     * 测试用例
     */
    public static void main(String[] args) throws Exception {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);

        StringRedisTemplate template = ctx.getBean(StringRedisTemplate.class);
//      CountDownLatch latch = ctx.getBean(CountDownLatch.class);

        LOGGER.info("Sending message......");
        template.convertAndSend("sprinboot-redis-messaage", "Hello, SpringBoot redis message!!!!");
//      latch.wait();

        System.exit(0);

    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84

对于本例并不十分清楚CountDownLatch latch这个的目的,在测试的过程中,加上这句代码,会抛一个异常,但是发送和接收消息都是成功的。异常信息如下:

2017-07-20 10:14:50.909  INFO 7200 --- [           main] c.t.s.redis.message.Application          : Sending message......
Exception in thread "main" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at cn.tyrone.springboot.redis.message.Application.main(Application.java:77)
  • 1
  • 2
  • 3
  • 4
  • 5

如果将此代码注释掉,该异常也将消息。同时,也并不影响消息的发布与接收。CountDownLatch 只是一个同步的辅助类,测试过程中,并没有发现这个类对测试结果的有什么帮助。



猜你喜欢

转载自blog.csdn.net/banqgg/article/details/80252710