Rabbit Mq学习笔记:rabbit mq的五种常用工作模式

Rabbit Mq学习笔记:rabbit mq的五种常用工作模式

下载安装就不介绍了,可以查看Rabbit Mq官方文档

一、配置可视化RabbitMQ管理界面
1、运行命令行窗口cmd
输入命令rabbitmq-plugins enable rabbitmq_management,这样就可以添加可视化插件了。
查看可视化插件是否成功:
开始菜单栏

2、运行RabbitMQ Service - start启动服务
在浏览器中输入地址:http://127.0.0.1:15672/
输入默认账号: guest 密码: guest
就可以登录查看rabbitmq里的资源信息。
备注:可以运行 rabbitmqctl stop 命令来停止服务
可以运行 rabbitmq-server -detached命令来重启服务并后台运行。
RabbitMQ的日志信息,可以在 C:/Users/Administrator/AppData/Roaming/RabbitMQ/log/文件夹下进行查看,如:C:/Users/Administrator/AppData/Roaming/RabbitMQ/log/rabbit@mywin-PC.log

二、五种工作模式
工具类:

package com.byz.rabbitmq.rabbitmqdemo.utils;

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

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * rabbit mq 连接工具类
 */
public class ConnectionUtil {

    private static String host = "localhost";
    private static Integer port = 5672;
    private static String username = "guest";
    private static String password = "guest";

    /**
     * 初始化连接
     */
    public static Connection getConnection() throws IOException, TimeoutException {
    	/*
            connection抽象了socket连接,控制协议版本和授权等问题。
            现在我们是在本地连接中间件,所以host使用localhost就可以了,
            如果想连接其他机器上的中间件只需要把host改成对应的host name或者ip地址就可以了
         */
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost(host);
        factory.setPort(port);
        factory.setUsername(username);
        factory.setPassword(password);
        //创建一个通道channel,其中包含了绝大多数的api。
        // 值得注意的是,创建channel的时候我们可以使用try-with-resources语法,
        // connection和channel都实现了Closeable接口,我们就不需要在代码中再写close相关的代码了
        //建立连接
        return factory.newConnection();
    }
}

1、简单模式(单生产、单消费)
在这里插入图片描述

生产者:

package com.byz.rabbitmq.rabbitmqdemo.service;

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

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;

/**
 * 发送消息,消息生产者
 */
public class SendMessage {

    private final static String QUEUE_NAME = "hello";

