RabbitMQ

概述(含安装)

MQ (Message Quene):翻译为消息队列,通过典型的生产者和消费者模型,生产者不断向消息队列中生产消息,消费者不断的从队列中获取消息。因为消息的生产和消费都是异步的,而且只关心消息的发送和接收,没有业务逻辑的侵入,轻松的实现系统间解耦。别名为消息中间件通过利用高效可靠的消息传递机制进行平 台无关的数据交流,并基于数据通信来进行分布式系统的集成。

MQ的分类
当今市面上有很多主流的消息中间件,如老牌的ActiveMQ、RabbitMQ,炙手可热的Kafka,阿里巴巴自主开发RocketMQ等。

MQ特点
ActiveMQ
ActiveMQ是Apache出品, 最流行的,能力强劲的开源消息总线。它是一一个完全支持JMS规范的的消息中间件。丰富的API, 多种集群架构模式让ActiveMQ在业界成为老牌的消息中间件,在中小型企业颇受欢迎!
Kafka
Kafka是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache顶级项目。Kafka主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0. 8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。
RocketMQ
RocketMQ是阿里开源的消息中间件,它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。RocketMQ思路起源于Kafka,但并不是Kafka的一个Copy,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog分发等场景。
RabbitMQ
RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。 AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。
RabbitMQ比Kafka可靠,Kafka更适合I0高吞吐的处理,一般应用在大数据日志处理或对实时性(少量延迟), 可靠性 (少量丢数据)要求稍低的场景使用,比如EK日志收集。

安装

1. RabbitMQ下载地址:https://www.rabbitmq.com/download.html;
2. erlang下载地址:http://www.erlang.org/downloads;
3. 输入指令激活插件:rabbitmq-plugins.bat enable rabbitmq_management
4. 在文件里点击sbin:rabbitmq-server.bat 开启RabbitMQ;
5. 输入网址验证:http://localhost:15672;
6. RabbitMQ命名行输入注意:
1、要在sbin文件内打开cmd
2、(查找的输入记得加上.bat)rabbitmqctl.bat help

模型

在这里插入图片描述

第一种模型(直连)
在这里插入图片描述
在上图的模型中,有以下概念:
P:生产者:也就是要发送消息的程序
C:消费者:消息的接受者,会一直等待消息的到来
queue:消息队列,图中红色部分。类似一个邮箱,可以缓存消息;生产者向其中投递消息,消费者从其中取出消息。

生产者类
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/22 14:48
 */
public class Provide {

//    生产消息
    @Test
    public void TestSendMessage() throws IOException, TimeoutException {
//        获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
//        获取连接中的通道
        Channel channel = connection.createChannel();
//        通道绑定对应的消息队列
//        ---参数1:队列名称,如果队列不存在自动创建,
//        ---参数2:用来定义队列的特性是否要持久化
//        ---参数3:是否独占队列,
//        ---参数4:是否在消费完成时自动删除队列,
//        ---参数5:额外附件参数,
        channel.queueDeclare("hello",false,false,false,null);
//        发布消息 参数1:交换机名称 ;
//                参数2:队列名称 ;
//                参数3:传递消息额外设置(可设置队列中的数据持久化) ;
//                参数4:消息的具体内容
        channel.basicPublish("","hello",null,"hello Rabbitmq".getBytes());

        channel.close();
        connection.close();
    }
}
消费者类
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/22 16:10
 */
public class Customer {
// 这里使用main方法是为了能打印System.out.println("****************"+new String(body));
    public static void main(String[] args) throws IOException, TimeoutException {
   //        获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
//        获取连接中的通道
        Channel channel = connection.createChannel();
//        通道绑定对应的消息队列
//        ---参数1:队列名称,如果队列不存在自动创建,
//        ---参数2:用来定义队列的特性是否要持久化
//        ---参数3:是否独占队列,
//        ---参数4:是否在消费完成时自动删除队列,
//        ---参数5:额外附件参数,
        channel.queueDeclare("hello",false,false,false,null);
//        消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
        channel.basicConsume( "hello",true,new DefaultConsumer(channel){

            //           byte[] body--消息队列中取出的消息
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("****************"+new String(body));
            }
        });

//        如果通道不关闭会一直监听我们的队列
//        channel.close();
//        connection.close();
    }
}
工具类(简化连接的创建)
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/22 17:03
 */
