八、RabbitMQ与SpringBoot集成

1.maven依赖

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

2.SpringBoot配置

spring.application.name=springboot-rabbitmq
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.virtual-host=/

3.RabbitMQ配置

3.1 ConnectionFactory:发布确认

@Bean
public ConnectionFactory connectionFactory() {
    CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
    connectionFactory.setAddresses(addresses + ":" + port);
    connectionFactory.setUsername(username);
    connectionFactory.setPassword(password);
    connectionFactory.setVirtualHost(virtualHost);
    // 发布确认
    connectionFactory.setPublisherConfirms(publisherConfirms);
    return connectionFactory;
}

3.2 RabbitTemplate:失败通知,发布确认回调

@Bean
public RabbitTemplate rabbitTemplate() {
    RabbitTemplate template = new RabbitTemplate(connectionFactory());
    template.setMandatory(true);
    template.setConfirmCallback(confirmCallback());
    template.setReturnCallback(returnCallback());
    return template;
}

3.3 声明交换器与队列

 //===============以下是验证topic Exchange==========
@Bean
public Queue queueEmailMessage() {
    return new Queue(RmConst.QUEUE_TOPIC_EMAIL);
}

@Bean
public Queue queueUserMessages() {
    return new Queue(RmConst.QUEUE_TOPIC_USER);
}

@Bean
public TopicExchange topicExchange() {
    return new TopicExchange(RmConst.EXCHANGE_TOPIC);
}

3.4 队列与交换器绑定

@Bean
public Binding bindingEmailExchangeMessage() {
    return BindingBuilder.bind(queueEmailMessage()).to(topicExchange()).with("sb.*.email");
}

@Bean
public Binding bindingUserExchangeMessages() {
    return BindingBuilder.bind(queueUserMessages()).to(topicExchange()).with("sb.*.user");
}

3.5 SimpleMessageListenerContainer:队列绑定消费者,手动确认

 @Bean
public SimpleMessageListenerContainer messageContainer() {
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
    container.setQueues(userQueue());
    container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    container.setMessageListener(userReceiver);
    return container;
}

3.6 生产者失败通知与发布确认回调

@Bean
public RabbitTemplate.ConfirmCallback confirmCallback() {
    return new RabbitTemplate.ConfirmCallback() {
        @Override
        public void confirm(CorrelationData correlationData, boolean ack, String cause) {
            if (ack) {
                System.out.println("发送者确认发送给mq成功");
            } else {
                //处理失败的消息
                System.out.println("发送者发送给mq失败,考虑重发:" + cause);
            }
        }
    };
}

@Bean
public RabbitTemplate.ReturnCallback returnCallback(){
    return new RabbitTemplate.ReturnCallback(){
        @Override
        public void returnedMessage(Message message,
                                    int replyCode,
                                    String replyText,
                                    String exchange,
                                    String routingKey) {
            System.out.println("无法路由的消息,需要考虑另外处理。");
            System.out.println("Returned replyText:"+replyText);
            System.out.println("Returned exchange:"+exchange);
            System.out.println("Returned routingKey:"+routingKey);
            String msgJson  = new String(message.getBody());
            System.out.println("Returned Message:"+msgJson);
        }
    };
}

3.7 完整配置

package com.zava.config;

import com.zava.constant.RmConst;
import com.zava.hello.UserReceiver;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author: Rab
 * @Date: 2020-04-17 09:35
 * @Description:
 */
@Configuration
public class RabbitConfig {

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

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

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

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

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

    @Value("${spring.rabbitmq.publisher-confirms}")
    private boolean publisherConfirms;

    @Autowired
    private UserReceiver userReceiver;

    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setAddresses(addresses + ":" + port);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost(virtualHost);
        connectionFactory.setPublisherConfirms(publisherConfirms);
        return connectionFactory;
    }

    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
        return new RabbitAdmin(connectionFactory);
    }

    @Bean
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(connectionFactory());
        template.setMandatory(true);
        template.setConfirmCallback(confirmCallback());
        template.setReturnCallback(returnCallback());
        return template;
    }

    //===============使用了RabbitMQ系统缺省的交换器==========
    @Bean
    public Queue userQueue() {
        return new Queue(RmConst.QUEUE_USER);
    }

    @Bean
    public Queue helloQueue() {
        return new Queue(RmConst.QUEUE_HELLO);
    }

    //===============以下是验证topic Exchange==========
    @Bean
    public Queue queueEmailMessage() {
        return new Queue(RmConst.QUEUE_TOPIC_EMAIL);
    }

    @Bean
    public Queue queueUserMessages() {
        return new Queue(RmConst.QUEUE_TOPIC_USER);
    }

    @Bean
    public TopicExchange topicExchange() {
        return new TopicExchange(RmConst.EXCHANGE_TOPIC);
    }

    @Bean
    public Binding bindingEmailExchangeMessage() {
        return BindingBuilder.bind(queueEmailMessage()).to(topicExchange()).with("sb.*.email");
    }

    @Bean
    public Binding bindingUserExchangeMessages() {
        return BindingBuilder.bind(queueUserMessages()).to(topicExchange()).with("sb.*.user");
    }

    //===============以上是验证topic Exchange==========

    //===============以下是验证Fanout Exchange==========
    @Bean
    public Queue AMessage() {
        return new Queue("sb.fanout.A");
    }

    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange(RmConst.EXCHANGE_FANOUT);
    }

    @Bean
    public Binding bindingExchangeA(Queue AMessage, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(AMessage).to(fanoutExchange);
    }

    //===============以上是验证Fanout Exchange的交换器==========
    //===============消费者确认==========
    @Bean
    public SimpleMessageListenerContainer messageContainer() {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
        container.setQueues(userQueue());
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        container.setMessageListener(userReceiver);
        return container;
    }

    //===============生产者发送确认==========
    @Bean
    public RabbitTemplate.ConfirmCallback confirmCallback() {
        return new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                if (ack) {
                    System.out.println("发送者确认发送给mq成功");
                } else {
                    //处理失败的消息
                    System.out.println("发送者发送给mq失败,考虑重发:" + cause);
                }
            }
        };
    }
    @Bean
    public RabbitTemplate.ReturnCallback returnCallback(){
        return new RabbitTemplate.ReturnCallback(){
            @Override
            public void returnedMessage(Message message,
                                        int replyCode,
                                        String replyText,
                                        String exchange,
                                        String routingKey) {
                System.out.println("无法路由的消息,需要考虑另外处理。");
                System.out.println("Returned replyText:"+replyText);
                System.out.println("Returned exchange:"+exchange);
                System.out.println("Returned routingKey:"+routingKey);
                String msgJson  = new String(message.getBody());
                System.out.println("Returned Message:"+msgJson);
            }
        };
    }
}

