RabbitMq的学习分享

Rabbitmq的学习分享



一、RabbitMq简介

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
官网对应模式介绍:https://www.rabbitmq.com/getstarted.html
在这里插入图片描述

二、Rabbitmq的安装与配置

可以参考这个: https://blog.csdn.net/qq_35332494/article/details/108528524

三、学习工厂模式

1. 简单模式

1.1 步骤分析:

在这里插入图片描述

1.2 简单模式分析:

在这里插入图片描述

1.3 Java代码进行编写
1.3.1 创建一个Maven工程’

导入ampq的依赖:

<dependencies>
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.6.0</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
1.3.2 创建生产者类

Producer_HelloWorld.java

package com.cy.producer;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * @author cy
 * @create 2020-09-10-11:00
 * @Description 发送消息
 */
public class Producer_HelloWorld {
    public static void main(String[] args) throws Exception{
        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //2.设置参数
        factory.setHost("********");//ip 不设置默认为localhost
        factory.setPort(5672); //端口 默认5672
        factory.setVirtualHost("**"); //虚拟机 默认是 /
        factory.setUsername("***");//用户名 默认guest
        factory.setPassword("****"); //密码 默认是 guest
        //3.创建连接 Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();
        //5.创建队列Queue
        /*queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
            queue:     队列名称
            durable:    是否持久化,当mq重启之后还在
            exclusive:
                    *是否独占,只能有一个消费者监听这队列
                    *当Connection关闭时,是否删除队列
            autoDelete:是否自动删除,当没有Consumer时,自动删除掉
            arguments:参数
        */
        //如果没没有一个叫Hello_World的队列,则会创建
        channel.queueDeclare("Hello_Word", true, false, false, null);
        //6.发送消息
        /*basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
            exchange: 交换机名称,简单模式下交换机会默认使用的 ""
            routingKey: 路由名称
            props: 配置信息
            body:  发送的消息数据
         */
        String body = "Hello rabbitmq~~~";
        channel.basicPublish("", "Hello_Word", null, body.getBytes());

        //7.释放资源
        channel.close();
        connection.close();
    }
}

运行之后,查看:
在这里插入图片描述
没有错误,登录rabbitmq管理界面查看队列:
在这里插入图片描述
创建成功,并且Ready列存在一条消息.

1.3.3 创建消费者类

Consumer_HelloWorld.java

package com.cy.consumer;

import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author cy
 * @create 2020-09-10-11:24
 * @Description 消费信息
 */
