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