RabbitMQ整合springboot

一、springboot版本和依賴

 

  • springboot 版本 2.1.5
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
  • dependencies
<dependencies>

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

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

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

    </dependencies>

二、生產端

1、yml  文件配置  

server:
  port: 8001
  servlet:
    context-path: /
spring:
  rabbitmq:
    addresses: ip:5672,ip:5672,ip:5672
    username: guest
    password: guest
    virtual-host: /
    connection-timeout: 15000

    publisher-confirms: true
    publisher-returns: true
    template:
      mandatory: true


  application:
    name: rabbit-producer
  http:
    encoding:
      charset: UTF-8
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    default-property-inclusion: NON_NULL

rabbitmq-exchange: exchange-1
rabbitmq-routingKey: springboot.abc
  1. address   server的ip地址加上端口號
  2. username  passowrd 賬號密碼
  3. virtual-host    最上層的一個域  ,例如  /order    /logistics
  4. 連接超時時間
  • 生產端的相關配置
  1. publisher-confirms  是否開啓消息確認模式,舉例:生產者發送消息到 broker(mq) ,我不確定我的消息是否100%已經投遞到mq 中,我們會進行線程監聽,mq 會返回一個成功或者是失敗的情況
  2. publisher-returns  是否開啓發布者退貨模式,舉例:生產者發送routingkey:  spring.xxx  ,queue routingkey:爲 springboot.xxx 。那麼不匹配路由規則。publisher-returns 設置爲false 的話,這條消息就丟掉了,消失了。設置爲true的話,會將消息 執行到我們指定的一對   exchange  和 queue 上。 需要和 mandatory 一起使用
  3. mandatory     是否開啓強制性消息

2、編寫發送消息方法

package com.example.producer.component;

import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.UUID;

/**
 * @Author: qiuj
 * @Description:
 * @Date: 2020-05-31 11:57
 */
@Component
public class Sender {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Value("${rabbitmq-exchange}")
    private String exchange;
    @Value("${rabbitmq-routingKey}")
    private String routingKey;

    /**
     * 這裏就是確認消息的回調監聽接口,用於確認消息是否被broker 所收到
     */
    final RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {
        @Override
        public void confirm(CorrelationData correlationData, boolean ack, String cause) {
            System.out.println("唯一id:" +  correlationData);
            System.out.println("消息是否成功投遞" + ack );
            System.out.println("如果失敗則會返回錯誤消息" + cause);
        }
    };


    public void sends (Object msg, Map<String,Object> properties) {
        //  第一步將消息包裝成boot 支持的方式
        MessageHeaders messageHeaders = new MessageHeaders(properties);
        Message<?> message = MessageBuilder.createMessage(msg,messageHeaders);
        //  指定唯一id
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        //  回調方法
        MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
            @Override
            public org.springframework.amqp.core.Message postProcessMessage(org.springframework.amqp.core.Message message) throws AmqpException {
                System.out.println("在發送消息之前的前置方法" + message);
                return message;
            }
        };
        //  前置方法
        rabbitTemplate.setConfirmCallback(confirmCallback);
        rabbitTemplate.convertAndSend(exchange,
                routingKey,
                message,
                messagePostProcessor,
                correlationData);
    }
}

三、消費端

1、yml  文件配置  

server:
  port: 8002
spring:
  rabbitmq:
    addresses: ip:5672,ip:5672,ip:5672
    username: guest
    password: guest
    virtual-host: /
    connection-timeout: 15000
    listener:
      simple:
        acknowledge-mode: manual
        concurrency: 5
        max-concurrency: 10
        prefetch: 2

  application:
    name: rabbit-consumer
  http:
    encoding:
      charset: UTF-8
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    default-property-inclusion: NON_NULL


queue-name: queue-1
queue-durable: true
exchange-name: exchange-1
exchange-topic: topic
exchange-durable: true
exchange-ignoreDeclarationExceptions: true
routingkey: springboot.*
  • 消費端的相關配置
  1. acknowledge-mode 默認auto ,也就是自動簽收消息,生產環境不建議,我們設置爲 manual  手工的進行簽收
  2. concurrency   max-concurrency  監聽器調用線程的最小數量  和最大數量
  3. prefetch     在單個請求中處理的消息個數,開啓限流,指定每次處理消息最多隻能處理2條消息

2、編寫接受消息方法

package com.example.consumer.component;


import com.rabbitmq.client.Channel;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * @Author: qiuj
 * @Description:
 * @Date: 2020-05-30 19:29
 */
@Component
public class RabbitReceive {


    /**
     * 組合使用監聽
     *  @RabbitListener @QueueBinding   @Queue  @Exchange
     * @param message
     * @param channel
     * @throws IOException
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "${queue-name}",durable = "${queue-durable}"),
            exchange = @Exchange(
                    value = "${exchange-name}",
                    type = "${exchange-topic}",
                    durable = "${exchange-durable}",
                    ignoreDeclarationExceptions = "${exchange-ignoreDeclarationExceptions}"
            ),
            key = "${routingkey}"
    ))
    @RabbitHandler
    public void onMessage (Message message, Channel channel) throws IOException {
        //  1:收到消息以後進行業務端處理
        System.out.println("消費消息:" + message.getPayload());
        //  2:處理成功之後    獲取deliveryTag   並進行手工的ACK操作,因爲我們配置文件裏配置的是   手工簽收
        //  spring.rabbitmq.listener.simple.acknowiedge-mode=manual
        Long deliveryTag = (Long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
        channel.basicAck(deliveryTag,false);

    }


}

四、 源碼

1、生產端源碼

2、消費端源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章