springboot-rabbitmq-docker

本文详细介绍了如何在SpringBoot应用中集成RabbitMQ,包括安装RabbitMQ镜像、配置SpringBoot依赖、实现队列发送、路由发送及topic模式发送。同时,探讨了消息消费、ack模式、发送确认及消息重试机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.安装rabbitmq

//下载镜像,我下载的这个lastest镜像没有web功能,也就是15672端口没有反应
docker pull rabbitmq
//启动镜像,这里15672端口没办法用,使用的话下载其他镜像
 docker run -d --hostname my-rabbit --name rabbit -e RABBITMQ_DEFAULT_USER=user -e RABBITMQ_DEFAULT_PASS=password -p 15672:15672 -p 5672:5672 rabbitmq

2.配置springboot

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
spring.rabbitmq.host=192.168.134.132
spring.rabbitmq.username=user
spring.rabbitmq.password=password
spring.rabbitmq.port=5672

3.进行简单的队列发送,路由发送,topic模式发送

(1)对指定队列进行发送和接收:

package com.example.demo.web;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;

/**
 * @Auther: gaoyang
 * @Date: 2018/12/5 14:13
 * @Description:
 */
@RestController
@Configuration
public class MyWeb {

    @Autowired
    RabbitTemplate rabbitTemplate;

    //注册一个队列
    @Bean
    public Queue queue1() {
        return new Queue("myQueue");
    }


     @GetMapping("/b")
    public Object b(){
        rabbitTemplate.convertAndSend("myQueue","测试");
        return "ok";
    }

}

(2)对指定路由发送数据

    //第二个队列    
    @Bean
    public Queue queue2() {
        return new Queue("test222");
    }
 
   //注册一个交换机
    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("fan");
    }
 
    //将两个队列绑定到该路由器   
    @Bean
    public Binding binding3(){
        return BindingBuilder.bind(queue2()).to(fanoutExchange());
    }
    @Bean
    public Binding binding4(){
        return BindingBuilder.bind(queue1()).to(fanoutExchange());
    }
    //第二个队列名称忽略,这样就会向两个队列同时发送信息
    @GetMapping("/c")
    public Object c(){
        rabbitTemplate.convertAndSend("fan",null,"测试");
        return "ok";
    }

(3)topic动态交换机名称发送

    //注册一个动态交换机
    @Bean
    public TopicExchange topicExchange() {
        return new TopicExchange("jiaohuan");
    }
    

    //这里绑定队列后路由名称为topic.msg
    @Bean
    public Binding binding(@Qualifier("queue1") Queue queue1, TopicExchange topicExchange) {
        return BindingBuilder.bind(queue1).to(topicExchange).with("topic.msg");
    }

    //这里的名字使用.#,#代表0到多个字符,*代表一个字符.所以这里会正则的匹配
    @Bean
    public Binding binding2(@Qualifier("queue2") Queue queue2, TopicExchange topicExchange) {
        return BindingBuilder.bind(queue2).to(topicExchange).with("topic.#");
    }

//所以这里发送的话,路由名称为topic.msg会像两个队列同时发送,如果为topic.aaa其他等则只会正则的匹配一个队列;

4.消费类

@Component
public class Consumer {

    @RabbitListener(queues = "test111")
    public void listen(List list){
        System.out.println(list.get(0));
    }
    @RabbitListener(queues = "test222")
    public void listen2(String list){
        System.out.println(list);
    }

}

 

4.ack模式

spring.rabbitmq.host=192.168.134.132
spring.rabbitmq.username=user
spring.rabbitmq.password=password
spring.rabbitmq.port=5672

# 开启发送确认
spring.rabbitmq.publisher-confirms=true
# 开启发送失败退回
spring.rabbitmq.publisher-returns=true
# 开启ACK
spring.rabbitmq.listener.direct.acknowledge-mode=manual
spring.rabbitmq.listener.simple.acknowledge-mode=manual

配置发送消息的异步结果:(该处可以做业务处理,重新发送等),此处是发送方到mq的结果

@Component
public class MyConfirm implements RabbitTemplate.ConfirmCallback {
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (!ack) {
            System.out.println("Confirm 消息发送失败" + cause + correlationData.toString());
        } else {
            System.out.println("Confirm 消息发送成功 ");
        }
    }
}

mq到接收方的结果:如果失败可以使用重新发送

@Component
public class MyCallBack implements RabbitTemplate.ReturnCallback {
    @Autowired
    RabbitTemplate rabbitTemplate;
    @Override
    public void returnedMessage(Message message, int i, String s, String s1, String s2) {
        System.out.println("sender return " + message.toString()+"==="+i+"==="+s1+"==="+s2);
        rabbitTemplate.send(message);
    }
}

 

 

发送信息:

    @GetMapping("/d")
    public Object d() {
        rabbitTemplate.setReturnCallback(myCallBack);
        rabbitTemplate.setConfirmCallback(myConfirm);
        rabbitTemplate.convertAndSend("test333", "测试");
        return "ok";
    }

消息接收者:

 @RabbitListener(queues = "test333")
    public void listen3(String list, Channel channel, Message message) throws IOException {
        System.out.println(list);
        try {
            int a= 100/0;
            //告诉服务器收到这条消息 已经被我消费了 可以在队列删掉 这样以后就不会再发了 否则消息服务器以为这条消息没处理掉 后续还会在发
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            System.out.println("receiver success");
        } catch (Exception e) {
            e.printStackTrace();
            //丢弃这条消息
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false,false);
            System.out.println("receiver fail");
        }
    }

channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);

以上第一个参数是该条数据的index标识,后面参数是是否全部处理小于当前index值得信息为接收成功;

channel.basicNack(message.getMessageProperties().getDeliveryTag(), false,false);

以上第一个和第二个参数与上面同理,这里是是否全部置于接收失败,第三个参数为是否重新接收数据;

具体的方法含义可以参数这个---链接;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值