SpringBoot 整合 RabbitMQ讲解

RabbitMQ指令

# 服务启动相关
systemctl start|restart|stop|status rabbitmq-server

# 管理命令行,用来不使用web管理界面情况下命令操作RabbitMQ
rabbitmqctl help #可以查看更多命令

# 插件管理命令行
rabbitmq-plugins enable|list|disable
# disable 禁用  enable 启用

RabbitMQ生产和消费消息

第一种模型(直连)

一个生产者对应一个消费者

RabbitMQ生产消息
// 创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("8.142.28.95");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/ems");
connectionFactory.setUsername("wupan");
connectionFactory.setPassword("wupan");

// 获取连接对象
Connection connection = connectionFactory.newConnection();

// 获取连接通道
Channel channel = connection.createChannel();

// 通道和队列要绑定
// 参数1:队列名称,不存在自动创建
// 参数2:用来定义队列特性是否要持久化,true 持久化队列,false:不持久化
// 参数3:是否独占队列 true 独占队列;false:不独占
// 参数4 是否在消费完成自动删除队列;true:自动删除;false 不自动删除
// 参数5:额外附件参数
channel.queueDeclare("newhello",true,false,false,null);

// 参数1: 交换机名称
// 参数2:队列名称
// 参数3:传递消息额外设置
// 参数4:消息的具体内容
channel.basicPublish("","newhello",MessageProperties.PERSISTENT_TEXT_PLAIN,"服务重启,消息是否丢失".getBytes());

// 关闭通道
channel.close();
// 关闭连接
connection.close();
RabbitMQ消费消息
// 创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("8.142.28.95");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/ems");
connectionFactory.setUsername("wupan");
connectionFactory.setPassword("wupan");

// 获取连接对象
Connection connection = connectionFactory.newConnection();
// 获取连接通道
Channel channel = connection.createChannel();

// 通道绑定队列
// * 消费消息队列要和生产消息队列参数保持一致
channel.queueDeclare("newhello",true,false,false,null);

// 消费消息
// 参数1:消费队列名称
// 参数2:开启消息的自动确认机制
// 参数3:消费消息时,回调接口
channel.basicConsume("newhello", true, new DefaultConsumer(channel){
         @Override // 参数1:标签
           // 参数2 : 信封
           // 参数4:消息队列中取出的消息
        public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("new String(body)=" + new String(body));
   	}
});
第二种模型(work queue)

默认情况下,work queue消费者消费消息时,进行循环消费

生产消息
// 获取连接
Connection connection = RabbitMQUtils.getConnection();
// 获取通道
Channel channel = connection.createChannel();

// 通过通道声明队列
channel.queueDeclare("work",true,false,false,null);

// 生产消息
for (int i = 0; i < 10; i++) {
  channel.basicPublish("","work",null,(i + "hello work queue").getBytes());
 }

RabbitMQUtils.closeConnectionAndChanel(channel,connection);
消费消息
// 消费者1
Connection connection = RabbitMQUtils.getConnection();

Channel channel = connection.createChannel();

channel.queueDeclare("work",true,false,false,null);

channel.basicConsume("work",true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者-1:" + new String(body));
            }
        });

// 消费者2
Connection connection = RabbitMQUtils.getConnection();

Channel channel = connection.createChannel();

channel.queueDeclare("work",true,false,false,null);

channel.basicConsume("work",true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者-1:" + new String(body));
            }
});
消息确认机制,能者多劳,保证消息的消费的原子性和正确性
Connection connection = RabbitMQUtils.getConnection();

Channel channel = connection.createChannel();

channel.queueDeclare("work",true,false,false,null);

// 每次通道中只能放入一条消息
channel.basicQos(1);
// 参数2:true:自动确认;false:手动确认
channel.basicConsume("work",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("消费者-1:" + new String(body));
                // 参数1:队列中消息的标识;参数2:true:批量确认;false:单个确认
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
});
第三种模型(fanout)
生产消息

fanout类型,直接发送消息给交换机

// 获取连接
Connection connection = RabbitMQUtils.getConnection();
Channel channel = connection.createChannel();

// 将通道申明指定的交换机
// 参数1: 交换机名称;参数2:交换机类型 fanout:广播类型
channel.exchangeDeclare("logs","fanout");

// 发送消息
channel.basicPublish("logs","",null,"fanout type message111".getBytes());

RabbitMQUtils.closeConnectionAndChanel(channel,connection);
消费消息

绑定交换机,创建临时队列,然后再通道中绑定交换机和队列,再从队列中取出消息

// 获取连接
Connection connection = RabbitMQUtils.getConnection();
// 获取通道对象
Channel channel = connection.createChannel();

// 通道绑定交换机
channel.exchangeDeclare("logs","fanout");
//临时队列
String queue = channel.queueDeclare().getQueue();

// 绑定交换机和队列
channel.queueBind(queue,"logs","");

channel.basicConsume(queue,true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者1:" + new String(body));
            }
        });
第四种模型(drict)