4.发送消息

  • FanoutSender
package com.zava.fanout;

import com.zava.constant.RmConst;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 */
@Component
public class FanoutSender {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void send(String msg) {
        String sendMsg = msg +"---"+ System.currentTimeMillis();;
        System.out.println("FanoutSender : " + sendMsg);
        this.rabbitTemplate.convertAndSend(RmConst.EXCHANGE_FANOUT, "",sendMsg);
    }

}
  • TopicSender
package com.zava.topic;

import com.zava.constant.RmConst;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 */
@Component
public class TopicSender {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void send() {
        String msg1 = "I am email mesaage msg======";
        System.out.println("TopicSender send the 1st : " + msg1);
        this.rabbitTemplate.convertAndSend(RmConst.EXCHANGE_TOPIC, RmConst.RK_EMAIL, msg1);

        String msg2 = "I am user mesaages msg########";
        System.out.println("TopicSender send the 2nd : " + msg2);
        this.rabbitTemplate.convertAndSend(RmConst.EXCHANGE_TOPIC, RmConst.RK_USER, msg2);

        String msg3 = "I am error mesaages msg";
        System.out.println("TopicSender send the 3rd : " + msg3);
        this.rabbitTemplate.convertAndSend(RmConst.EXCHANGE_TOPIC, "errorkey", msg3);
    }
}
  • DefaultSender
package com.zava.hello;

import com.zava.constant.RmConst;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @Author: Rab
 * @Date: 2020-04-17 10:40
 * @Description:
 */
@Component
public class DefaultSender {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void send(String msg) {
        String sendMsg = msg +"---"+ System.currentTimeMillis();;
        System.out.println("Sender : " + sendMsg);
        this.rabbitTemplate.convertAndSend(RmConst.QUEUE_HELLO, sendMsg);
        this.rabbitTemplate.convertAndSend(RmConst.QUEUE_USER, sendMsg);
    }
}
  • 发送统一入口
package com.zava.controller;

import com.zava.fanout.FanoutSender;
import com.zava.hello.DefaultSender;
import com.zava.topic.TopicSender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 */
@RestController
@RequestMapping("/rabbit")
public class RabbitTest {

    @Autowired
    private DefaultSender defaultSender;

    @Autowired
    private TopicSender topicSender;

    @Autowired
    private FanoutSender fanoutSender;

    /**
     * 普通类型测试
     */
    @GetMapping("/hello")
    public void hello() {
        defaultSender.send("hellomsg!");
    }

    /**
     * topic exchange类型rabbitmq测试
     */
    @GetMapping("/topicTest")
    public void topicTest() {
        topicSender.send();
    }

    /**
     * fanout exchange类型rabbitmq测试
     */
    @GetMapping("/fanoutTest")
    public void fanoutTest() {
        fanoutSender.send("hellomsg:OK");
    }
}
  • 用到的常量类
package com.zava.constant;

/**
 */
public class RmConst {

    public final static String QUEUE_HELLO = "sb.hello";
    public final static String QUEUE_USER = "sb.user";

    public final static String QUEUE_TOPIC_EMAIL = "sb.info.email";
    public final static String QUEUE_TOPIC_USER = "sb.info.user";
    public final static String RK_EMAIL = "sb.info.email";
    public final static String RK_USER = "sb.info.user";

    public final static String EXCHANGE_TOPIC = "sb.exchange";
    public final static String EXCHANGE_FANOUT = "sb.fanout.exchange";
}

5.消费消息

5.1 第一种方式:RabbitListener + RabbitHandler

package com.zava.fanout;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 */
@Component
@RabbitListener(queues = "sb.fanout.A")
public class FanoutReceiver {

    @RabbitHandler
    public void process(String hello) {
        System.out.println("FanoutReceiver : " + hello);
    }

}

5.2 第二种方式:RabbitMQ配置进行绑定 + ChannelAwareMessageListener

  • RabbitMQ配置进行绑定
@Bean
public SimpleMessageListenerContainer messageContainer() {
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
    container.setQueues(userQueue());
    container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    container.setMessageListener(userReceiver);
    return container;
}
  • 实现ChannelAwareMessageListener监听消息
package com.zava.hello;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.stereotype.Component;

/**
 * @Author: Rab
 * @Date: 2020-04-17 10:27
 * @Description:
 */
@Component
public class UserReceiver implements ChannelAwareMessageListener {
    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        try {
            String msg = new String(message.getBody());
            System.out.println("UserReceiver>>>>>>>接收到消息:"+msg);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            System.out.println("UserReceiver>>>>>>消息已消费");
        } catch (Exception e) {
            System.out.println(e.getMessage());
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            System.out.println("UserReceiver>>>>>>拒绝消息,要求Mq重新派发");
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值