RabbitMQ基础

概念

在这里插入图片描述

RabbitMQ的优势

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

RabbitMQ的劣势

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

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

安装

一.安装Erlang

安装RabbitMQ需要
安装Erlang/OTP,并保持版本匹配。
在这里插入图片描述
下载地址:http://erlang.org/download/otp_win64_20.3.exe
以管理员身份运行此文件进行安装。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
erlang安装完成需要配置erlang 系统环境变量: ERLANG_HOME=C:\Program Files\erl9.3 在path中添
加%ERLANG_HOME%\bin;
在这里插入图片描述

二.安装rabbitMQ

下载地址:https://github.com/rabbitmq/rabbitmq-server/releases/tag/v3.7.14
以管理员身份运行此文件进行安装。安装完成后可以在系统服务中查看到RabbitMQ服务。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三.配置插件

为了更加方便的管理RabbitMQ服务,可以安装RabbitMQ提供的一个浏览器端管理插件,可以通过浏览器页面方便
的进行服务管理。
安装方式:
1、以管理员身份打开 cmd (不是PowerShell);然后进入在RabbitMQ的安装目录下sbin目录
2、在上述窗口执行命令: rabbitmq-plugins.bat enable rabbitmq_management
在这里插入图片描述
打开浏览器访问网站http://localhost:15672进入登录页面,默认账号和密码都为guest
在这里插入图片描述
在这里插入图片描述

问题注意:
1、安装erlang和RabbitMQ时都需要以管理员身份进行安装
2、当卸载重新安装时会出现RabbitMQ服务注册失败,此时需要进入注册表清理erlang,方法为搜索
RabbitMQ、ErlSrv,将对应的项全部删除

原生代码的五种模式

一.简单模式

1.消息产生者§将消息放入队列
2.消息的消费者(consumer) 监听(while) 消息队列,如果队列中有消息,就消费掉,消息被拿走后,自动从队列中删除(隐患 消息可能没有被消费者正确处理,已经从队列中消失了,造成消息的丢失)应用场景:聊天(中间有一个过度的服务器;p端,c端)

生产方

package cn.rabbitmq;

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

public class ProducerTest {


    public static void main(String[] args) throws Exception{

        //创建连接工厂对象
        ConnectionFactory factoryObj = new ConnectionFactory();

        //输入MabbitMQ管理台中的所设置的用户参数,以该用户连接Mabbit
        factoryObj.setHost("127.0.0.1");
        factoryObj.setPort(5672);
        factoryObj.setVirtualHost("/lele");
        factoryObj.setUsername("lele");
        factoryObj.setPassword("lele");

        //通过连接工厂对象来创建连接对象
        Connection connectionObj = factoryObj.newConnection();

        //通过连接对象创建引导对象'Channel'
        Channel channelObj = connectionObj.createChannel();

        //通过连接引导对象创建队列

        /*
        1.队列名称  当使用basicPublish方法发送消息时,该名称会被当作路由名称使用.
        2.是否持久化 即:当重启之后还存在
        3.是否独占 即:只能由一个消费者监听该队列,
        4.是否自动删除 即:当没有Consumer消费者时,自动删除掉
        5.参数
         */
        channelObj.queueDeclare("hello_world",true, false, false,null );


        //发送消息给消费者
        /*
        1.交换机名称 简单模式下的交换机名为:""
        2.路由名称,需要同队列名称一致
        3.配置信息
        4.要发送的数据
         */
        String bodyInfo = "hello!!!!!!lele!!!";

        channelObj.basicPublish("", "hello_world",null , bodyInfo.getBytes() );

        //释放资源
        channelObj.close();
        connectionObj.close();

    }

}

消费方

package cn.rabbitmq;

import com.rabbitmq.client.*;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

import java.io.IOException;
import java.util.logging.Handler;

public class ConsumerTest {


