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

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清晨先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值