public class Consumer_HelloWord {
    public static void main(String[] args) throws Exception{
        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //2.设置参数
        factory.setHost("********");//ip 不设置默认为localhost
        factory.setPort(5672); //端口 默认5672
        factory.setVirtualHost("**"); //虚拟机 默认是 /
        factory.setUsername("***");//用户名 默认guest
        factory.setPassword("****"); //密码 默认是 guest
        //3.创建连接 Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();
      
        //5.消费信息
        /*
         * basicConsume(String queue, boolean autoAck, Consumer callback)
         *  queue: 队列名称
         *  autoAck: 是否自动确认
         *  callback:  回调对象
         */
        DefaultConsumer consumer = new DefaultConsumer(channel){
            /**
             * 回调方法,当收到信息后,会自动执行该方法
             * @param consumerTag  标识
             * @param envelope 获取一些信息,交换机,路由key
             * @param properties 配置信息
             * @param body 数据
             * @throws IOException
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("consumerTag: "+consumerTag);
                System.out.println("Exchange: "+envelope.getExchange());
                System.out.println("RoutingKey: "+envelope.getRoutingKey());
                System.out.println("properties: "+properties);
                System.out.println("body: "+ new String(body));
            }
        };
        /*
         * basicConsume(String queue, boolean autoAck, Consumer callback)
         *  queue: 队列名称
         *  autoAck: 是否自动确认
         *  callback:  回调对象
         */
        channel.basicConsume("Hello_Word", true, consumer);
    }
}

运行之后,进行查看:
在这里插入图片描述
消息已经成功打印,查看Rabbitmq管理界面:
在这里插入图片描述
消息被消费者消费,成功.

2. 工作队列模式

2.1 模式说明

在这里插入图片描述

2.2 代码编写
2.2.1 创建工作队列生产者类

创建Producer_WorkQueue.java

package com.cy.producer;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * @author cy
 * @create 2020-09-10-11:00
 * @Description 发送消息
 */
public class Producer_WorkQueue {
    public static void main(String[] args) throws Exception{

        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //2.设置参数
         factory.setHost("********");//ip 不设置默认为localhost
        factory.setPort(5672); //端口 默认5672
        factory.setVirtualHost("**"); //虚拟机 默认是 /
        factory.setUsername("***");//用户名 默认guest
        factory.setPassword("****"); //密码 默认是 guest
        //3.创建连接 Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();

        //5.创建队列Queue
        /*queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
            queue:     队列名称
            durable:    是否持久化,当mq重启之后还在
            exclusive:
                    *是否独占,只能有一个消费者监听这队列
                    *当Connection关闭时,是否删除队列
            autoDelete:是否自动删除,当没有Consumer时,自动删除掉
            arguments:参数
        */
        //如果没没有一个叫Hello_World的队列,则会创建
        channel.queueDeclare("work_queues", true, false, false, null);


        //6.发送消息
        /*basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
            exchange: 交换机名称,简单模式下交换机会默认使用的 ""
            routingKey: 路由名称
            props: 配置信息
            body:  发送的消息数据
         */
        for (int i = 0; i <10 ; i++) {
            String body = i + "Hello rabbitmq~~~";
            channel.basicPublish("", "work_queues", null, body.getBytes());
        }
        //7.释放资源
        channel.close();
        connection.close();
    }
}

运行之后,查看:
在这里插入图片描述
运行成功,来查看rabbitmq后台管理页面:
在这里插入图片描述
已经存在队列work_queues,并且有10条消息.

2.2.2 创建工作队列消费者类

由于可以有多个消费者队列,这里创建两个:
Consumer_WorkQueues1.java

package com.cy.consumer;

import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author cy
 * @create 2020-09-10-11:24
 * @Description 消费信息
 */
public class Consumer_WorkQueues1 {
    public static void main(String[] args) throws Exception{
        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //2.设置参数
        factory.setHost("********");//ip 不设置默认为localhost
        factory.setPort(5672); //端口 默认5672
        factory.setVirtualHost("**"); //虚拟机 默认是 /
        factory.setUsername("***");//用户名 默认guest
        factory.setPassword("****"); //密码 默认是 guest
        //3.创建连接 Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();
        
        //5.消费信息
        /*
         * basicConsume(String queue, boolean autoAck, Consumer callback)
         *  queue: 队列名称
         *  autoAck: 是否自动确认
         *  callback:  回调对象
         */
        DefaultConsumer consumer = new DefaultConsumer(channel){
            /**
             * 回调方法,当收到信息后,会自动执行该方法
             * @param consumerTag  标识
             * @param envelope 获取一些信息,交换机,路由key
             * @param properties 配置信息
             * @param body 数据
             * @throws IOException
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
              /*  System.out.println("consumerTag"+consumerTag);
                System.out.println("Exchange"+envelope.getExchange());
                System.out.println("RoutingKey"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("body"+ new String(body));*/
                System.out.println("body1: "+new String(body));
            }
        };
         /*
         * basicConsume(String queue, boolean autoAck, Consumer callback)
         *  queue: 队列名称
         *  autoAck: 是否自动确认
         *  callback:  回调对象
         */
        channel.basicConsume("work_queues", true, consumer);
    }
}

Consumer_WorkQueues2.java

package com.cy.consumer;

