SpringBoot整合RabbitMQ

本文介绍了如何在SpringBoot应用中集成RabbitMQ,包括在POM文件中引入依赖,配置MQ连接参数,启用RabbitMQ相关注解,以及设置消息确认机制。同时展示了创建消息生产者和消费者的方法,以及使用AmqpAdmin创建交换机、队列和绑定的过程。
摘要由CSDN通过智能技术生成

1、pom文件导入坐标

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

2、application.properties中MQ的配置

# RabbitMQ配置
spring.rabbitmq.host=192.168.200.130
spring.rabbitmq.port=5672
# 虚拟主机配置
spring.rabbitmq.virtual-host=/
# 开启发送端消息抵达Broker确认
spring.rabbitmq.publisher-confirms=true
# 开启发送端消息抵达Queue确认
spring.rabbitmq.publisher-returns=true
# 只要消息抵达Queue,就会异步发送优先回调returnfirm 设不设置都可以
spring.rabbitmq.template.mandatory=true
# 手动ack消息,不使用默认的消费端确认
spring.rabbitmq.listener.simple.acknowledge-mode=manual

3、主启动类

@EnableDiscoveryClient //开启服务注册发现功能
@EnableRabbit//开启RabbitMQ注解
@SpringBootApplication
public class GulimallOrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(GulimallOrderApplication.class, args);
    }

}

4、MyRabbitConfig.java 配置RabbitMQ

package com.acm.gulimall.order.config;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/**
 * @Description
 * @Auther: QZ
 * @Date: 2023/2/7 - 02 - 07 - 15:51
 * @version: 1.0
 */
@Configuration
public class MyRabbitConfig {


    @Autowired
    private RabbitTemplate rabbitTemplate;


    /**
     * 给RabbitMQ发送消息是对象装换成json发送
     * 默认是实体类转换成流进行发送
     * @return
     */
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    /**
     * 定制RabbitTemplate
     * 1、服务收到消息就会回调
     *      1、spring.rabbitmq.publisher-confirms: true
     *      2、设置确认回调
     * 2、消息正确抵达队列就会进行回调
     *      1、spring.rabbitmq.publisher-returns: true
     *         spring.rabbitmq.template.mandatory: true
     *      2、设置确认回调ReturnCallback
     *
     * 3、消费端确认(保证每个消息都被正确消费,此时才可以broker删除这个消息)
     *
     */
    @PostConstruct  //MyRabbitConfig对象创建完成以后,执行这个方法
    public void initRabbitTemplate() {

        /**
         * 1、只要消息抵达Broker就ack=true
         * correlationData:当前消息的唯一关联数据(这个是消息的唯一id)
         * ack:消息是否成功收到
         * cause:失败的原因
         */
        //设置确认回调
        rabbitTemplate.setConfirmCallback((correlationData,ack,cause) -> {
            System.out.println("confirm...correlationData["+correlationData+"]==>ack:["+ack+"]==>cause:["+cause+"]");
        });


        /**
         * 只要消息没有投递给指定的队列,就触发这个失败回调
         * message:投递失败的消息详细信息
         * replyCode:回复的状态码
         * replyText:回复的文本内容
         * exchange:当时这个消息发给哪个交换机
         * routingKey:当时这个消息用哪个路邮键
         */
        rabbitTemplate.setReturnCallback((message,replyCode,replyText,exchange,routingKey) -> {
            System.out.println("Fail Message["+message+"]==>replyCode["+replyCode+"]" +
                    "==>replyText["+replyText+"]==>exchange["+exchange+"]==>routingKey["+routingKey+"]");
        });
    }
}

5、测试类,创建消息生产者
 

创建交换机,队列,binging,同时创建生产者

package com.acm.gulimall.order;