public class RabbitMQUtils {
//    定义提供连接的对象
    public static Connection getConnection(){
        try {
//        创建mq的连接工厂对象
            ConnectionFactory connectionFactory = new ConnectionFactory();
//        设置连接rabbitmq的主机
            connectionFactory.setHost("127.0.0.1");
//        设置端口号
            connectionFactory.setPort(5672);
//        连接虚拟主机名
            connectionFactory.setVirtualHost("/ems");
//        设置访问虚拟主机的用户名和密码
            connectionFactory.setUsername("ems");
            connectionFactory.setPassword("123456");
//        获取连接对象
            return connectionFactory.newConnection();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
        return null;
    }

//    关闭连接和通道
    public static void closeConnection(Channel channel,Connection connection){
        try {
            if (channel!=null)
            {
                channel.close();
            }
            if (connection!=null){
                connection.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
}
注意事项
//        通道绑定对应的消息队列
//        ---参数1:队列名称,如果队列不存在自动创建,
//        ---参数2:用来定义队列的特性是否要持久化
//        ---参数3:是否独占队列,
//        ---参数4:是否在消费完成时自动删除队列,(当消费者结束即断开连接时触发)
//        ---参数5:额外附件参数,
        channel.queueDeclare("hello",false,false,false,null);
*********生产者和消费者所绑定的消息队列里面的参数设置必须一一对应*********

第二种模型(work quene)能者多劳:

work quene,也被称为(Task queues)任务模型。当消息处理比较耗时的时候,可能生产消息的速度会远远大于消息的消费速度。长久以往,消息就会堆积越来越多,无法及时处理。此时就可以使用work模型:让多个消费者绑定到一个队列,共同消费队列中的消息。队列中的消息一旦消费,就会消失,因此任务是不会被重复执行的。

在这里插入图片描述
在上图的模型中,有以下概念:
P:生产者:也就是要发送消息的程序
C1:消费者1:消息的接受者,会一直等待消息的到来,假设完成速度较慢
C2:消费者2:消息的接受者,会一直等待消息的到来,假设完成速度快
queue:消息队列,图中红色部分。类似一个邮箱,可以缓存消息;生产者向其中投递消息,消费者从其中取出消息。

生产者
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/22 14:48
 */
public class Provide {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
//        获取连接中的通道
        Channel channel = connection.createChannel();
//        通道绑定对应的消息队列
//        ---参数1:队列名称,如果队列不存在自动创建,
//        ---参数2:用来定义队列的特性是否要持久化
//        ---参数3:是否独占队列,
//        ---参数4:是否在消费完成时自动删除队列,
//        ---参数5:额外附件参数,
        channel.queueDeclare("work",true,false,false,null);

        for (int i = 0; i <= 20; i++) {
            //        发布消息 参数1:交换机名称 ;参数2:队列名称 ;参数3:传递消息额外设置 ;参数4:消息的具体内容
            channel.basicPublish("","work", null,(i+"hello Rabbitmq").getBytes());
        }
        RabbitMQUtils.closeConnection(channel,connection);
    }
}
消费者1
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/22 22:33
 */
public class Customer1 {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
//        获取连接中的通道
        Channel channel = connection.createChannel();
//        每次只能消费一个消息,其余消息在消息队列等待---
        channel.basicQos(1);
//        通道绑定对应的消息队列
//        ---参数1:队列名称,如果队列不存在自动创建,
//        ---参数2:用来定义队列的特性是否要持久化
//        ---参数3:是否独占队列,
//        ---参数4:是否在消费完成时自动删除队列,
//        ---参数5:额外附件参数,
        channel.queueDeclare("work",true,false,false,null);
//        消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
        channel.basicConsume( "work",false,new DefaultConsumer(channel){

//           byte[] body--消息队列中取出的消息
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("*******111******"+new String(body));
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });
    }
}
消费者2
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/22 22:33
 */
public class Customer2 {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
//        获取连接中的通道
        Channel channel = connection.createChannel();
        //        通道绑定对应的消息队列
//        ---参数1:队列名称,如果队列不存在自动创建,
//        ---参数2:用来定义队列的特性是否要持久化
//        ---参数3:是否独占队列,
//        ---参数4:是否在消费完成时自动删除队列,
//        ---参数5:额外附件参数,
        channel.queueDeclare("work",true,false,false,null);
//        消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
        channel.basicConsume( "work",false,new DefaultConsumer(channel){

            //           byte[] body--消息队列中取出的消息
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("******222*******"+new String(body));
                //手动确认参 数1:手动确认消息标识参 数2:false每次确认一个
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });
    }
}
工具类(简化连接的创建)
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/22 17:03
 */
public class RabbitMQUtils {
//    定义提供连接的对象
    public static Connection getConnection(){
        try {
//        创建mq的连接工厂对象
            ConnectionFactory connectionFactory = new ConnectionFactory();
//        设置连接rabbitmq的主机
            connectionFactory.setHost("127.0.0.1");
//        设置端口号
            connectionFactory.setPort(5672);
//        连接虚拟主机名
            connectionFactory.setVirtualHost("/ems");
//        设置访问虚拟主机的用户名和密码
            connectionFactory.setUsername("ems");
            connectionFactory.setPassword("123456");
//        获取连接对象
            return connectionFactory.newConnection();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
        return null;
    }

//    关闭连接和通道
    public static void closeConnection(Channel channel,Connection connection){
        try {
            if (channel!=null)
            {
                channel.close();
            }
            if (connection!=null){
                connection.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
}

第三种模型(fanout)广播:
在这里插入图片描述
在广播模式下,消息发送流程是这样的:
可以有多个消费者
每个消费者有自己的queue (队列)
每个队列都要绑定到Exchange (交换机)
生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定。
交换机把消息发送给绑定过的所有队列
队列的消费者都能拿到消息。实现一条消息被多个消费者消费

生产者
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/22 14:48
 */
public class Provide {

//    生产消息
    @Test
    public void TestSendMessage() throws IOException, TimeoutException {
//        获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
//        获取连接中的通道
        Channel channel = connection.createChannel();
//        绑定交换机  参数1:交换机名称  参数2:交换机类型--fanout广播类型
        channel.exchangeDeclare("log","fanout");
//        发送消息
        channel.basicPublish("log","",null,"fanout type message".getBytes());
//        释放资源
        RabbitMQUtils.closeConnection(channel,connection);
    }
}
消费者1
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/22 16:10
 */
public class Customer1 {

    public static void main(String[] args) throws IOException, TimeoutException {
//        获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
//        获取连接中的通道
        Channel channel = connection.createChannel();
//        绑定交换机  参数1:交换机名称  参数2:交换机类型--fanout广播类型
        channel.exchangeDeclare("log","fanout");
//        临时队列
        String queue = channel.queueDeclare().getQueue();
//        绑定交换机和队列
        channel.queueBind(queue,"log","");
//        消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
        channel.basicConsume( queue,true,new DefaultConsumer(channel){
//           byte[] body--消息队列中取出的消息
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("******111*******"+new String(body));
            }
        });

//        如果通道不关闭会一直监听我们的队列
//        channel.close();
//        connection.close();
    }
}
消费者2
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 0:00
 */
public class Customer2 {

    public static void main(String[] args) throws IOException, TimeoutException {
//        获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
//        获取连接中的通道
        Channel channel = connection.createChannel();
//        绑定交换机  参数1:交换机名称  参数2:交换机类型--fanout广播类型
        channel.exchangeDeclare("log","fanout");
//        临时队列
        String queue = channel.queueDeclare().getQueue();
//        绑定交换机和队列
        channel.queueBind(queue,"log","");
//        消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
        channel.basicConsume( queue,true,new DefaultConsumer(channel){
            //           byte[] body--消息队列中取出的消息
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("******222*******"+new String(body));
            }
        });

//        如果通道不关闭会一直监听我们的队列
//        channel.close();
//        connection.close();
    }
}
消费者3
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 0:01
 */
public class Customer3 {

    public static void main(String[] args) throws IOException, TimeoutException {
//        获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
//        获取连接中的通道
        Channel channel = connection.createChannel();
//        绑定交换机  参数1:交换机名称  参数2:交换机类型--fanout广播类型
        channel.exchangeDeclare("log","fanout");
//        临时队列
        String queue = channel.queueDeclare().getQueue();
//        绑定交换机和队列
        channel.queueBind(queue,"log","");
//        消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
        channel.basicConsume( queue,true,new DefaultConsumer(channel){
            //           byte[] body--消息队列中取出的消息
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("******333*******"+new String(body));
            }
        });

//        如果通道不关闭会一直监听我们的队列
//        channel.close();
//        connection.close();
    }
}
工具类(简化连接的创建)
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/22 17:03
 */
public class RabbitMQUtils {
//    定义提供连接的对象
    public static Connection getConnection(){
        try {
//        创建mq的连接工厂对象
            ConnectionFactory connectionFactory = new ConnectionFactory();
//        设置连接rabbitmq的主机
            connectionFactory.setHost("127.0.0.1");
//        设置端口号
            connectionFactory.setPort(5672);
//        连接虚拟主机名
            connectionFactory.setVirtualHost("/ems");
//        设置访问虚拟主机的用户名和密码
            connectionFactory.setUsername("ems");
            connectionFactory.setPassword("123456");
//        获取连接对象
            return connectionFactory.newConnection();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
        return null;
    }

//    关闭连接和通道
    public static void closeConnection(Channel channel,Connection connection){
        try {
            if (channel!=null)
            {
                channel.close();
            }
            if (connection!=null){
                connection.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
}

第四种模型(Routing)路由:

Routing之订阅模型
在Fanout模式中,一条消息会被所有订阅的队列都消费。但是,在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。
在Direct模型下:
队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey (路由key)
消息的发送方在向Exchange发送消息时,也必须指定消息的RoutingKey。
Exchange不再把消息交给每一个绑定的队列,而是根据消息的Routing Key进行判断,只有队列的Routingkey与消息的Routing key完全一致,才会接收到消息

在这里插入图片描述
P:生产者:向Exchange发送消息, 发送消息时,会指定一 个routing key;
X:Exchange (交换机):接收生产者的消息,然后把消息递交给与routing key完全匹配的队列;
C1:消费者:其所在队列指定了需要routing key为error的消息;
C2:消费者:其所在队列指定了需要routing key为info、error、warning的消息。

生产者
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 8:55
 */
public class Provide {
    //    生产消息
    @Test
    public void TestSendMessage() throws IOException, TimeoutException {
//        获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
//        获取连接中的通道
        Channel channel = connection.createChannel();
//        绑定交换机  参数1:交换机名称  参数2:交换机类型--direct路由模式
        channel.exchangeDeclare("login","direct");
//        设置路由
        String routingKey="info";
//        发送消息
        channel.basicPublish("login",routingKey,null,"这是基于direct模型发布的routing".getBytes());
//        释放资源
        RabbitMQUtils.closeConnection(channel,connection);
    }
}
消费者1
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 8:56
 */
public class Customer1 {
    public static void main(String[] args) throws IOException, TimeoutException {
//        获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
//        获取连接中的通道
        Channel channel = connection.createChannel();
//        绑定交换机  参数1:交换机名称  参数2:交换机类型--direct路由模式
        channel.exchangeDeclare("login","direct");
//        临时队列
        String queue = channel.queueDeclare().getQueue();
//        绑定交换机和队列
        channel.queueBind(queue,"login","error");
//        消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
        channel.basicConsume( queue,true,new DefaultConsumer(channel){
            //           byte[] body--消息队列中取出的消息
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("******111*******"+new String(body));
            }
        });

//        如果通道不关闭会一直监听我们的队列
//        channel.close();
//        connection.close();
    }
}
消费者2
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 8:56
 */
public class Customer2 {
    public static void main(String[] args) throws IOException, TimeoutException {
//        获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
//        获取连接中的通道
        Channel channel = connection.createChannel();
//        绑定交换机  参数1:交换机名称  参数2:交换机类型--direct路由模式
        channel.exchangeDeclare("login","direct");
//        临时队列
        String queue = channel.queueDeclare().getQueue();
//        绑定交换机和队列
        channel.queueBind(queue,"login","info");
        channel.queueBind(queue,"login","error");
//        消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
        channel.basicConsume( queue,true,new DefaultConsumer(channel){
            //           byte[] body--消息队列中取出的消息
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("******222*******"+new String(body));
            }
        });

//        如果通道不关闭会一直监听我们的队列
//        channel.close();
//        connection.close();
    }
}
工具类(简化连接的创建)
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/22 17:03
 */
public class RabbitMQUtils {
//    定义提供连接的对象
    public static Connection getConnection(){
        try {
//        创建mq的连接工厂对象
            ConnectionFactory connectionFactory = new ConnectionFactory();
//        设置连接rabbitmq的主机
            connectionFactory.setHost("127.0.0.1");
//        设置端口号
            connectionFactory.setPort(5672);
//        连接虚拟主机名
            connectionFactory.setVirtualHost("/ems");
//        设置访问虚拟主机的用户名和密码
            connectionFactory.setUsername("ems");
            connectionFactory.setPassword("123456");
//        获取连接对象
            return connectionFactory.newConnection();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
        return null;
    }

//    关闭连接和通道
    public static void closeConnection(Channel channel,Connection connection){
        try {
            if (channel!=null)
            {
                channel.close();
            }
            if (connection!=null){
                connection.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
}

第五种模型(Topics)动态路由:

Topic类型的Exchange与Direct相比,都是可以根据RoutingKey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key 的时候使用通配符!这种模型Routingkey一般都是由一个或多个单词组成,多个单词之间以"."分割,例如: item.insert;

在这里插入图片描述

#统配符
* (star) can substitute for exactly one word.   匹配不多不少恰好一个词
# (hash) can substitute for zero or more words.  匹配一个或多个词
#如:
audit.#       匹配audit.irs.corporate或者audit.irs等
audit.*       只能匹配audit.irs 
生产者
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 9:17
 */
public class Provide {
    //    生产消息
    @Test
    public void TestSendMessage() throws IOException, TimeoutException {
//        获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
//        获取连接中的通道
        Channel channel = connection.createChannel();
//        绑定交换机  参数1:交换机名称  参数2:交换机类型--topic动态路由模式
        channel.exchangeDeclare("topics","topic");
//        设置路由
        String routingKey="user.save";
//        发送消息
        channel.basicPublish("topics",routingKey,null,"这是基于topic模型发布的动态routing".getBytes());
//        释放资源
        RabbitMQUtils.closeConnection(channel,connection);
    }
}
消费者1
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 9:17
 */
public class Customer1 {
    public static void main(String[] args) throws IOException, TimeoutException {
//        获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
//        获取连接中的通道
        Channel channel = connection.createChannel();
//        绑定交换机  参数1:交换机名称  参数2:交换机类型--topic动态路由模式
        channel.exchangeDeclare("topics","topic");
//        临时队列
        String queue = channel.queueDeclare().getQueue();
//        绑定交换机和队列
        channel.queueBind(queue,"topics","user.*");
//        消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
        channel.basicConsume( queue,true,new DefaultConsumer(channel){
            //           byte[] body--消息队列中取出的消息
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("******111*******"+new String(body));
            }
        });

//        如果通道不关闭会一直监听我们的队列
//        channel.close();
//        connection.close();
    }
}
消费者2
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 9:18
 */
public class Customer2 {
    public static void main(String[] args) throws IOException, TimeoutException {
//        获取连接对象
        Connection connection = RabbitMQUtils.getConnection();
//        获取连接中的通道
        Channel channel = connection.createChannel();
//        绑定交换机  参数1:交换机名称  参数2:交换机类型--topic动态路由模式
        channel.exchangeDeclare("topics","topic");
//        临时队列
        String queue = channel.queueDeclare().getQueue();
//        绑定交换机和队列
        channel.queueBind(queue,"topics","user.#");
//        消费消息 参数1:队列名称 ;参数2:开始消息的自动确认机制 ;参数3:消费时的回调接口 ;参数4:消息的具体内容
        channel.basicConsume( queue,true,new DefaultConsumer(channel){
            //           byte[] body--消息队列中取出的消息
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("******222*******"+new String(body));
            }
        });

//        如果通道不关闭会一直监听我们的队列
//        channel.close();
//        connection.close();
    }
}
工具类(简化连接的创建)
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/22 17:03
 */
public class RabbitMQUtils {
//    定义提供连接的对象
    public static Connection getConnection(){
        try {
//        创建mq的连接工厂对象
            ConnectionFactory connectionFactory = new ConnectionFactory();
//        设置连接rabbitmq的主机
            connectionFactory.setHost("127.0.0.1");
//        设置端口号
            connectionFactory.setPort(5672);
//        连接虚拟主机名
            connectionFactory.setVirtualHost("/ems");
//        设置访问虚拟主机的用户名和密码
            connectionFactory.setUsername("ems");
            connectionFactory.setPassword("123456");
//        获取连接对象
            return connectionFactory.newConnection();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
        return null;
    }

//    关闭连接和通道
    public static void closeConnection(Channel channel,Connection connection){
        try {
            if (channel!=null)
            {
                channel.close();
            }
            if (connection!=null){
                connection.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
}

整合SpringBoot项目

引入依赖

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

配置配置文件(RabbitTemplate用来简化操作)

spring:
    application:
        name: springboot_r abbi tmq
    rabbitmq:
        host: 10.15.0.9
        port: 5672
        username: ems
        password: 123
        virtual-host: /ems

直连模式

/**生产者(直连模式)
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 14:41
 */
@SpringBootTest(classes = SpringbootRabbitmqApplication.class)

public class TestRabbitMQ {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void Test(){
        rabbitTemplate.convertAndSend("hello","hello word");
    }

}

/**消费者(直连模式)
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 14:48
 */
@Component
@RabbitListener(queuesToDeclare = @Queue("hello"))

public class HelloCustomer {

    @RabbitHandler
    public void receive(String Message){
        System.out.println("Message"+Message);
    }
}

(work quene)默认是公平调度,如果实现能者多劳需要额外的配置

/**生产者(work quene)
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 14:41
 */
@SpringBootTest(classes = SpringbootRabbitmqApplication.class)

public class TestRabbitMQ {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void TestWork(){
        for (int i = 0; i < 10; i++) {
        rabbitTemplate.convertAndSend("Work","Work 模型");
        }
    }

}

/**消费者(work quene)
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 15:07
 */
@Component
public class WorkCustomer {

    @RabbitListener(queuesToDeclare = @Queue("hello"))
    public void receive(String Message){
        System.out.println("work"+Message);
    }

    @RabbitListener(queuesToDeclare = @Queue("hello"))
    public void receive2(String Message){
        System.out.println("work2"+Message);
    }
}

(fanout)广播

/**生产者(fanout)
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 14:41
 */
@SpringBootTest(classes = SpringbootRabbitmqApplication.class)

public class TestRabbitMQ {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void fanout(){
    rabbitTemplate.convertAndSend("log","","fanout 模型");
    }

}

/**消费者(fanout)

/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 15:17
 */
@Component
public class FanoutCustomer {

    @RabbitListener(bindings = {
            @QueueBinding(value = @Queue,    //创建临时队列
                    exchange = @Exchange(value = "log",type = "fanout")   //绑定交换机
            )
    })
    public void receive(String Message){
        System.out.println("fanout"+Message);
    }

    @RabbitListener(bindings = {
            @QueueBinding(value = @Queue,    //创建临时队列
                    exchange = @Exchange(value = "log",type = "fanout")   //绑定交换机
            )
    })
    public void receive2(String Message){
        System.out.println("fanout2"+Message);
    }
}

(Routing)路由

/**生产者(fanout)
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 14:41
 */
@SpringBootTest(classes = SpringbootRabbitmqApplication.class)

public class TestRabbitMQ {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void routing(){
    rabbitTemplate.convertAndSend("login","info","routing 模型");
    }
}

/**消费者(fanout)
/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/23 15:29
 */
@Component
public class RoutingCustomer {

    @RabbitListener(bindings = {
            @QueueBinding(value = @Queue,    //创建临时队列
                    exchange = @Exchange(value = "login",type = "direct") ,  //绑定交换机
                    key = {"info","error"}
            )
    })
    public void receive(String Message){
        System.out.println("direct"+Message);
    }

    @RabbitListener(bindings = {
            @QueueBinding(value = @Queue,    //创建临时队列
                    exchange = @Exchange(value = "login",type = "direct") ,  //绑定交换机
                    key = {"info"}
            )
    })
    public void receive2(String Message){
        System.out.println("direct2"+Message);
    }
}

(Topics)动态路由


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值