SpringBoot2.x + RabbitMQ 實現簡單的發佈與訂閱消息

前言

MQ是消費-生產者模型的一個典型的代表,一端往消息隊列中不斷寫入消息,而另一端則可以讀取或者訂閱隊列中的消息。MQ和JMS類似,但不同的是JMS是SUN JAVA消息中間件服務的一個標準和API定義,而MQ則是遵循了AMQP協議的具體實現和產品。

在項目中,將一些無需即時返回且耗時的操作提取出來,進行了異步處理,而這種異步處理的方式大大的節省了服務器的請求響應時間,從而提高了系統的吞吐量。

RabbitMQ是一個在AMQP基礎上基於Erlang完成的,可複用的企業消息系統。他遵循Mozilla Public License開源協議

RabbitMQ 特性和基礎還有什麼不瞭解的,可以移步另外一篇博客瞭解後再進行閱讀本篇博客

簡單的示例

1、引入 RabbitMQ 的SpringBoot-starter 包

<!-- 集成RabbitMQ  -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

2、對RabbitMQ進行簡單的配置

# RabbitMQ基礎配置
spring.rabbitmq.host=192.168.8.110
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.connection-timeout=
spring.rabbitmq.virtual-host=/
# RabbitMQ監聽配置
## 初始併發量
spring.rabbitmq.listener.simple.concurrency=5
## 最大併發量
spring.rabbitmq.listener.simple.max-concurrency=15
## 簽收方式
spring.rabbitmq.listener.simple.acknowledge-mode=manual
## 最多一次消費多少條數據 -限流
spring.rabbitmq.listener.simple.prefetch=1

3、創建一個承載發送消息的對象SocketMessage

package com.hm.www.manp.entity;

import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * @author yangxiaohui
 * @Date: Create by 2018-12-5 15:38
 * @Description:
 */
@Data
public class SocketMessage implements Serializable {
    private static final long serialVersionUID = -8221467966772683998L;
    private String id;
    private String senderUser;
    private String receiverUser;
    private String content;
    private Date sendTime;
    private Date readTime;
}

4、創建一個生產(發送)消息的對象 SoketProducer

package com.hm.www.manp.producer;

import com.hm.www.manp.entity.SocketMessage;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.UUID;

/**
 * @author yangxiaohui
 * @Date: Create by 2018-12-6 14:38
 * @Description: 消息生產者
 */
@Component
public class SoketProducer {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    public void send(SocketMessage socketMessage)throws Exception{
        rabbitTemplate.convertAndSend(
            "socket-exchange", //分發消息的交換機名稱
            "socket.message",  //用來匹配消息隊列的Key
            socketMessage,	   //消息體
            new CorrelationData(socketMessage.getId())//消息id
        );
        
    }
}

5、創建一個 消費(監聽接收)消息的對象 SocketConsumer

package com.hm.www.manp.consumer;

import com.hm.www.manp.entity.SocketMessage;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import java.util.Map;

/**
 * @author yangxiaohui
 * @Date: Create by 2018-12-6 14:38
 * @Description: 消息消費端
 */
@Component
public class SocketConsumer {
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "socket-queue",durable = "true"),
            exchange = @Exchange(value = "socket-exchange",durable = "true",type = "topic"),
            key = "socket.message"
    ))
    @RabbitHandler
    public void receiveSocket(@Payload SocketMessage socketMessage, @Headers Map<String ,Object> headers,
                              Channel channel)throws Exception{
        System.out.println("-----------接收到消息--------");
        System.out.println("消息內容:"+socketMessage.toString());
        //消息確認 ACK
        channel.basicAck((Long)headers.get(AmqpHeaders.DELIVERY_TAG),false);
    }
}

6、創建一個Controller 測試消息的發送與接收 SendMessgeController

package com.hm.www.manp.controller;

import com.hm.www.manp.entity.SocketMessage;
import com.hm.www.manp.producer.SoketProducer;
import com.hm.www.manp.util.Result;
import com.hm.www.manp.util.ResultUtil;
import com.hm.www.manp.util.UuidUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**
 * @author yangxiaohui
 * @Date: Create by 2018-12-6 14:37
 * @Description:
 */
@RestController
public class SendMessgeController {
    @Autowired
    private SoketProducer soketProducer;
    @GetMapping("sendSocket")
    public Result sendSocket(@RequestParam String content) throws Exception{
        SocketMessage socketMessage = new SocketMessage();
        socketMessage.setId(UuidUtil.getUUID_32_Upper());
        socketMessage.setSenderUser("admin");
        socketMessage.setReceiverUser("zhangsan");
        socketMessage.setSendTime(new Date());
        socketMessage.setContent(content);
        soketProducer.send(socketMessage);
        return ResultUtil.success();
    }
}

7、測試消息的發送與監聽 項目啓動後訪問 http://ip:port/項目名/sendSocket?content=消息內容

在這裏插入圖片描述

8、查看後臺輸出日誌

在這裏插入圖片描述

確認能夠接收到消息 OK

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