import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author cy
 * @create 2020-09-10-11:24
 * @Description 消费信息
 */
public class Consumer_WorkQueues1 {
    public static void main(String[] args) throws Exception{
        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //2.设置参数
        factory.setHost("********");//ip 不设置默认为localhost
        factory.setPort(5672); //端口 默认5672
        factory.setVirtualHost("**"); //虚拟机 默认是 /
        factory.setUsername("***");//用户名 默认guest
        factory.setPassword("****"); //密码 默认是 guest
        //3.创建连接 Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();
        
        //5.消费信息
        /*
         * basicConsume(String queue, boolean autoAck, Consumer callback)
         *  queue: 队列名称
         *  autoAck: 是否自动确认
         *  callback:  回调对象
         */
        DefaultConsumer consumer = new DefaultConsumer(channel){
            /**
             * 回调方法,当收到信息后,会自动执行该方法
             * @param consumerTag  标识
             * @param envelope 获取一些信息,交换机,路由key
             * @param properties 配置信息
             * @param body 数据
             * @throws IOException
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
              /*  System.out.println("consumerTag"+consumerTag);
                System.out.println("Exchange"+envelope.getExchange());
                System.out.println("RoutingKey"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("body"+ new String(body));*/
                System.out.println("body1: "+new String(body));
            }
        };
         /*
         * basicConsume(String queue, boolean autoAck, Consumer callback)
         *  queue: 队列名称
         *  autoAck: 是否自动确认
         *  callback:  回调对象
         */
        channel.basicConsume("work_queues", true, consumer);
    }
}

点击运行,查看控制台1和控制台2:
提示:这里需要注意的是,需要先开启两个消费者,在开启生产者,因为开启消费者顺序会存在一前一后.所以我是先开启了两个队列消费者,在开启生产者.
在这里插入图片描述
在这里插入图片描述
再查看rabbitmq后台管理界面:
在这里插入图片描述
成功.

2.3 小小的总结

在这里插入图片描述
我们再来看这张图,C1和C2共同消费一个queue中的消息,但是都是轮流的,可以从上述上述控制台1和2看出,轮流消费,你一个我一个那种.属于竞争关系.

3. Pub/Sub 订阅模式

3.1 模式说明

在这里插入图片描述

3.2 代码编写
3.2.1 创建Pub/Sub生产者类

Producer_PubSub.java

package com.cy.producer;

import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author cy
 * @create 2020-09-10-11:24
 * @Description 生产信息,通过特定模式发送
 */
public class Producer_PubSub {
    public static void main(String[] args) throws Exception {
        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //2.设置参数
        factory.setHost("********");//ip 不设置默认为localhost
        factory.setPort(5672); //端口 默认5672
        factory.setVirtualHost("**"); //虚拟机 默认是 /
        factory.setUsername("***");//用户名 默认guest
        factory.setPassword("****"); //密码 默认是 guest
        //3.创建连接 Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();

        //5.创建交换机
        /*
        exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments)
            exchange:  交换机名称
            type:      交换机类型
                     DIRECT("direct"), :定向
                    FANOUT("fanout"),  :扇形(广播),发送消息到每一个与之绑定的队列
                    TOPIC("topic"),    :通配符的方式
                    HEADERS("headers");:参数匹配
            durable:     是否持久化
            autoDelete:  是否自动删除
            internal:    内部使用(一般false)
            arguments:   参数
         */

        String exchangeName = "test_fanout";
        channel.exchangeDeclare(exchangeName, BuiltinExchangeType.FANOUT,true,false,false,null);//采用广播类型的交换机
        //6.创建队列
        String queue1Name = "test_fanout_queue1";
        String queue2Name = "test_fanout_queue2";
         /*queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
            queue:     队列名称
            durable:    是否持久化,当mq重启之后还在
            exclusive:
                    *是否独占,只能有一个消费者监听这队列
                    *当Connection关闭时,是否删除队列
            autoDelete:是否自动删除,当没有Consumer时,自动删除掉
            arguments:参数
        */
        channel.queueDeclare(queue1Name, true, false, false, null);
        channel.queueDeclare(queue2Name, true, false, false, null);

        //7.绑定队列和交换机
        /*
                queueBind(String queue, String exchange, String routingKey)

                queue:     队列名称
                exchange:   交换机名称
                routingKey:  路由键,绑定规则: 如果交换机规则为fanout,routingKey设置为 ""
         */
            channel.queueBind(queue1Name,exchangeName,"");
            channel.queueBind(queue2Name,exchangeName,"");

        //8.发送消息
        String body = "日志信息:张三调用了findAll方法 .....  日志级别info....";
        /*basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
            exchange: 交换机名称,简单模式下交换机会默认使用的 ""
            routingKey: 路由键名称
            props: 配置信息
            body:  发送的消息数据
         */
        channel.basicPublish(exchangeName, "", null, body.getBytes());
        //9.释放资源
        channel.close();
        connection.close();
    }
}