    public static void main(String[] args) throws Exception{

        //创建连接工厂对象
        ConnectionFactory factoryObj = new ConnectionFactory();

        //输入MabbitMQ管理台中的所设置的用户参数,以该用户连接Mabbit
        factoryObj.setHost("127.0.0.1");
        factoryObj.setPort(5672);
        factoryObj.setVirtualHost("/lele");
        factoryObj.setUsername("lele");
        factoryObj.setPassword("lele");

        //通过连接工厂对象来创建连接对象
        Connection connectionObj = factoryObj.newConnection();

        //通过连接对象创建引导对象'Channel'
        Channel channelObj = connectionObj.createChannel();

        //通过连接引导对象创建队列

        /*
        1.队列名称  当使用basicConsume方法接收消息时,该名称还会被引用.
        2.是否持久化 即:当重启之后还存在
        3.是否独占 即:只能由一个消费者监听该队列,
        4.是否自动删除 即:当没有Consumer消费者时,自动删除掉
        5.参数
         */
        channelObj.queueDeclare("hello_world",true, false, false,null );




        //定义回调对象
        Consumer comsumer = new DefaultConsumer(channelObj){

            /*
            形参1:consumerTag 标识
            形参2:envelope 获取信息,如:交换机,路由Key等等..
            形参3:properties 配置信息
            形参4:body 消息
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("标识为:"+consumerTag);
                System.out.println("交换机名称为:"+envelope.getExchange());
                System.out.println("路由Key值为:"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("消息:"+new String(body));
                super.handleDelivery(consumerTag, envelope, properties, body);
            }
        };

        //接收消息
        /*
        1.队列名称
        2.是否自动确认
        3.回调对象 即:当收到消息后,自动执行某个方法,其方法类型必须为'Consumer'.多数为'Consumer'实现类'DefaultConsumer'的方法'handleDelivery',该方法需要被重写.
         */
        channelObj.basicConsume("hello_world",true, comsumer);

        //消费者无需关闭资源.这并非是因为消费者没有close方法.而是因为消费者本身的作用就是一直在监听状态的基础上来获取生产者发送的消息.





    }

}

二.WorkQueue工作(竞争)模式

也称之为竞争模式
1.消息产生者将消息放入队列消费者可以有多个,消费者1,消费者2,同时监听同一个队列,消息被消费?C1 C2共同争抢当前的消息队列内容,谁先拿到谁负责消费消息(隐患,高并发情况下,默认会产生某一个消息被多个消费者共同使用,可以设置一个开关(syncronize,与同步锁的性能不一样) 保证一条消息只能被一个消费者使用)
2。应用场景:红包;大项目中的资源调度(任务分配系统不需知道哪一个任务执行系统在空闲,直接将任务扔到消息队列中,空闲的系统自动争抢)
在这里插入图片描述

生产方

package cn.rabbitmq.workqueues;

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

public class ProducetOfWorkqueues {


    public static void main(String[] args) throws Exception {

        //创建连接工厂对象
        ConnectionFactory factoryObj = new ConnectionFactory();

        //输入MabbitMQ管理台中的所设置的用户参数,以该用户连接Mabbit
        factoryObj.setHost("127.0.0.1");
        factoryObj.setPort(5672);
        factoryObj.setVirtualHost("/lele");
        factoryObj.setUsername("lele");
        factoryObj.setPassword("lele");

        //通过连接工厂对象来创建连接对象
        Connection connectionObj = factoryObj.newConnection();

        //通过连接对象创建引导对象'Channel'
        Channel channelObj = connectionObj.createChannel();

        //通过连接引导对象创建队列

        /*
        1.队列名称  当使用basicPublish方法发送消息时,该名称会被当作路由名称使用.
        2.是否持久化 即:当重启之后还存在
        3.是否独占 即:只能由一个消费者监听该队列,
        4.是否自动删除 即:当没有Consumer消费者时,自动删除掉
        5.参数
         */
        channelObj.queueDeclare("hello_world", true, false, false, null);


        //发送消息给消费者
        /*
        1.交换机名称 简单模式下的交换机名为:""
        2.路由名称,需要同队列名称一致
        3.配置信息
        4.要发送的数据
         */
        for (int i = 1; i < 11; i++) {
            String bodyInfo = "hello!!!!!!lele!!! 第" + i + "次";


            channelObj.basicPublish("", "hello_world", null, bodyInfo.getBytes());
        }


        //释放资源
        channelObj.close();
        connectionObj.close();

    }

}

消费方A

package cn.rabbitmq.workqueues;

import com.rabbitmq.client.*;

import java.io.IOException;

public class ConsumerOfWorkqueuesA {