import com.acm.gulimall.order.entity.OrderEntity;
import com.acm.gulimall.order.entity.OrderReturnApplyEntity;
import com.acm.gulimall.order.entity.OrderReturnReasonEntity;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.annotation.Order;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Date;
import java.util.UUID;

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class GulimallOrderApplicationTests {

    @Autowired
    private AmqpAdmin amqpAdmin;

    @Autowired
    private RabbitTemplate rabbitTemplate;


    /**
     * 给队列发送消息
     */
    @Test
    public void sendMessage(){
        //发送字符串
        String msg = "hello word!";

        for (int i = 0; i < 10; i++) {
            //发送对象
            if(i%2==0){
                OrderReturnReasonEntity returnReasonEntity = new OrderReturnReasonEntity();
                returnReasonEntity.setId(1L);
                returnReasonEntity.setCreateTime(new Date());
                returnReasonEntity.setName("hh-"+i);
                rabbitTemplate.convertAndSend("hello-java-exchange","hello-java",returnReasonEntity);
            }else {
                OrderEntity orderEntity = new OrderEntity();
                orderEntity.setOrderSn(UUID.randomUUID().toString());
                rabbitTemplate.convertAndSend("hello-java-exchange","hello-java",orderEntity);
            }

        }
    }

    /**
     * 1、如何创建Exchange、Queue、Binding
     *      1)、使用AmqpAdmin进行创建
     * 2、如何收发消息
     */
    @Test
    public void createExchange() {
        /**
         * String name, boolean durable, boolean autoDelete, Map<String, Object> arguments
         */
        DirectExchange directExchange = new DirectExchange("hello-java-exchange", true, false);
        amqpAdmin.declareExchange(directExchange);
        log.info("Exchange[{}]创建成功","hello-java-exchange");
    }

    /**
     * String name, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
     * boolean durable:是否持久化,就是开关机都存在
     * boolean exclusive:是否排他,只能进行和一个交换机进行绑定
     */
    @Test
    public void createQueue(){
        Queue queue = new Queue("hello-java-queue",true,false,false);
        amqpAdmin.declareQueue(queue);
        log.info("Queue[{}]创建成功","hello-java-queue");
    }

    /**
     * String destination, 【目的地】
     * Binding.DestinationType destinationType, 【目的地类型】
     * String exchange, 【交换机】
     * String routingKey, 【绑定的键】
     * Map<String, Object> arguments【参数】
     */
    @Test
    public void createBinging(){
        Binding binding = new Binding("hello-java-queue",
                Binding.DestinationType.QUEUE,
                "hello-java-exchange",
                "hello-java",null);
        amqpAdmin.declareBinding(binding);
        log.info("Binding[{}]创建成功","hello-java");
    }

}

6、服务端,消息接收者

package com.acm.gulimall.order.service.impl;

import com.acm.gulimall.order.entity.OrderEntity;
import com.acm.gulimall.order.entity.OrderReturnReasonEntity;
import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.acm.common.utils.PageUtils;
import com.acm.common.utils.Query;

import com.acm.gulimall.order.dao.OrderItemDao;
import com.acm.gulimall.order.entity.OrderItemEntity;
import com.acm.gulimall.order.service.OrderItemService;

@RabbitListener(queues = {"hello-java-queue"})
@Service("orderItemService")
public class OrderItemServiceImpl extends ServiceImpl<OrderItemDao, OrderItemEntity> implements OrderItemService {

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<OrderItemEntity> page = this.page(
                new Query<OrderItemEntity>().getPage(params),
                new QueryWrapper<OrderItemEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * queues:声明需要监听的队列
     * channel:当前传输数据的通道
     * 获取实际消息内容有两种方式:
     *  方式一:在方法参数列表中直接声明出来
     *  方式二:从请求体中取出消息的二进制形式,然后通过JSON反序列化即可
     */
    //@RabbitListener(queues = {"hello-java-queue"})
    @RabbitHandler
    public void revieveMessage(Message message, OrderReturnReasonEntity entity, Channel channel) {
        // 请求体,序列化存储(本例中已使用Jackson2JsonMessageConverter序列化器作JSON序列化存储)
        byte[] body = message.getBody();
        // 请求头
        MessageProperties messageProperties = message.getMessageProperties();
        // JSON反序列得到消息内容对象
        OrderReturnReasonEntity reason = JSONObject.parseObject(body, OrderReturnReasonEntity.class);
        System.out.println("接受到的消息对象" + message);
        System.out.println("接受到的消息内容" + reason);
        System.out.println("接受到的消息内容" + entity);
    }

    @RabbitHandler
    public void revieveMessage(Message message, OrderEntity entity, Channel channel) {
        // 请求体,序列化存储(本例中已使用Jackson2JsonMessageConverter序列化器作JSON序列化存储)
        byte[] body = message.getBody();
        // 请求头
        MessageProperties properties = message.getMessageProperties();
        // channel内按顺序自增的long类型消息标签
        long deliveryTag = properties.getDeliveryTag();
        // JSON反序列得到消息内容对象
        OrderEntity reason = JSONObject.parseObject(body, OrderEntity.class);
        System.out.println("接受到的消息对象" + message);
        System.out.println("接受到的消息内容" + reason);
        System.out.println("接受到的消息内容" + entity);
        try {
            System.out.println(deliveryTag);
            if (deliveryTag % 2 == 0) {
                // 手动确认,消息会从unacked中删除,total数量减1
                // boolean multiple:是否批量签收
                channel.basicAck(deliveryTag, false);
                System.out.println("消息接受成功:"+deliveryTag);
            } else {
                // 手动拒签
                // boolean multiple:是否批量拒签
                // boolean requeue:当前拒签消息是否发回服务器重新入队
                // 重新入队的消息会继续发送 等待条件满足进行消费
                channel.basicNack(deliveryTag, false, true);
                System.out.println("消息拒签:"+deliveryTag);
            }
        } catch (IOException e) {
            // 网络中断
            e.printStackTrace();
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值