生产者发送消息时,将交换机和路由key进行绑定,消费者消费消息时,要满足对应的key才能消费

第五种模型(topic)

生产者发送消息时,将交换机和路由key进行绑定,消费者消费消息时,可以通过动态路由key的方式进行消费

路由key必须是 user.add 的形式

消费者可以通过 user.* or user.# 的动态路由key进行消费

user.* 只能匹配 user.add,表示只能匹配一个单词

user.# 可以匹配 user,user.add,user.add.success等等,后面可以一直拼接,表示可以匹配0个或者多个单词

SpringBoot整合RabbitMQ模型
helloWorld模型

生产者

package com.example.demo;

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest(classes = DemoApplication.class)
@RunWith(SpringRunner.class)
class DemoApplicationTests {

    // 注入rabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void test () {
        // convertAndSend 发送消息
        // 参数1:队列名称;参数2: 消息内容
        rabbitTemplate.convertAndSend("hello_test","hello world");
    }
}

消费者

package com.example.demo;

import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class HelloCustomer {
	
    // RabbitListener监听队列名称:【hello_test】
    // RabbitListener可以注释在类上,也可以注释在方法上
    @RabbitListener(queuesToDeclare = @Queue("hello_test"))
    // RabbitHandler声明回调方法,方法名可以是任意的
    @RabbitHandler
    public void receiver (String message) {
        System.out.println("message = " + message);
    }

}
工作队列模型

生产者

package com.example.demo;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest(classes = DemoApplication.class)
@RunWith(SpringRunner.class)
public class DemoApplicationTests {

    // 注入rabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void testWork () {
        rabbitTemplate.convertAndSend("word","work模型");
    }
}

消费者

package com.example.demo.work;

import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class WorkConsumer {

    // 一个消费者
    @RabbitListener(queuesToDeclare = @Queue("work"))
    public void receiver1 (String message){
        System.out.println("message1 = " + message);
    }

    // 一个消费者
    @RabbitListener(queuesToDeclare = @Queue("work"))
    public void receiver2 (String message){
        System.out.println("message2 = " + message);
    }
}
Fanout广播模式

生产者

package com.example.demo;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest(classes = DemoApplication.class)
@RunWith(SpringRunner.class)
public class DemoApplicationTests {

    // 注入rabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;

    // fanout
    @Test
    public void testFanout() {
        rabbitTemplate.convertAndSend("exchange_logs","","springboot整合rabbitmq,发送fanout消息");
    }
}

消费者

package com.example.demo.fanout;

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 HelloFanout {

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,// 不指定名称,表示生成临时队列
                    exchange = @Exchange(value = "exchange_logs", type = "fanout") // value 交换机名称,type:发送消息类型
            )
    })
    public void receiver1(String message) {
        System.out.println("message1:" + message);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,// 不指定名称,表示生成临时队列
                    exchange = @Exchange(value = "exchange_logs", type = "fanout") // value 交换机名称,type:发送消息类型
            )
    })
    public void receiver2(String message) {
        System.out.println("message2:" + message);
    }
}
Router路由模式

生产者

package com.example.demo;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest(classes = DemoApplication.class)
@RunWith(SpringRunner.class)
public class DemoApplicationTests {

    // 注入rabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;

    // router
    @Test
    public void testRouter () {
        rabbitTemplate.convertAndSend("router_los","info","springboot整合rabbitmq,发送router消息【info】");
        rabbitTemplate.convertAndSend("router_los","error","springboot整合rabbitmq,发送router消息【error】");
    }
}

消费者

package com.example.demo.router;

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 HelloRouter {

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(value = "router_los", type = "direct"),
                	// key可以指定要生产者发送要的对应的key的消息
                    key = {"info","warn","debugger"}
            )
    })
    public void receiver1 (String message) {
        System.out.println("message1:" + message);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue, // 不指定队列名称,表示生成临时队列
                    exchange = @Exchange(value = "router_los", type = "direct"),
                    key = {"error"}
            )
    })
    public void receiver2 (String message) {
        System.out.println("message2:" + message);
    }

}
Topic模式(动态路由)模式

生产者

package com.example.demo;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest(classes = DemoApplication.class)
@RunWith(SpringRunner.class)
public class DemoApplicationTests {

    // 注入rabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;

    // topic
    @Test
    public void testTopic () {
        rabbitTemplate.convertAndSend("topic_logs","user.add.save","springboot整合rabbitmq,发送topic消息【user.add.save】");
    }
}

消费者

package com.example.demo.topic;

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 HelloTopic {

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(value = "topic_logs", type = "topic"),
                	// #可以匹配多个
                    key = {"user.#"}
            )
    })
    public void receiver1 (String message) {
        System.out.println("message1:" + message);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(value = "topic_logs", type = "topic"),
                	// * 只能匹配到一个
                    key = {"user.*"}
            )
    })
    public void receiver2 (String message) {
        System.out.println("message2:" + message);
    }
}

RabbitMQ的应用场景

异步处理
应用解耦
流量削峰
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值