    public static void main(String[] args) throws Exception{

        //创建连接工厂对象
        ConnectionFactory factoryObj = new ConnectionFactory();

        //输入MabbitMQ管理台中的所设置的用户参数,以该用户连接Mabbit
        factoryObj.setHost("127.0.0.1");
        factoryObj.setPort(5672);
        factoryObj.setVirtualHost("/lele");
        factoryObj.setUsername("lele");
        factoryObj.setPassword("lele");

        //通过连接工厂对象来创建连接对象
        Connection connectionObj = factoryObj.newConnection();

        //通过连接对象创建引导对象'Channel'
        Channel channelObj = connectionObj.createChannel();

        //通过连接引导对象创建队列

        /*
        1.队列名称  当使用basicConsume方法接收消息时,该名称还会被引用.
        2.是否持久化 即:当重启之后还存在
        3.是否独占 即:只能由一个消费者监听该队列,
        4.是否自动删除 即:当没有Consumer消费者时,自动删除掉
        5.参数
         */
        channelObj.queueDeclare("hello_world",true, false, false,null );




        //定义回调对象
        Consumer comsumer = new DefaultConsumer(channelObj){

            /*
            形参1:consumerTag 标识
            形参2:envelope 获取信息,如:交换机,路由Key等等..
            形参3:properties 配置信息
            形参4:body 消息
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("标识为:"+consumerTag);
                System.out.println("交换机名称为:"+envelope.getExchange());
                System.out.println("路由Key值为:"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("消息:"+new String(body));
                super.handleDelivery(consumerTag, envelope, properties, body);
            }
        };

        //接收消息
        /*
        1.队列名称
        2.是否自动确认
        3.回调对象 即:当收到消息后,自动执行某个方法,其方法类型必须为'Consumer'.多数为'Consumer'实现类'DefaultConsumer'的方法'handleDelivery',该方法需要被重写.
         */
        channelObj.basicConsume("hello_world",true, comsumer);

        //消费者无需关闭资源.这并非是因为消费者没有close方法.而是因为消费者本身的作用就是一直在监听状态的基础上来获取生产者发送的消息.





    }

}

消费方B

package cn.rabbitmq.workqueues;

import com.rabbitmq.client.*;

import java.io.IOException;

public class ConsumerOfWorkqueuesB {