运行之后,查看:
在这里插入图片描述
没有错误,查看rabbitmq管理后台是否存在队列以及消息:
在这里插入图片描述
提示:由于交换机类型为广播类型,又有创建了两个队列和交换机进行绑定,所以,会存在两个队列并都存有一条消息.

3.2.2 创建Pub/Sub消费者类

同样的,创建两个消费者类
Consumer_PubSub1.java

package com.cy.consumer;

import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author cy
 * @create 2020-09-10-11:24
 * @Description 消费信息
 */
public class Consumer_PubSub1 {
    public static void main(String[] args) throws Exception{

        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //2.设置参数
        factory.setHost("********");//ip 不设置默认为localhost
        factory.setPort(5672); //端口 默认5672
        factory.setVirtualHost("**"); //虚拟机 默认是 /
        factory.setUsername("***");//用户名 默认guest
        factory.setPassword("****"); //密码 默认是 guest
        //3.创建连接 Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();
        
        //5.消费信息
        DefaultConsumer consumer = new DefaultConsumer(channel){
            /**
             * 回调方法,当收到信息后,会自动执行该方法
             * @param consumerTag  标识
             * @param envelope 获取一些信息,交换机,路由key
             * @param properties 配置信息
             * @param body 数据
             * @throws IOException
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
              /*  System.out.println("consumerTag"+consumerTag);
                System.out.println("Exchange"+envelope.getExchange());
                System.out.println("RoutingKey"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("body"+ new String(body));*/
                System.out.println("body1: "+new String(body));
                System.out.println("将日志打印到控制台......");
            }
        };
        String queue1Name = "test_fanout_queue1";
        String queue2Name = "test_fanout_queue2";
         /*
         * basicConsume(String queue, boolean autoAck, Consumer callback)
         *  queue: 队列名称
         *  autoAck: 是否自动确认
         *  callback:  回调对象
         */
        channel.basicConsume(queue1Name, true, consumer);

    }
}

Consumer_PubSub1.java

package com.cy.consumer;

import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author cy
 * @create 2020-09-10-11:24
 * @Description 消费信息
 */
public class Consumer_PubSub2 {
    public static void main(String[] args) throws Exception{

        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //2.设置参数
        factory.setHost("********");//ip 不设置默认为localhost
        factory.setPort(5672); //端口 默认5672
        factory.setVirtualHost("**"); //虚拟机 默认是 /
        factory.setUsername("***");//用户名 默认guest
        factory.setPassword("****"); //密码 默认是 guest
        //3.创建连接 Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();
 
        //5.消费信息
        DefaultConsumer consumer = new DefaultConsumer(channel){
            /**
             * 回调方法,当收到信息后,会自动执行该方法
             * @param consumerTag  标识
             * @param envelope 获取一些信息,交换机,路由key
             * @param properties 配置信息
             * @param body 数据
             * @throws IOException
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
              /*  System.out.println("consumerTag"+consumerTag);
                System.out.println("Exchange"+envelope.getExchange());
                System.out.println("RoutingKey"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("body"+ new String(body));*/
                System.out.println("body1: "+new String(body));
                System.out.println("将日志保存到数据库......");
            }
        };
        String queue1Name = "test_fanout_queue1";
        String queue2Name = "test_fanout_queue2";
         /*
         * basicConsume(String queue, boolean autoAck, Consumer callback)
         *  queue: 队列名称
         *  autoAck: 是否自动确认
         *  callback:  回调对象
         */
        channel.basicConsume(queue2Name, true, consumer);
    }
}

