RabbitMQ相关知识

#介绍

RabbitMQ 是使用一种比较小众的编程语言:Erlang 语言编写的,它最早是为电信行业系统之间的可靠通信设计的,是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。

RabbitMQ 就像它的名字中的兔子一样:轻量级、迅捷,它的 Slogan,也就是宣传口号,也很明确地表明了 RabbitMQ 的特点:Messaging that just works,“开箱即用的消息队列”。也就是说,RabbitMQ 是一个相当轻量级的消息队列,非常容易部署和使用。

另外 RabbitMQ 还号称是世界上使用最广泛的开源消息队列,是不是真的使用率世界第一,我们没有办法统计,但至少是“最流行的消息中间之一”,这是没有问题的。

AMQP,即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。
基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。Erlang中的实现有RabbitMQ等。

 

 #SpringBoot集成RabbitMQ

pom配置

     <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

 

yml配置

spring:
    rabbitmq:
    host: localhost
    username: guest
    password: guest
    port: 5672

 

 配置类

@Configuration
public class RabbitConfig {

    @Value("${spring.rabbitmq.host}")
    private String host;

    @Value("${spring.rabbitmq.port}")
    private int port;

    @Value("${spring.rabbitmq.username}")
    private String username;

    @Value("${spring.rabbitmq.password}")
    private String password;


    public static final String EXCHANGE_A = "my-mq-exchange_A";
    public static final String EXCHANGE_B = "my-mq-exchange_B";
    public static final String EXCHANGE_C = "my-mq-exchange_C";


    public static final String QUEUE_A = "QUEUE_A";
    public static final String QUEUE_B = "QUEUE_B";
    public static final String QUEUE_C = "QUEUE_C";

    public static final String ROUTING_KEY_A = "spring-boot-routingKey_A";
    public static final String ROUTING_KEY_B = "spring-boot-routingKey_B";
    public static final String ROUTING_KEY_C = "spring-boot-routingKey_C";

    @Bean
    public CachingConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host, port);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setPublisherConfirms(true);
        return connectionFactory;
    }

    /**
     * 必须是prototype类型
     */
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public RabbitTemplate rabbitTemplate() {
        return new RabbitTemplate(connectionFactory());
    }

    /**
     * 针对消费者配置
     * 1. 设置交换机类型
     * 2. 将队列绑定到交换机
     * FanoutExchange: 将消息分发到所有的绑定队列,无routingkey的概念
     * HeadersExchange :通过添加属性key-value匹配
     * DirectExchange:按照routingkey分发到指定队列
     * TopicExchange:多关键字匹配
     */
    @Bean
    public DirectExchange defaultExchange() {
        return new DirectExchange(EXCHANGE_A);
    }

    @Bean
    public Queue queueA() {
        //队列持久
        return new Queue(QUEUE_A, true);
    }

    @Bean
    public Queue queueB() {
        //队列持久
        return new Queue(QUEUE_B, true);
    }

    @Bean
    public Binding binding() {
        return BindingBuilder.bind(queueA()).to(defaultExchange())
                .with(RabbitConfig.ROUTING_KEY_A);
    }

    @Bean
    public Binding bindingB(){
        return BindingBuilder.bind(queueB()).to(defaultExchange()).with(RabbitConfig.ROUTING_KEY_B);
    }

}

 

生产消息

@Slf4j
@Component
public class MsgProducer implements RabbitTemplate.ConfirmCallback {

    /**
     * 由于rabbitTemplate的scope属性设置为ConfigurableBeanFactory.SCOPE_PROTOTYPE,所以不能自动注入
     */
    private RabbitTemplate rabbitTemplate;

    /**
     * 构造方法注入rabbitTemplate
     */
    @Autowired
    public MsgProducer(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
        //rabbitTemplate如果为单例的话,那回调就是最后设置的内容
        rabbitTemplate.setConfirmCallback(this);
    }

    public void sendMsg(String content) {
        CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
        //把消息放入ROUTING_KEY_A对应的队列当中去,对应的是队列A
        rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_A, RabbitConfig.ROUTING_KEY_A, content, correlationId);
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        log.info(" 回调id:{}", correlationData);
        if (ack) {
            log.info("消息成功消费");
        } else {
            log.info("消息消费失败:{}", cause);
        }
    }

}

 

消费者一


@Slf4j
@Component
@RabbitListener(queues = RabbitConfig.QUEUE_A)
public class MsgReceiverOne {

@RabbitHandler
public void process(String message) {
log.info("处理器one接收处理队列A当中的消息:{}", message);
}

}

 

消费者二

@Slf4j
@Component
@RabbitListener(queues = RabbitConfig.QUEUE_A)
public class MsgReceiverTwo {

    @RabbitHandler
    public void process(String message) {
        log.info("处理器two接收处理队列A当中的消息:{}", message);
    }

}

 

测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class RabbitMqTestCase {

    @Autowired
    private MsgProducer msgProducer;

    @Test
    public void contextLoads() {
        for (int i = 0; i < 10; i++) {
            msgProducer.sendMsg("这是一条测试消息,来自RabbitMQ");
        }
    }

}

 

posted @ 2020-05-29 17:29  家乐先生  阅读(151)  评论(0编辑  收藏  举报