    public static void main(String[] args) throws Exception{

        //创建连接工厂对象
        ConnectionFactory factoryObj = new ConnectionFactory();

        //输入MabbitMQ管理台中的所设置的用户参数,以该用户连接Mabbit
        factoryObj.setHost("127.0.0.1");
        factoryObj.setPort(5672);
        factoryObj.setVirtualHost("/lele");
        factoryObj.setUsername("lele");
        factoryObj.setPassword("lele");

        //通过连接工厂对象来创建连接对象
        Connection connectionObj = factoryObj.newConnection();

        //通过连接对象创建引导对象'Channel'
        Channel channelObj = connectionObj.createChannel();

        //通过连接引导对象创建队列

        /*
        1.队列名称  当使用basicConsume方法接收消息时,该名称还会被引用.
        2.是否持久化 即:当重启之后还存在
        3.是否独占 即:只能由一个消费者监听该队列,
        4.是否自动删除 即:当没有Consumer消费者时,自动删除掉
        5.参数
         */
        channelObj.queueDeclare("hello_world",true, false, false,null );




        //定义回调对象
        Consumer comsumer = new DefaultConsumer(channelObj){

            /*
            形参1:consumerTag 标识
            形参2:envelope 获取信息,如:交换机,路由Key等等..
            形参3:properties 配置信息
            形参4:body 消息
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("标识为:"+consumerTag);
                System.out.println("交换机名称为:"+envelope.getExchange());
                System.out.println("路由Key值为:"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("消息:"+new String(body));
                super.handleDelivery(consumerTag, envelope, properties, body);
            }
        };

        //接收消息
        /*
        1.队列名称
        2.是否自动确认
        3.回调对象 即:当收到消息后,自动执行某个方法,其方法类型必须为'Consumer'.多数为'Consumer'实现类'DefaultConsumer'的方法'handleDelivery',该方法需要被重写.
         */
        channelObj.basicConsume("hello_world",true, comsumer);

        //消费者无需关闭资源.这并非是因为消费者没有close方法.而是因为消费者本身的作用就是一直在监听状态的基础上来获取生产者发送的消息.





    }

}

三.广播(订阅)模式

1.X代表交换机rabbitMQ内部组件,erlang 消息产生者是代码完成,代码的执行效率不高,消息产生者将消息放入交换机,交换机发布订阅把消息发送到所有消息队列中,对应消息队列的消费者拿到消息进行消费
2.相关场景:邮件群发,群聊天,广播(广告)
在这里插入图片描述
在这里插入图片描述

生产方

package cn.rabbitmq.pubsub;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
/*
Pubsub模式
 */
public class ProducerPubsub {
    public static void main(String[] args)throws Exception {


        //创建连接工厂对象
        ConnectionFactory factoryObj = new ConnectionFactory();

        //输入MabbitMQ管理台中的所设置的用户参数,以该用户连接Mabbit
        factoryObj.setHost("127.0.0.1");
        factoryObj.setPort(5672);
        factoryObj.setVirtualHost("/lele");
        factoryObj.setUsername("lele");
        factoryObj.setPassword("lele");

        //通过连接工厂对象来创建连接对象
        Connection connectionObj = factoryObj.newConnection();

        //通过连接对象创建引导对象'Channel'
        Channel channelObj = connectionObj.createChannel();

        // 定义交换机名称 text_exchenge   路径为/lele
        String exchangeName = "text_exchenge";

        //创建并定义一个交换机
        /* exchangeDeclare  exchangeDeclare(String var1, BuiltinExchangeType var2, boolean var3, boolean var4, boolean var5, Map<String, Object> var6)
        1.交换机名称
        2.交换机类型 BuiltinExchangeType.交换机类型
        3.是否自动持久化
        4.是否自动删除
        5.是否内部使用,一般为false
        6.参数

         */
        channelObj.exchangeDeclare(exchangeName, BuiltinExchangeType.FANOUT , true,false , false,null);

        //创建列队
        String queueOne = "test_fanout_queueOne";
        String queueTwo = "test_fanout_queueTwo";
        channelObj.queueDeclare(queueOne,true ,false ,false ,null );
        channelObj.queueDeclare(queueTwo,true ,false ,false ,null );


        //将列队和交换机进行绑定
        /*
        com.rabbitmq.client.AMQP.Queue.BindOk queueBind(String var1, String var2, String var3)
        1.队列名称
        2.交换机名称
        3.路由键(绑定规则)
            如果交换机类型为fanout,则设置为""


         */
        channelObj.queueBind(queueOne, exchangeName,"" );
        channelObj.queueBind(queueTwo,exchangeName ,"" );

        //发送消息
        String body = "你好!";
        channelObj.basicPublish(exchangeName,"" ,null ,body.getBytes() );



        //释放资源
        channelObj.close();
        connectionObj.close();


    }

}

消费方A

package cn.rabbitmq.pubsub;

import com.rabbitmq.client.*;

import java.io.IOException;

public class ConsumerPubsubA {
    public static void main(String[] args)throws Exception {
        //创建连接工厂对象
        ConnectionFactory factoryObj = new ConnectionFactory();

        //输入MabbitMQ管理台中的所设置的用户参数,以该用户连接Mabbit
        factoryObj.setHost("127.0.0.1");
        factoryObj.setPort(5672);
        factoryObj.setVirtualHost("/lele");
        factoryObj.setUsername("lele");
        factoryObj.setPassword("lele");

        //通过连接工厂对象来创建连接对象
        Connection connectionObj = factoryObj.newConnection();

        //通过连接对象创建引导对象'Channel'
        Channel channelObj = connectionObj.createChannel();

        //先定义队列名
        String queueOne = "test_fanout_queueOne";




        //定义回调对象
        Consumer comsumer = new DefaultConsumer(channelObj){

            /*
            形参1:consumerTag 标识
            形参2:envelope 获取信息,如:交换机,路由Key等等..
            形参3:properties 配置信息
            形参4:body 消息
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("标识为:"+consumerTag);
                System.out.println("交换机名称为:"+envelope.getExchange());
                System.out.println("路由Key值为:"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("消息:"+new String(body));
                System.out.println("pubsubOne Success.....消费者A接收到信息,并将信息进行封装");
                super.handleDelivery(consumerTag, envelope, properties, body);
            }
        };

        //接收消息
        /*
        1.队列名称
        2.是否自动确认
        3.回调对象 即:当收到消息后,自动执行某个方法,其方法类型必须为'Consumer'.多数为'Consumer'实现类'DefaultConsumer'的方法'handleDelivery',该方法需要被重写.
         */
        channelObj.basicConsume(queueOne,true, comsumer);

        //消费者无需关闭资源.这并非是因为消费者没有close方法.而是因为消费者本身的作用就是一直在监听状态的基础上来获取生产者发送的消息.



    }

}

消费方B

package cn.rabbitmq.pubsub;

import com.rabbitmq.client.*;

import java.io.IOException;

public class ConsumerPubsubB {