开启消费者1和消费者2,查看控制台:
在这里插入图片描述
在这里插入图片描述
两个消费者都消费了消息
再查看rabbitmq管理后台:
在这里插入图片描述
两个队列都无消息.

3.3 小小的总结

在这里插入图片描述

4. Routing 路由模式

4.1 模式说明

在这里插入图片描述

4.2 代码编写
4.2.1 创建 路由生产者

Producer_Routing.java

package com.cy.producer;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * @author cy
 * @create 2020-09-10-11:24
 * @Description 消费信息
 */
public class Producer_Routing {
    public static void main(String[] args) throws Exception {

        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //2.设置参数
        factory.setHost("********");//ip 不设置默认为localhost
        factory.setPort(5672); //端口 默认5672
        factory.setVirtualHost("**"); //虚拟机 默认是 /
        factory.setUsername("***");//用户名 默认guest
        factory.setPassword("****"); //密码 默认是 guest
        //3.创建连接 Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();
        //5.创建交换机
        /*
        exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments)
            exchange:  交换机名称
            type:      交换机类型
                     DIRECT("direct"), :定向
                    FANOUT("fanout"),  :扇形(广播),发送消息到每一个与之绑定的队列
                    TOPIC("topic"),    :通配符的方式
                    HEADERS("headers");:参数匹配
            durable:     是否持久化
            autoDelete:  是否自动删除
            internal:    内部使用(一般false)
            arguments:   参数
         */

        String exchangeName = "test_direct";

        channel.exchangeDeclare(exchangeName, BuiltinExchangeType.DIRECT,true,false,false,null);
        //6.创建队列
        String queue1Name = "test_direct_queue1";
        String queue2Name = "test_direct_queue2";
        channel.queueDeclare(queue1Name, true, false, false, null);
        channel.queueDeclare(queue2Name, true, false, false, null);

        //7.绑定队列和交换机
        /*
                queueBind(String queue, String exchange, String routingKey)

                queue:     队列名称
                exchange:   交换机名称
                routingKey:  路由键,绑定规则:   如果交换机规则为fanout,routingKey设置为 ""
         */
                //队列一的绑定
            channel.queueBind(queue1Name,exchangeName,"error");
                //队列二的绑定
            channel.queueBind(queue2Name,exchangeName,"info");
            channel.queueBind(queue2Name,exchangeName,"error");
            channel.queueBind(queue2Name,exchangeName,"warning");

        //8.发送消息
        String body = "日志信息:张三调用了delete方法 .....出错了..  日志级别error....";
            channel.basicPublish(exchangeName, "warning", null, body.getBytes());

        //9.释放资源

        channel.close();
        connection.close();
    }
}

运行之后,查看:
在这里插入图片描述
没有错误,再来查看rabbitmq后台:
在这里插入图片描述
只有队列二有消息


/*
                queueBind(String queue, String exchange, String routingKey)

                queue:     队列名称
                exchange:   交换机名称
                routingKey:  路由键,绑定规则:   如果交换机规则为fanout,routingKey设置为 ""
         */
                //队列一的绑定
            channel.queueBind(queue1Name,exchangeName,"error");
                //队列二的绑定
            channel.queueBind(queue2Name,exchangeName,"info");
            channel.queueBind(queue2Name,exchangeName,"error");
            channel.queueBind(queue2Name,exchangeName,"warning");