    public static void main(String[] args) {
        try {
        	// 初始化连接
            Connection connection = ConnectionUtil .getConnection();
            //建立通道
            Channel channel = connection.createChannel();
            //声明一个queue
            /**参数:
	         * 队列名
	         * 是否持久化
	         *  是否排外  即只允许该channel访问该队列   一般等于true的话用于一个队列只能有一个消费者来消费的场景
	         *  是否自动删除  消费完删除
	         *  其他属性
	         */    
	        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
            //message
            String message = "Hello World! Hello World!";
            //发送消息
            /**参数:
	         * 交换机
	         * 队列名
	         * 其他属性  路由
	         * 消息body
	         */
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
            System.out.println(" [x] Send '" + message + "'");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
}

消费者:

package com.byz.rabbitmq.rabbitmqdemo.service;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * 接收消息
 */
public class ReceiveMessage {
    //队列名称(与生产者队列名称保持一致)
    private final static String QUEUE_NAME = "hello";

    public static void main(String[] args) {
        try {
        	// 初始化连接
            Connection connection = ConnectionUtil .getConnection();
            //创建连接
            Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();
            channel.queueDeclare(QUEUE_NAME,false,false,false,null);
            //接收消息(lambda表达式写法)
            DeliverCallback  deliverCallback = (consumerTag, delivery) -> {
                String message = new String(delivery.getBody(), "UTF-8");
                System.out.println(" [x] Received '" + message + "'");
            };
            channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }

}

2、工作模式(Work queues)
在这里插入图片描述

该模式为简单模式的扩展模式,即在简单模式下新增多个消费者,所有消费者消费的消息完全相同。

3、发布/订阅者模式(Publish/Subscribe)
在这里插入图片描述

生产者:

package com.byz.rabbitmq.rabbitmqdemo.service;

import com.byz.rabbitmq.rabbitmqdemo.utils.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

/**
 * 发布/订阅者模式
 * 工作原理:消息生产者生产消息,发送给交换机,由交换机转发给绑定该交换机的队列
 *          消息消费者,监听绑定交换机的消息队列,接收消息,处理并回复
 */
public class SendMessageByPubAndSub {
    //定义交换机
    private final static String EXCHANGE = "exchange_test";

    public static void main(String[] args) {
        Connection connection = null;
        Channel channel = null;
        try {
            //创建连接工厂,并初始化工厂参数
            //由工厂初始化一个连接
            connection = ConnectionUtil.getConnection();
            //初始化一个通道
            channel = connection.createChannel();
            //声明交换机 发布订阅者模式交换机必须声明为:fanout
            channel.exchangeDeclare(EXCHANGE,"fanout");
            for (int i = 0; i <10; i++) {
                //定义消息内容
                String message = "publish/subscribe send message:" + i;
                //发送消息
                channel.basicPublish(EXCHANGE,"",null,message.getBytes("UTF-8"));
                System.out.println("发送消息:" + message);
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

消费者:

package com.byz.rabbitmq.rabbitmqdemo.service;

import com.byz.rabbitmq.rabbitmqdemo.utils.ConnectionUtil;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * 发布/订阅者    接收消息
 */
public class ReceiveMessageByPubAndSub {
    //定义交换机
    private final static String EXCHANGE = "exchange_test";
    //定义队列
    private final static String QUEUE = "queue_test_01";

    public static void main(String[] args) {
        try {
            //初始化连接工厂
            //创建连接
            Connection connection = ConnectionUtil.getConnection();
            //获取通道
            Channel channel = connection.createChannel();
            //声明交换机(分发:发布/订阅模式)
            channel.exchangeDeclare(EXCHANGE, "fanout");
            //声明队列
            channel.queueDeclare(QUEUE, false, false, false, null);
            //将队列绑定到交换机
            channel.queueBind(QUEUE, EXCHANGE, "");
            //设置每次分发个数
            channel.basicQos(1);
            //定义消费者
            DefaultConsumer consumer = new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    //接收消息内容
                    String message = new String(body,"UTF-8");
                    System.out.println("publish/subsecribe 接收消息内容:" + message);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        //设置手动应答
                        System.out.println("消息应答");
                        //手动应答消息
                        channel.basicAck(envelope.getDeliveryTag(),false);
                    }
                }
            };
            //监听队列并设置手动应答
            channel.basicConsume(QUEUE,false,consumer);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4、路由模式(Routing)
在这里插入图片描述

生产者:

package com.byz.rabbitmq.rabbitmqdemo.service;

import com.byz.rabbitmq.rabbitmqdemo.utils.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeoutException;

/**
 * 路由模式
 * 生产者:必须定义交换机和路由,生产消息时必须指定分发到哪个交换机的哪个路由上,交换机模式声明为direct。
 * 消费者:必须定义交换机、路由和队列,接收消息时必须指定接收哪个交换机的哪个路由上的消息(即队列绑定交换机并指定路由),否则接收不到消息。
 */
public class SendMessageByDirect {
    //定义交换机名称
    private final static String DIRECT_EXCHANGE_NAME = "direct_exchange_name";
    //定义路由名称,info级别
    private final static String ROUTING_NAME_INFO = "routing_name_info";
    //定义路由名称,waring级别
    private final static String ROUTING_NAME_WARING = "routing_name_waring";
    //定义路由名称,error级别
    private final static String ROUTING_NAME_ERROR = "routing_name_error";
    //定义路由名称,debug级别
    private final static String ROUTING_NAME_DEBUG = "routing_name_debug";

    public static void main(String[] args) {
        try {
            //初始化连接
            Connection connection = ConnectionUtil.getConnection();
            //获取通道
            Channel channel = connection.createChannel();
            //声明交换机
            channel.exchangeDeclare(DIRECT_EXCHANGE_NAME,"direct");
            //定义消息
            String messageInfo = "this is a info message";
            String messageDebug = "this is a debug message";
            String messageError = "this is a error message";
            String messageWaring = "this is a waring message";
            //发送消息
            channel.basicPublish(DIRECT_EXCHANGE_NAME,ROUTING_NAME_INFO,null,messageInfo.getBytes(Charset.defaultCharset()));
            System.out.println("[info] send message:" + messageInfo);
            channel.basicPublish(DIRECT_EXCHANGE_NAME,ROUTING_NAME_DEBUG,null,messageDebug.getBytes(Charset.defaultCharset()));
            System.out.println("[debug] send message:" + messageDebug);
            channel.basicPublish(DIRECT_EXCHANGE_NAME,ROUTING_NAME_ERROR,null,messageError.getBytes(Charset.defaultCharset()));
            System.out.println("[error] send message:" + messageError);
            channel.basicPublish(DIRECT_EXCHANGE_NAME,ROUTING_NAME_WARING,null,messageWaring.getBytes(Charset.defaultCharset()));
            System.out.println("[waring] send message:" + messageWaring);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
}

消费者:

package com.byz.rabbitmq.rabbitmqdemo.service;

import com.byz.rabbitmq.rabbitmqdemo.utils.ConnectionUtil;
import com.rabbitmq.client.*;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeoutException;

/**
 * 路由模式,消费者1
 */
public class ReceiveMessageByDirect1 {
    //定义交换机名称
    private final static String DIRECT_EXCHANGE_NAME = "direct_exchange_name";
    //定义队列名称
    private final static String QUEUE_NAME = "queue_name";
    //定义路由名称,info级别
    private final static String ROUTING_NAME_INFO = "routing_name_info";
    //定义路由名称,waring级别
    private final static String ROUTING_NAME_WARING = "routing_name_waring";
    //定义路由名称,error级别
    private final static String ROUTING_NAME_ERROR = "routing_name_error";
    //定义路由名称,debug级别
    private final static String ROUTING_NAME_DEBUG = "routing_name_debug";

    public static void main(String[] args) {
        try {
            //初始化连接
            Connection connection = ConnectionUtil.getConnection();
            //获取通道
            Channel channel = connection.createChannel();
            //声明交换机
            channel.exchangeDeclare(DIRECT_EXCHANGE_NAME,"direct");
            //声明队列
            channel.queueDeclare(QUEUE_NAME,false,false,false,null);
            //队列绑定到交换机上
            channel.queueBind(QUEUE_NAME,DIRECT_EXCHANGE_NAME,ROUTING_NAME_DEBUG);
//            channel.queueBind(QUEUE_NAME,DIRECT_EXCHANGE_NAME,ROUTING_NAME_INFO);
//            channel.queueBind(QUEUE_NAME,DIRECT_EXCHANGE_NAME,ROUTING_NAME_WARING);
            channel.queueBind(QUEUE_NAME,DIRECT_EXCHANGE_NAME,ROUTING_NAME_ERROR);
            //设置只分发一次
            channel.basicQos(1);
            //定义消费者
            DefaultConsumer consumer = new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    //获取消息内容
                    String message = new String(body, Charset.defaultCharset());
                    System.out.println("[receive] message:" + message);
                    //手动应答
                    channel.basicAck(envelope.getDeliveryTag(),false);
                }
            };
            //监听队列,设置手动应答
            channel.basicConsume(QUEUE_NAME,false,consumer);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
}

5、主题模式(Topics)
在这里插入图片描述
生产者:

package com.byz.rabbitmq.rabbitmqdemo.service;

import com.byz.rabbitmq.rabbitmqdemo.utils.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeoutException;

/**
 * topic模式
 * 路由键匹配类型有两种:
 *      1、# 匹配一个或多个 (常用)
 *      2、* 匹配一个
 * 生产者:指定交换机类型为topic,发送消息时,指定交换机和路由类型
 * 消费者:声明队列,绑定队列到指定交换机并指定路由类型,接收消息时只接收路由类型匹配成功的消息
 *
 */
public class SendMessageByTopic {
    //定义交换机
    private final static String EXCHANGE_TOPIC_NAME = "exchange_topic_name";
    //定义路由键
    private final static String ROUTING_TOPIC_MESSAGE_KEY_ADD = "key.add";
    private final static String ROUTING_TOPIC_MESSAGE_KEY_UPDATE = "key.update";

    public static void main(String[] args) {
        try {
            //初始化连接
            Connection connection = ConnectionUtil.getConnection();
            //创建连接通道
            Channel channel = connection.createChannel();
            //声明交换机
            channel.exchangeDeclare(EXCHANGE_TOPIC_NAME,"topic");
            //发送消息
            String message = "this is a topic key.add message";
            channel.basicPublish(EXCHANGE_TOPIC_NAME,ROUTING_TOPIC_MESSAGE_KEY_ADD,null,message.getBytes(Charset.defaultCharset()));
            System.out.println("[topic] send message:" + message);
            String messageEdit = "this is a topic key.update message";
            channel.basicPublish(EXCHANGE_TOPIC_NAME,ROUTING_TOPIC_MESSAGE_KEY_UPDATE,null,messageEdit.getBytes(Charset.defaultCharset()));
            System.out.println("[topic] send messge:" + messageEdit);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }

}

消费者:

package com.byz.rabbitmq.rabbitmqdemo.service;

import com.byz.rabbitmq.rabbitmqdemo.utils.ConnectionUtil;
import com.rabbitmq.client.*;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeoutException;

/**
 * topic模式,消息接收类
 */
public class ReceiveMessageByTopic {
    //定义交换机
    private final static String EXCHANGE_TOPIC_NAME = "exchange_topic_name";
    //定义路由键
    private final static String ROUTING_TOPIC_MESSAGE_KEY_ALL = "key.#";
    //定义队列名称
    private final static String QUEUE_TOPIC_NAME = "queue_topic_name";

    public static void main(String[] args) {
        try {
            //初始化连接
            Connection connection = ConnectionUtil.getConnection();
            //创建通道
            Channel channel = connection.createChannel();
            //声明队列
            channel.queueDeclare(QUEUE_TOPIC_NAME,false,false,false,null);
            //绑定队列到交换机上,指定接收消息的路由键
            channel.queueBind(QUEUE_TOPIC_NAME,EXCHANGE_TOPIC_NAME,ROUTING_TOPIC_MESSAGE_KEY_ALL);
            //指定每次分发个数
            channel.basicQos(1);
            //接收消息
            DefaultConsumer consumer = new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    //获取消息
                    String message = new String(body, Charset.defaultCharset());
                    System.out.println("[topic] receive message:" + message);
                    //设置手动应答
                    channel.basicAck(envelope.getDeliveryTag(),false);
                }
            };
            //监控队列
            channel.basicConsume(QUEUE_TOPIC_NAME,false,consumer);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值