    public static void main(String[] args) throws Exception{
        //创建连接工厂对象
        ConnectionFactory factoryObj = new ConnectionFactory();

        //输入MabbitMQ管理台中的所设置的用户参数,以该用户连接Mabbit
        factoryObj.setHost("127.0.0.1");
        factoryObj.setPort(5672);
        factoryObj.setVirtualHost("/lele");
        factoryObj.setUsername("lele");
        factoryObj.setPassword("lele");

        //通过连接工厂对象来创建连接对象
        Connection connectionObj = factoryObj.newConnection();

        //通过连接对象创建引导对象'Channel'
        Channel channelObj = connectionObj.createChannel();

        //先定义队列名
        String queueTwo = "test_fanout_queueTwo";




        //定义回调对象
        Consumer comsumer = new DefaultConsumer(channelObj){

            /*
            形参1:consumerTag 标识
            形参2:envelope 获取信息,如:交换机,路由Key等等..
            形参3:properties 配置信息
            形参4:body 消息
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("标识为:"+consumerTag);
                System.out.println("交换机名称为:"+envelope.getExchange());
                System.out.println("路由Key值为:"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("消息:"+new String(body));
                System.out.println("pubsubTwo Success..... 消费者B接收到信息,并将信息保存到数据库");
                super.handleDelivery(consumerTag, envelope, properties, body);

            }
        };

        //接收消息
        /*
        1.队列名称
        2.是否自动确认
        3.回调对象 即:当收到消息后,自动执行某个方法,其方法类型必须为'Consumer'.多数为'Consumer'实现类'DefaultConsumer'的方法'handleDelivery',该方法需要被重写.
         */
        channelObj.basicConsume(queueTwo,true, comsumer);

        //消费者无需关闭资源.这并非是因为消费者没有close方法.而是因为消费者本身的作用就是一直在监听状态的基础上来获取生产者发送的消息.

    }
}

四.路由(Routing)模式

1.消息生产者将消息发送给交换机按照路由判断,路由是字符串(info) 当前产生的消息携带路由字符(对象的方法),交换机根据路由的key,只能匹配上路由key对应的消息队列,对应的消费者才能消费消息;
2.根据业务功能定义路由字符串
3.从系统的代码逻辑中获取对应的功能字符串,将消息任务扔到对应的队列中业务场景:error 通知;EXCEPTION;错误通知的功能;传统意义的错误通知;客户通知;利用key路由,可以将程序中的错误封装成消息传入到消息队列中,开发者可以自定义消费者,实时接收错误;
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

生产方

package cn.rabbitmq.routing;

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

public class ProducerRouting {