查看这部分代码,routingKey中, 队列 1 绑定了 “error” 规则 ,队列 2绑定了 “info”,“error”,“warning” 等路由规则.


 //8.发送消息
 /*basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
            exchange: 交换机名称,简单模式下交换机会默认使用的 ""
            routingKey: 路由名称
            props: 配置信息
            body:  发送的消息数据
         */
        String body = "日志信息:张三调用了delete方法 .....出错了..  日志级别error....";
            channel.basicPublish(exchangeName, "warning", null, body.getBytes());

由于发送的消息为"warning" 规则 , 所以只有 队列 2 才会收到消息 .


4.2.2 创建路由消费者

Consumer_Routing1.java

package com.cy.consumer;

import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author cy
 * @create 2020-09-10-11:24
 * @Description 消费信息
 */
public class Consumer_Routing1 {
    public static void main(String[] args) throws Exception{
        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //2.设置参数
         factory.setHost("********");//ip 不设置默认为localhost
        factory.setPort(5672); //端口 默认5672
        factory.setVirtualHost("**"); //虚拟机 默认是 /
        factory.setUsername("***");//用户名 默认guest
        factory.setPassword("****"); //密码 默认是 guest
        //3.创建连接 Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();
        //5.消费信息
        /*
         * basicConsume(String queue, boolean autoAck, Consumer callback)
         *  queue: 队列名称
         *  autoAck: 是否自动确认
         *  callback:  回调对象
         */

        DefaultConsumer consumer = new DefaultConsumer(channel){
            /**
             * 回调方法,当收到信息后,会自动执行该方法
             * @param consumerTag  标识
             * @param envelope 获取一些信息,交换机,路由key
             * @param properties 配置信息
             * @param body 数据
             * @throws IOException
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
              /*  System.out.println("consumerTag"+consumerTag);
                System.out.println("Exchange"+envelope.getExchange());
                System.out.println("RoutingKey"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("body"+ new String(body));*/
                System.out.println("body1: "+new String(body));
                System.out.println("将日志存储到数据库......");
            }
        };
        String queue1Name = "test_direct_queue1";
        String queue2Name = "test_direct_queue2";
        channel.basicConsume(queue1Name, true, consumer);

    }
}

Consumer_Routing2.java

package com.cy.consumer;

import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author cy
 * @create 2020-09-10-11:24
 * @Description 消费信息
 */
public class Consumer_Routing2 {
    public static void main(String[] args) throws Exception{
        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //2.设置参数
        factory.setHost("********");//ip 不设置默认为localhost
        factory.setPort(5672); //端口 默认5672
        factory.setVirtualHost("**"); //虚拟机 默认是 /
        factory.setUsername("***");//用户名 默认guest
        factory.setPassword("****"); //密码 默认是 guest
        //3.创建连接 Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();
        //5.消费信息
        /*
         * basicConsume(String queue, boolean autoAck, Consumer callback)
         *  queue: 队列名称
         *  autoAck: 是否自动确认
         *  callback:  回调对象
         */
        DefaultConsumer consumer = new DefaultConsumer(channel){
            /**
             * 回调方法,当收到信息后,会自动执行该方法
             * @param consumerTag  标识
             * @param envelope 获取一些信息,交换机,路由key
             * @param properties 配置信息
             * @param body 数据
             * @throws IOException
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
              /*  System.out.println("consumerTag"+consumerTag);
                System.out.println("Exchange"+envelope.getExchange());
                System.out.println("RoutingKey"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("body"+ new String(body));*/
                System.out.println("body1: "+new String(body));
                System.out.println("将日志打印到控制台......");
            }
        };
        String queue1Name = "test_direct_queue1";
        String queue2Name = "test_direct_queue2";
        channel.basicConsume(queue2Name, true, consumer);
    }
}

