前言
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