    public static void main(String[] args)throws Exception {
        //创建连接工厂对象
        ConnectionFactory factoryObj = new ConnectionFactory();

        //输入MabbitMQ管理台中的所设置的用户参数,以该用户连接Mabbit
        factoryObj.setHost("127.0.0.1");
        factoryObj.setPort(5672);
        factoryObj.setVirtualHost("/lele");
        factoryObj.setUsername("lele");
        factoryObj.setPassword("lele");

        //通过连接工厂对象来创建连接对象
        Connection connectionObj = factoryObj.newConnection();

        //通过连接对象创建引导对象'Channel'
        Channel channelObj = connectionObj.createChannel();

        // 定义交换机名称 text_exchenge   路径为/lele
        String exchangeName = "text_exchenge_routing";

        //创建并定义一个交换机
        /* exchangeDeclare  exchangeDeclare(String var1, BuiltinExchangeType var2, boolean var3, boolean var4, boolean var5, Map<String, Object> var6)
        1.交换机名称
        2.交换机类型 BuiltinExchangeType.交换机类型
        3.是否自动持久化
        4.是否自动删除
        5.是否内部使用,一般为false
        6.参数

         */
        channelObj.exchangeDeclare(exchangeName, BuiltinExchangeType.DIRECT , true,false , false,null);

        //创建列队
        String queueOne = "test_DIRECT_queueOne";
        String queueTwo = "test_DIRECT_queueTwo";
        channelObj.queueDeclare(queueOne,true ,false ,false ,null );
        channelObj.queueDeclare(queueTwo,true ,false ,false ,null );




        /*
        com.rabbitmq.client.AMQP.Queue.BindOk queueBind(String var1, String var2, String var3)
        1.队列名称
        2.交换机名称
        3.路由键(绑定规则标识)
            如果交换机类型为fanout,则设置为""
            如果交换机类型为DIRECT(routing),则需要根据需要设置值
         */
        //将列队1和交换机进行绑定,并设置队列的Key路由键.
        channelObj.queueBind(queueOne, exchangeName,"error" );

        //将列队2和交换机进行绑定,并设置队列的Key路由键.
        channelObj.queueBind(queueTwo,exchangeName ,"info" );
        channelObj.queueBind(queueTwo,exchangeName ,"warning" );
        channelObj.queueBind(queueTwo,exchangeName ,"error" );

        //发送消息
        /*
        1.交换机名称 简单模式下的交换机名为:""
        2.路由键(规则标识)
        3.配置信息
        4.要发送的数据
         */

       // String body = "你好!这是direct(routing)模式,当前级别为:waring.... 只有消费者B可以收到消息";
        String body = "你好!这是direct(routing)模式,当前级别为:error.... 消费者A和消费者B都可以收到消息";
        channelObj.basicPublish(exchangeName,"error" ,null ,body.getBytes() );



        //释放资源
        channelObj.close();
        connectionObj.close();








    }

}

消费方A

package cn.rabbitmq.routing;

import com.rabbitmq.client.*;

import java.io.IOException;

public class ConsumerRoutingA {
    public static void main(String[] args)throws Exception {

        //创建连接工厂对象
        ConnectionFactory factoryObj = new ConnectionFactory();

        //输入MabbitMQ管理台中的所设置的用户参数,以该用户连接Mabbit
        factoryObj.setHost("127.0.0.1");
        factoryObj.setPort(5672);
        factoryObj.setVirtualHost("/lele");
        factoryObj.setUsername("lele");
        factoryObj.setPassword("lele");

        //通过连接工厂对象来创建连接对象
        Connection connectionObj = factoryObj.newConnection();

        //通过连接对象创建引导对象'Channel'
        Channel channelObj = connectionObj.createChannel();

        //先定义队列名
        String queueOne = "test_DIRECT_queueOne";




        //定义回调对象
        Consumer comsumer = new DefaultConsumer(channelObj){

            /*
            形参1:consumerTag 标识
            形参2:envelope 获取信息,如:交换机,路由Key等等..
            形参3:properties 配置信息
            形参4:body 消息
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("标识为:"+consumerTag);
                System.out.println("交换机名称为:"+envelope.getExchange());
                System.out.println("路由Key值为:"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("消息:"+new String(body));
                System.out.println("pubsubOne Success.....消费者A接收到信息,并将信息进行封装");
                super.handleDelivery(consumerTag, envelope, properties, body);
            }
        };

        //接收消息
        /*
        1.队列名称
        2.是否自动确认
        3.回调对象 即:当收到消息后,自动执行某个方法,其方法类型必须为'Consumer'.多数为'Consumer'实现类'DefaultConsumer'的方法'handleDelivery',该方法需要被重写.
         */
        channelObj.basicConsume(queueOne,true, comsumer);

        //消费者无需关闭资源.这并非是因为消费者没有close方法.而是因为消费者本身的作用就是一直在监听状态的基础上来获取生产者发送的消息.


    }
}

消费方B

package cn.rabbitmq.routing;

import com.rabbitmq.client.*;

import java.io.IOException;

public class ConsumerRoutingB {
    public static void main(String[] args)throws Exception {

        //创建连接工厂对象
        ConnectionFactory factoryObj = new ConnectionFactory();

        //输入MabbitMQ管理台中的所设置的用户参数,以该用户连接Mabbit
        factoryObj.setHost("127.0.0.1");
        factoryObj.setPort(5672);
        factoryObj.setVirtualHost("/lele");
        factoryObj.setUsername("lele");
        factoryObj.setPassword("lele");

        //通过连接工厂对象来创建连接对象
        Connection connectionObj = factoryObj.newConnection();

        //通过连接对象创建引导对象'Channel'
        Channel channelObj = connectionObj.createChannel();

        //先定义队列名
        String queueTwo = "test_DIRECT_queueTwo";




        //定义回调对象
        Consumer comsumer = new DefaultConsumer(channelObj){

            /*
            形参1:consumerTag 标识
            形参2:envelope 获取信息,如:交换机,路由Key等等..
            形参3:properties 配置信息
            形参4:body 消息
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("标识为:"+consumerTag);
                System.out.println("交换机名称为:"+envelope.getExchange());
                System.out.println("路由Key值为:"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("消息:"+new String(body));
                System.out.println("pubsubOne Success.....消费者B接收到信息,并将信息进行封装");
                super.handleDelivery(consumerTag, envelope, properties, body);
            }
        };

        //接收消息
        /*
        1.队列名称
        2.是否自动确认
        3.回调对象 即:当收到消息后,自动执行某个方法,其方法类型必须为'Consumer'.多数为'Consumer'实现类'DefaultConsumer'的方法'handleDelivery',该方法需要被重写.
         */
        channelObj.basicConsume(queueTwo,true, comsumer);

        //消费者无需关闭资源.这并非是因为消费者没有close方法.而是因为消费者本身的作用就是一直在监听状态的基础上来获取生产者发送的消息.

    }

}

五.topics主题(路由模式的一种)模式

1.星号井号代表通配符
2.星号代表多个单词,井号代表一个单词
3.路由功能添加模糊匹配
4.消息产生者产生消息,把消息交给交换机
5.交换机根据key的规则模糊匹配到对应的队列,由队列的监听消费者接收消息消费

# 号代表匹配0到多个后缀 如:error.# = error.test.test.test        
* 号代表只能匹配一个后缀 如:info.* = info.test

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

生产方

package cn.rabbitmq.topics;

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

public class ProducerTopics {

