springboot集成rabbitmq

一、添加依赖

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

二、配置服务

#配置rabbitmq的安装地址、端口以及账户信息
#注意port 15672是管理端的端口
spring.rabbitmq.host=192.168.184.134
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin

三、编写生产者

package com.host.mq;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
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;

@Component
public class ProductMessage implements RabbitTemplate.ConfirmCallback {
    private static final Logger LOGGER = LoggerFactory.getLogger(ProductMessage.class);

    @Autowired
    private RabbitTemplate rabbitTemplate;

    private static final String EXCHANG = "test_exchang";
    private static final String ROUNTING_KEY = "meng_key";

    public void send() {
        //rabbitTemplate.convertAndSend(EXCHANG, ROUNTING_KEY, "hello world");
        String str = "hellow woo";
        MessageProperties properties = new MessageProperties();
        Message message = new Message(str.getBytes(), properties);
        rabbitTemplate.send(EXCHANG, ROUNTING_KEY, message);
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        LOGGER.info("=====correlationData= " + correlationData);
        if (ack) {
            LOGGER.info("消息确认成功:");
        } else {
            LOGGER.info("消息确认失败:" + cause);
        }
    }
}

四、编写消费者
这里通过@RabbitListener注解在方法上来监听消息,并通过路由ke绑定exchange和queue。@RabbitListener可以在类和方法中使用,在类中注解@RabbitListener的话,方法中必须添加@RabbitHandler,才会生效。
如果消费者使用public void process(Message message)接收消息,那么@RabbitListener必须注解在方法上。

package com.host.mq;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class ConsumerMessage {
    private static final Logger LOGGER = LoggerFactory.getLogger(ConsumerMessage.class);

    @RabbitListener(bindings = {@QueueBinding(value = @Queue("testqueue"),exchange = @Exchange(name = "test_exchang"),
            key="meng_key")})
    public void process(Message message) {
        LOGGER.info("========ConsumerMessage=====" + new String(message.getBody()));
    }
}

执行程序发送消息,下面日志显示接收成功

2020-03-01 21:01:37.608  INFO 2740 --- [io-10020-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2020-03-01 21:01:37.608  INFO 2740 --- [io-10020-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2020-03-01 21:01:37.633  INFO 2740 --- [io-10020-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 25 ms
2020-03-01 21:01:37.743  INFO 2740 --- [cTaskExecutor-1] com.host.mq.ConsumerMessage              : ========ConsumerMessage=====(Body:'hello world' MessageProperties [headers={}, contentType=text/plain, contentEncoding=UTF-8, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, redelivered=false, receivedExchange=test_exchang, receivedRoutingKey=meng_key, deliveryTag=1, consumerTag=amq.ctag-kw_1CoA72CT7z23K9oThCQ, consumerQueue=testqueue])
2020-03-01 21:01:37.743  INFO 2740 --- [cTaskExecutor-1] com.host.mq.ConsumerMessage              : ========ConsumerMessage=====hello world

五、手动确认机制

手动确认在spring-boot中配置方法:
spring.rabbitmq.listener.simple.acknowledge-mode = manual

1、消费成功手动确认方法:
void basicAck(long deliveryTag, boolean multiple) throws IOException;
deliveryTag:该消息的index
multiple:是否批量确认。true:将一次性ack所有小于deliveryTag的消息。
消费者成功处理消息后,手动调用channel.basicAck(message.getMessageProperties().getDeliveryTag(), false)方法对消息进行消费确认。
@RabbitListener(bindings = {@QueueBinding(value = @Queue("testqueue"),exchange = @Exchange(name = "test_exchang"),
            key="meng_key")})
    public void process(Message message, Channel channel) {
        LOGGER.info("========ConsumerMessage=====" + new String(message.getBody()));
        try {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            try {
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
void basicNack(long deliveryTag, boolean multiple, boolean requeue) throws IOException;
deliveryTag:该消息的index。
multiple:是否批量. true:将一次性拒绝所有小于deliveryTag的消息。
requeue:被拒绝的是否重新入队列。

void basicReject(long deliveryTag, boolean requeue) throws IOException;
deliveryTag:该消息的index。
requeue:被拒绝的是否重新入队列。

channel.basicNack 方法与 channel.basicReject 方法区别在于basicNack可以批量拒绝多条消息,而basicReject一次只能拒绝一条消息。

如果消费端既没有设置basicAck,也没有设置basicNack 。这是消息会一直在Unacked中,如果消费者服务器断开后,消息回到Ready中等待重新消费。当消费端服务器重新启动后,会再次消费这条消息。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值