运行消费者,查看控制台:
在这里插入图片描述
在这里插入图片描述
只有二队列有消息并得到了消费,查看rabbitmq后台查看:
在这里插入图片描述
成功.

4.3 小小的总结

在这里插入图片描述

5. Topics 通配符模式

5.1 模式说明

在这里插入图片描述

  • ( # ) :占位符,只零个或多个单位
  • ( * ) : 占位符,指单个单位
5.2 代码编写
5.2.1 编写通配生产者类

Producer_Topics.java

package com.cy.producer;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * @author cy
 * @create 2020-09-10-11:24
 * @Description 
 */
public class Producer_Topics {
    public static void main(String[] args) throws Exception {

        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //2.设置参数
         factory.setHost("********");//ip 不设置默认为localhost
        factory.setPort(5672); //端口 默认5672
        factory.setVirtualHost("**"); //虚拟机 默认是 /
        factory.setUsername("***");//用户名 默认guest
        factory.setPassword("****"); //密码 默认是 guest
        //3.创建连接 Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();

        //5.创建交换机
        /*
        exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments)
            exchange:  交换机名称
            type:      交换机类型
                     DIRECT("direct"), :定向
                    FANOUT("fanout"),  :扇形(广播),发送消息到每一个与之绑定的队列
                    TOPIC("topic"),    :通配符的方式
                    HEADERS("headers");:参数匹配
            durable:     是否持久化
            autoDelete:  是否自动删除
            internal:    内部使用(一般false)
            arguments:   参数
         */

        String exchangeName = "test_topic";

        channel.exchangeDeclare(exchangeName, BuiltinExchangeType.TOPIC,true,false,false,null);
        //6.创建队列
        String queue1Name = "test_topic_queue1";
        String queue2Name = "test_topic_queue2";
        channel.queueDeclare(queue1Name, true, false, false, null);
        channel.queueDeclare(queue2Name, true, false, false, null);

        //7.绑定队列和交换机
        /*
                queueBind(String queue, String exchange, String routingKey)

                queue:     队列名称
                exchange:   交换机名称
                routingKey:  路由键,绑定规则:   如果交换机规则为fanout,routingKey设置为 ""
         */
          //  # 代表零个或者多个    * 代表一个
        //routingKey   系统的名称.日志的级别
        //===需求:  所有error级别的日志存入数据库 , 所有order 系统的日志存入数据库
        //队列1 的绑定
            channel.queueBind(queue1Name,exchangeName,"#.error");
            channel.queueBind(queue1Name,exchangeName,"order.*");
         // 队列2 的绑定   
            channel.queueBind(queue2Name,exchangeName,"*.*");

        //8.发送消息
        String body = "日志信息:张三调用了findAll方法 .....  日志级别info....";
            channel.basicPublish(exchangeName, "my.goods.error", null, body.getBytes());

        //9.释放资源

        channel.close();
        connection.close();
    }
}

启动生产者,并查看控制台:
在这里插入图片描述
查看rabbitmq后台是否有相应队列以及消息:
在这里插入图片描述

5.2.2 编写通配消费者类

Consumer_Topic1.java

package com.cy.consumer;

import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author cy
 * @create 2020-09-10-11:24
 * @Description 消费信息
 */
public class Consumer_Topic1 {
    public static void main(String[] args) throws Exception{

        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //2.设置参数
         factory.setHost("********");//ip 不设置默认为localhost
        factory.setPort(5672); //端口 默认5672
        factory.setVirtualHost("**"); //虚拟机 默认是 /
        factory.setUsername("***");//用户名 默认guest
        factory.setPassword("****"); //密码 默认是 guest
        //3.创建连接 Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();
       
        //5.消费信息
        /*
         * basicConsume(String queue, boolean autoAck, Consumer callback)
         *  queue: 队列名称
         *  autoAck: 是否自动确认
         *  callback:  回调对象
         */

        DefaultConsumer consumer = new DefaultConsumer(channel){
            /**
             * 回调方法,当收到信息后,会自动执行该方法
             * @param consumerTag  标识
             * @param envelope 获取一些信息,交换机,路由key
             * @param properties 配置信息
             * @param body 数据
             * @throws IOException
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
              /*  System.out.println("consumerTag"+consumerTag);
                System.out.println("Exchange"+envelope.getExchange());
                System.out.println("RoutingKey"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("body"+ new String(body));*/
                System.out.println("body1: "+new String(body));
                System.out.println("将日志存储到数据库......");
            }
        };
        String queue1Name = "test_topic_queue1";
        String queue2Name = "test_topic_queue2";
        channel.basicConsume(queue1Name, true, consumer);

    }
}