    public static void main(String[] args)throws Exception {
        //创建连接工厂对象
        ConnectionFactory factoryObj = new ConnectionFactory();

        //输入MabbitMQ管理台中的所设置的用户参数,以该用户连接Mabbit
        factoryObj.setHost("127.0.0.1");
        factoryObj.setPort(5672);
        factoryObj.setVirtualHost("/lele");
        factoryObj.setUsername("lele");
        factoryObj.setPassword("lele");

        //通过连接工厂对象来创建连接对象
        Connection connectionObj = factoryObj.newConnection();

        //通过连接对象创建引导对象'Channel'
        Channel channelObj = connectionObj.createChannel();

        // 定义交换机名称 text_exchenge   路径为/lele
        String exchangeName = "text_exchenge_topics";

        //创建并定义一个交换机
        /* exchangeDeclare  exchangeDeclare(String var1, BuiltinExchangeType var2, boolean var3, boolean var4, boolean var5, Map<String, Object> var6)
        1.交换机名称
        2.交换机类型 BuiltinExchangeType.交换机类型
        3.是否自动持久化
        4.是否自动删除
        5.是否内部使用,一般为false
        6.参数

         */
        channelObj.exchangeDeclare(exchangeName, BuiltinExchangeType.TOPIC , true,false , false,null);

        //创建列队
        String queueOne = "test_topics_queueOne";
        String queueTwo = "test_topics_queueTwo";
        channelObj.queueDeclare(queueOne,true ,false ,false ,null );
        channelObj.queueDeclare(queueTwo,true ,false ,false ,null );




        /*
        com.rabbitmq.client.AMQP.Queue.BindOk queueBind(String var1, String var2, String var3)
        1.队列名称
        2.交换机名称
        3.路由键(绑定规则标识)
            如果交换机类型为fanout,则设置为""
            如果交换机类型为DIRECT(routing),则需要根据需要设置值
            如果交换机类型为TOPIC,则为匹配模式,   # 号代表匹配0到多个后缀 如:error.# = error.test.test.test        * 号代表只能匹配一个后缀 如:info.* = info.test

         */



        //将列队1和交换机进行绑定,并设置队列的Key路由键.
        channelObj.queueBind(queueOne, exchangeName,"error.#" );

        //将列队2和交换机进行绑定,并设置队列的Key路由键.
        channelObj.queueBind(queueTwo,exchangeName ,"info.*" );
        channelObj.queueBind(queueTwo,exchangeName ,"warning" );
        channelObj.queueBind(queueTwo,exchangeName ,"error.#" );

        //发送消息
        /*
        1.交换机名称 简单模式下的交换机名为:""
        2.路由键(规则标识)
        3.配置信息
        4.要发送的数据
         */

        //String body = "你好!这是topics模式,当前级别为:info.*.... 只有消费者B可以收到消息,且因为通配符的存在,只有一个后缀时才可以发送得出去";
        String body = "你好!这是topics模式,当前级别为:error.# 消费者A和消费者B都可以收到消息,且因为通配符的存在所以不管多少个后缀都可以发送出去";


        channelObj.basicPublish(exchangeName,"error.eee.eeee" ,null ,body.getBytes() );



        //释放资源
        channelObj.close();
        connectionObj.close();








    }

}

消费者A

package cn.rabbitmq.topics;

import com.rabbitmq.client.*;

import java.io.IOException;

public class ConsumerTopicsA {
    public static void main(String[] args)throws Exception {

        //创建连接工厂对象
        ConnectionFactory factoryObj = new ConnectionFactory();

        //输入MabbitMQ管理台中的所设置的用户参数,以该用户连接Mabbit
        factoryObj.setHost("127.0.0.1");
        factoryObj.setPort(5672);
        factoryObj.setVirtualHost("/lele");
        factoryObj.setUsername("lele");
        factoryObj.setPassword("lele");

        //通过连接工厂对象来创建连接对象
        Connection connectionObj = factoryObj.newConnection();

        //通过连接对象创建引导对象'Channel'
        Channel channelObj = connectionObj.createChannel();

        //先定义队列名
        String queueOne = "test_topics_queueOne";




        //定义回调对象
        Consumer comsumer = new DefaultConsumer(channelObj){

            /*
            形参1:consumerTag 标识
            形参2:envelope 获取信息,如:交换机,路由Key等等..
            形参3:properties 配置信息
            形参4:body 消息
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("标识为:"+consumerTag);
                System.out.println("交换机名称为:"+envelope.getExchange());
                System.out.println("路由Key值为:"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("消息:"+new String(body));
                System.out.println("pubsubOne Success.....消费者A接收到信息,并将信息进行封装");
                super.handleDelivery(consumerTag, envelope, properties, body);
            }
        };

        //接收消息
        /*
        1.队列名称
        2.是否自动确认
        3.回调对象 即:当收到消息后,自动执行某个方法,其方法类型必须为'Consumer'.多数为'Consumer'实现类'DefaultConsumer'的方法'handleDelivery',该方法需要被重写.
         */
        channelObj.basicConsume(queueOne,true, comsumer);

        //消费者无需关闭资源.这并非是因为消费者没有close方法.而是因为消费者本身的作用就是一直在监听状态的基础上来获取生产者发送的消息.


    }
}

消费者B

package cn.rabbitmq.topics;

import com.rabbitmq.client.*;

import java.io.IOException;

public class ConsumerTopicsB {
    public static void main(String[] args)throws Exception {

        //创建连接工厂对象
        ConnectionFactory factoryObj = new ConnectionFactory();

        //输入MabbitMQ管理台中的所设置的用户参数,以该用户连接Mabbit
        factoryObj.setHost("127.0.0.1");
        factoryObj.setPort(5672);
        factoryObj.setVirtualHost("/lele");
        factoryObj.setUsername("lele");
        factoryObj.setPassword("lele");

        //通过连接工厂对象来创建连接对象
        Connection connectionObj = factoryObj.newConnection();

        //通过连接对象创建引导对象'Channel'
        Channel channelObj = connectionObj.createChannel();

        //先定义队列名
        String queueTwo = "test_topics_queueTwo";




        //定义回调对象
        Consumer comsumer = new DefaultConsumer(channelObj){

            /*
            形参1:consumerTag 标识
            形参2:envelope 获取信息,如:交换机,路由Key等等..
            形参3:properties 配置信息
            形参4:body 消息
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("标识为:"+consumerTag);
                System.out.println("交换机名称为:"+envelope.getExchange());
                System.out.println("路由Key值为:"+envelope.getRoutingKey());
                System.out.println("properties"+properties);
                System.out.println("消息:"+new String(body));
                System.out.println("pubsubOne Success.....消费者B接收到信息,并将信息进行封装");
                super.handleDelivery(consumerTag, envelope, properties, body);
            }
        };

        //接收消息
        /*
        1.队列名称
        2.是否自动确认
        3.回调对象 即:当收到消息后,自动执行某个方法,其方法类型必须为'Consumer'.多数为'Consumer'实现类'DefaultConsumer'的方法'handleDelivery',该方法需要被重写.
         */
        channelObj.basicConsume(queueTwo,true, comsumer);

        //消费者无需关闭资源.这并非是因为消费者没有close方法.而是因为消费者本身的作用就是一直在监听状态的基础上来获取生产者发送的消息.

    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值