Consumer_Topic2.java

package com.cy.consumer;

import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author cy
 * @create 2020-09-10-11:24
 * @Description 消费信息
 */
public class Consumer_Topic2 {
    public static void main(String[] args) throws Exception{

        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //2.设置参数
         factory.setHost("********");//ip 不设置默认为localhost
        factory.setPort(5672); //端口 默认5672
        factory.setVirtualHost("**"); //虚拟机 默认是 /
        factory.setUsername("***");//用户名 默认guest
        factory.setPassword("****"); //密码 默认是 guest
        //3.创建连接 Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();
        //5.创建队列Queue
        /*queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
            queue:     队列名称
            durable:    是否持久化,当mq重启之后还在
            exclusive:
                    *是否独占,只能有一个消费者监听这队列
                    *当Connection关闭时,是否删除队列
            autoDelete:是否自动删除,当没有Consumer时,自动删除掉
            arguments:参数
        */
        //如果没没有一个叫Hello_World的队列,则会创建
        //6.消费信息
        /*
         * basicConsume(String queue, boolean autoAck, Consumer callback)
         *  queue: 队列名称
         *  autoAck: 是否自动确认
         *  callback:  回调对象
         */

        DefaultConsumer consumer = new DefaultConsumer(channel){
            /**
             * 回调方法,当收到信息后,会自动执行该方法
             * @param consumerTag  标识
             * @param envelope 获取一些信息,交换机,路由key
             * @param properties 配置信息
             * @param body 数据
             * @throws IOException
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
              /*  System.out.println("consumerTag"+consumerTag);
                System.out.println("Exchange"+envelope.getExchange());
                System.out.println("RoutingKey"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("body"+ new String(body));*/
                System.out.println("body1: "+new String(body));
                System.out.println("将日志打印控制台.....");
            }
        };
        String queue1Name = "test_topic_queue1";
        String queue2Name = "test_topic_queue2";
        channel.basicConsume(queue2Name, true, consumer);

    }
}

运行消费者,并查看控制台打印:
在这里插入图片描述
在这里插入图片描述
符合,查看后台:
在这里插入图片描述
这就是路由通配方式.

5.3 小小的总结

在这里插入图片描述

四、工作模式总结

在这里插入图片描述
工作队列模式 和简单模式生产区别不大,主要在于消费时,多创建了消费者

发布订阅模式(Pub/Sub) 主要在与生产时,需要创建一个交换机并制动交换机类型为"fanout",也要绑定交换机和队列,发布时,如果交换机规则为fanout,routingKey设置为 " " .

路由模式(Routing) 主要在于生产时,需要创建一个交换机并制动交换机类型为"direct", 交换机和队列绑定时,需要制定特定的routingKey , 例如 “error”,“info”,“warning” 等等. 消费无差.

通配符模式 主要在于生产时,需要创建一个交换机并制动交换机类型为"topic", 交换机和队列绑定时,需要制定特定的routingKey,例如 “#.error” "order." ".*"等等,消费无差.


仅供个人学习参考,只是一枚Java菜鸟,如有问题请指出.谢谢
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值