二、消息中间件RabbitMQ之入门使用

1、使用RabbitMQ原生Java客户端进行消息通信

首先比较推荐使用Maven项目来学习,JDK版本在1.8及以上版本。要使用RabbitMQ客户端需要引用amqp-client-5.0.0.jar和slf4j-api-1.6.1.jar两个依赖包

第一步首选添加以下依赖

<dependency>
	<groupId>com.rabbitmq</groupId>
	<artifactId>amqp-client</artifactId>
	<version>5.0.0</version>
</dependency>

2.Direct交换器的基本使用

生产者

生产者主要就是用于消息的生产,并且将消息通过交换器,将消息由路由键和队列的匹配关系发送到指定的队列上的过程。

package com.kevin.task.exchange.direct;

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

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

/**
 * 描述:Direct交换器生产者<br/>
 * 创建人: Kevin Lea <br/>
 * 创建时间: 2019-9-22 14:24<br/>
 * 版本:1.0
 */
public class DirectProduct {
    public final static String EXCHANGE_NAME = "direct_exchange";

    public static void main(String[] args) throws IOException,TimeoutException {
        //1.创建连接,连接到RabbitMQ
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //2.设置连接地址,和端口,默认是5672
        connectionFactory.setHost("172.0.0.1");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("test");
        connectionFactory.setPassword("test");
        connectionFactory.setVirtualHost("myhost");

        //3.创建连接
        Connection connection = connectionFactory.newConnection();

        //4.创建信道
        Channel channel = connection.createChannel();

        //5.在信道中去设置交换器
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);

        //6.申明队列,可以在消费者地方申明,也可以在生产者地方申明,这里采用在消费者地方申明

        //7.申明路由键
        String[] routeKeys = {"apple","huawei","xiaomi"};
        for(int i=0;i<routeKeys.length;i++){
            String routeKey = routeKeys[i%3];
            String msg = "I like " + routeKey + (i+1);
            channel.basicPublish(EXCHANGE_NAME,routeKey,null,msg.getBytes());
            System.out.println("Send:" + routeKey + ":" + msg);
        }

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

消费者

Direct交换器有四种使用方法:1.生产者消费者一般用法;2.队列和交换器的多重绑定;3.一个连接多个信道;4.一个队列多个消费者。那下面我们看看这四种消费者是如何实现的。

  • 1.生产者消费者一般用法
package com.kevin.task.exchange.direct;

import com.rabbitmq.client.*;

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

/**
 * 描述:一般使用方法<br/>
 * 创建人: Kevin Lea <br/>
 * 创建时间: 2019-9-22 14:42<br/>
 * 版本:1.0
 */
public class NormalConsumer {
    public static void main(String[] args) throws IOException,TimeoutException {
        //1.创建连接,连接到RabbitMQ
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //2.设置连接地址,和端口,默认是5672
        connectionFactory.setHost("172.0.0.1");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("test");
        connectionFactory.setPassword("test");
        connectionFactory.setVirtualHost("myhost");

        //3.创建连接
        Connection connection = connectionFactory.newConnection();

        //4.创建信道
        Channel channel = connection.createChannel();

        //5.在信道中去设置交换器
        channel.exchangeDeclare(DirectProduct.EXCHANGE_NAME, BuiltinExchangeType.DIRECT);

        //6.申明队列,之前在生产者地方没有创建的队列在这里创建了
        String queueName = "queue-apple";
        /**
         * 第一个参数:队列名称
         * 第二个参数:是否是持久队列
         * 第三个参数:是否是独占队列
         * 第四个参数:是否自动删除队列
         * 第五个参数:队列的其他属性是一个hashmap
         */
        channel.queueDeclare(queueName,false,false,false,null);

        //7.绑定路由键,这里只绑定apple做测试,其他所有的key不接收
        String routeKey = "apple";
        channel.queueBind(queueName,DirectProduct.EXCHANGE_NAME,routeKey);
        System.out.println("waiting for message......");

        //8.申明消费者去消费-回调函数
        final Consumer 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("received:["+envelope.getRoutingKey()+"]" + message);
            }
        };

        //9.消费者正式在一个指定的队列上消费
        //第一个参数:队列名称
        //第二个参数:是否自动确认
        //第三个参数:回调函数
        channel.basicConsume(queueName,true,consumer);

    }
}
  • 2.队列和交换器的多重绑定
package com.kevin.task.exchange.direct;

import com.rabbitmq.client.*;

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

/**
 * 描述:队列和交换器的多重绑定<br/>
 * 创建人: Kevin Lea <br/>
 * 创建时间: 2019-9-22 14:42<br/>
 * 版本:1.0
 */
public class MultiBindConsumer {
    public static void main(String[] args) throws IOException,TimeoutException {
        //1.创建连接,连接到RabbitMQ
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //2.设置连接地址,和端口,默认是5672
        connectionFactory.setHost("172.0.0.1");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("test");
        connectionFactory.setPassword("test");
        connectionFactory.setVirtualHost("myhost");

        //3.创建连接
        Connection connection = connectionFactory.newConnection();

        //4.创建信道
        Channel channel = connection.createChannel();

        //5.在信道中去设置交换器
        channel.exchangeDeclare(DirectProduct.EXCHANGE_NAME, BuiltinExchangeType.DIRECT);

        //6.申明随机队列
        String queueName = channel.queueDeclare().getQueue();

        //7.绑定路由键
        String[] routeKeys = {"apple","huawei","xiaomi"};
        for(String routeKey : routeKeys){
            channel.queueBind(queueName,DirectProduct.EXCHANGE_NAME,routeKey);
        }
        System.out.println("waiting for message......");

        //8.申明消费者去消费
        final Consumer 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("received:["+envelope.getRoutingKey()+"]" + message);
            }
        };

        //9.消费者正式在一个指定的队列上消费
        channel.basicConsume(queueName,true,consumer);

    }
}
  • 3.一个连接多个信道
package com.kevin.task.exchange.direct;

import com.rabbitmq.client.*;

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

/**
 * 描述:一个连接多个信道<br/>
 * 创建人: Kevin Lea <br/>
 * 创建时间: 2019-9-22 14:42<br/>
 * 版本:1.0
 */
public class MultiChannerConsumer {
    public static void main(String[] args) throws IOException,TimeoutException {
        //1.创建连接,连接到RabbitMQ
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //2.设置连接地址,和端口,默认是5672
        connectionFactory.setHost("172.0.0.1");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("test");
        connectionFactory.setPassword("test");
        connectionFactory.setVirtualHost("myhost");

        //3.创建连接
        Connection connection = connectionFactory.newConnection();

		//创建两个子线程去创建信道,这里创建2个信道,都共同用同一个connection
        for(int i=0;i<2;i++){
            Thread thread = new Thread(new ConsumerWork(connection));
            thread.start();
        }

    }

	/**
     * 内部静态类
     */
    public static class ConsumerWork implements Runnable{
        private final Connection connection;

        public ConsumerWork(Connection connection) {
            this.connection = connection;
        }

        public void run() {
            try {
                //4.创建信道
                Channel channel = connection.createChannel();

                //5.在信道中去设置交换器
                channel.exchangeDeclare(DirectProduct.EXCHANGE_NAME, BuiltinExchangeType.DIRECT);

                //6.申明随机队列
                String queueName = channel.queueDeclare().getQueue();

                //7.绑定路由键
                String[] routeKeys = {"apple","huawei","xiaomi"};
                for(String routeKey : routeKeys){
                    channel.queueBind(queueName,DirectProduct.EXCHANGE_NAME,routeKey);
                }
				//消费者名称,这里用线程的名称作为消费者名称
                final String consumerName = Thread.currentThread().getName() + "-all";

                System.out.println("["+consumerName+"]waiting for message......");



                //8.申明消费者去消费
                final Consumer 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("["+consumerName+"]received:["+envelope.getRoutingKey()+"]" + message);
                    }
                };

                //9.消费者正式在一个指定的队列上消费
                channel.basicConsume(queueName,true,consumer);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
  • 4.一个队列多个消费者。那下面我们看看这四种消费者是如何实现的
package com.kevin.task.exchange.direct;

import com.rabbitmq.client.*;

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

/**
 * 描述:一个队列多个消费者<br/>
 * 创建人: Kevin Lea <br/>
 * 创建时间: 2019-9-22 14:42<br/>
 * 版本:1.0
 */
public class MultiConsumerOneQueue {
    public static void main(String[] args) throws IOException,TimeoutException {
        //1.创建连接,连接到RabbitMQ
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //2.设置连接地址,和端口,默认是5672
        connectionFactory.setHost("172.0.0.1");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("test");
        connectionFactory.setPassword("test");
        connectionFactory.setVirtualHost("myhost");

        //3.创建连接
        Connection connection = connectionFactory.newConnection();
		//申明一个唯一的队列名称
        String queueName = "OnlyQueue";

		//创建3个任务
        for(int i=0;i<3;i++){
            Thread thread = new Thread(new ConsumerWork(connection,queueName));
            thread.start();
        }

    }

	/**
	 * 内部静态类,一个连接,一个队列,多个消费者
	 */
    public static class ConsumerWork implements Runnable{
        private final Connection connection;
        private final String queueName;

        public ConsumerWork(Connection connection,String queueName) {
            this.connection = connection;
            this.queueName = queueName;
        }

        public void run() {
            try {
                //4.创建信道
                Channel channel = connection.createChannel();

                //5.在信道中去设置交换器
                channel.exchangeDeclare(DirectProduct.EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
				/**
		         * 第一个参数:队列名称
		         * 第二个参数:是否是持久队列
		         * 第三个参数:是否是独占队列
		         * 第四个参数:是否自动删除队列
		         * 第五个参数:队列的其他属性是一个hashmap
		         */
          		channel.queueDeclare(queueName,false,false,false,null);

                //7.绑定路由键
                String[] routeKeys = {"apple","huawei","xiaomi"};
                for(String routeKey : routeKeys){
                    channel.queueBind(queueName,DirectProduct.EXCHANGE_NAME,routeKey);
                }

                final String consumerName = Thread.currentThread().getName() + "-all";

                System.out.println("["+consumerName+"]waiting for message......");



                //8.申明消费者去消费
                final Consumer 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("["+consumerName+"]received:["+envelope.getRoutingKey()+"]" + message);
                    }
                };

                //9.消费者正式在一个指定的队列上消费
                channel.basicConsume(queueName,true,consumer);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

3.Fanout交换器的基本使用

Fanout其实就是一个广播模式,在这里消费者其实绑定什么路由键都是无所谓的,生产者生产的消息他们其实都是可以收的到的。

生产者

package com.kevin.task.exchange.fanout;

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

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

/**
 * 描述:Fanout生产者,除了交换器类型不一样外,其他基本上是一样的<br/>
 * 创建人: Kevin Lea <br/>
 * 创建时间: 2019-9-22 14:24<br/>
 * 版本:1.0
 */
public class FanoutProduct {
    public final static String EXCHANGE_NAME = "fanout_exchange";

    public static void main(String[] args) throws IOException,TimeoutException {
        //1.创建连接,连接到RabbitMQ
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //2.设置连接地址,和端口,默认是5672
        connectionFactory.setHost("172.0.0.1");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("test");
        connectionFactory.setPassword("test");
        connectionFactory.setVirtualHost("myhost");

        //3.创建连接
        Connection connection = connectionFactory.newConnection();

        //4.创建信道
        Channel channel = connection.createChannel();

        //5.在信道中去设置交换器,这里指定FANOUT类型
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);

        //6.申明队列,可以在消费者地方申明,也可以在生产者地方申明,这里采用在消费者地方申明

        //7.申明路由键
        String[] routeKeys = {"apple","huawei","xiaomi"};
        for(int i=0;i<routeKeys.length;i++){
            String routeKey = routeKeys[i%3];
            String msg = "I like " + routeKey + (i+1);
            channel.basicPublish(EXCHANGE_NAME,routeKey,null,msg.getBytes());
            System.out.println("Send:" + routeKey + ":" + msg);
        }

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

消费者

这里可以启动多个下面的想消费者。用于监听消息广播,可以把每个消费者的绑定的路由键给设置成不同的,或者设置成生产者没有的路由键也可以。主要测试消费者是否能够全部收到消息。

package com.kevin.task.exchange.fanout;

import com.kevin.task.exchange.direct.DirectProduct;
import com.rabbitmq.client.*;

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

/**
 * 描述:FANOUT方式的消费者<br/>
 * 创建人: Kevin Lea <br/>
 * 创建时间: 2019-9-22 14:42<br/>
 * 版本:1.0
 */
public class Consumer1 {
    public static void main(String[] args) throws IOException,TimeoutException {
        //1.创建连接,连接到RabbitMQ
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //2.设置连接地址,和端口,默认是5672
        connectionFactory.setHost("172.0.0.1");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("test");
        connectionFactory.setPassword("test");
        connectionFactory.setVirtualHost("myhost");

        //3.创建连接
        Connection connection = connectionFactory.newConnection();

        //4.创建信道
        Channel channel = connection.createChannel();

        //5.在信道中去设置交换器
        channel.exchangeDeclare(FanoutProduct.EXCHANGE_NAME, BuiltinExchangeType.FANOUT);

        //6.申明队列
        String queueName = channel.queueDeclare().getQueue();

        //7.绑定路由键,这里只绑定apple做测试
        String routeKey = "all";
        channel.queueBind(queueName,FanoutProduct.EXCHANGE_NAME,routeKey);
        System.out.println("waiting for message......");

        //8.申明消费者去消费
        final Consumer 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("received:["+envelope.getRoutingKey()+"]" + message);
            }
        };

        //9.消费者正式在一个指定的队列上消费
        channel.basicConsume(queueName,true,consumer);

    }
}

4.Topic交换器的基本使用

Topic交换器主要呢也就是绑定路由键有很多姿势,路由键一般是有几个段组成每个段之间呢用点号分割(例如a.b.c),这里主要有两种方式做路由键匹配一个是#一个是*。
#匹配一个或者多个(例如a.#)
*匹配一个(a.*.c)

生产者

package com.kevin.task.exchange.topic;

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

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

/**
 * 描述:Topic交换器的基本使用-生产者<br/>
 * 创建人: Kevin Lea <br/>
 * 创建时间: 2019-9-22 14:24<br/>
 * 版本:1.0
 */
public class TopicProduct {
    public final static String EXCHANGE_NAME = "topic_exchange";

    public static void main(String[] args) throws IOException,TimeoutException {
        //1.创建连接,连接到RabbitMQ
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //2.设置连接地址,和端口,默认是5672
        connectionFactory.setHost("172.0.0.1");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("test");
        connectionFactory.setPassword("test");
        connectionFactory.setVirtualHost("myhost");

        //3.创建连接
        Connection connection = connectionFactory.newConnection();

        //4.创建信道
        Channel channel = connection.createChannel();

        //5.在信道中去设置交换器
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);

        //6.申明队列,可以在消费者地方申明,也可以在生产者地方申明,这里采用在消费者地方申明

        //7.申明路由键
        String[] phones = {"apple","huawei","xiaomi"};
        for(int i=0;i<phones.length;i++){
            String[] products = {"iphone","MATE","ReadMi"};
            for(int j=0;j<products.length;j++){
                String[] versions = {"11","20","9"};
                for(int k=0;k<versions.length;k++){
                    String routeKey = phones[i%3] + "." + products[j%3] + "." + versions[k%3];
                    String msg = "I like " + routeKey + (i+1);
                    channel.basicPublish(EXCHANGE_NAME,routeKey,null,msg.getBytes());
                    System.out.println("Send:" + routeKey + ":" + msg);
                }
            }

        }

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

消费者

package com.kevin.task.exchange.topic;

import com.rabbitmq.client.*;

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

/**
 * 描述:Topic交换器的基本使用-消费者<br/>
 * 创建人: Kevin Lea <br/>
 * 创建时间: 2019-9-22 14:42<br/>
 * 版本:1.0
 */
public class ALL_Consumer {
    public static void main(String[] args) throws IOException,TimeoutException {
        //1.创建连接,连接到RabbitMQ
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //2.设置连接地址,和端口,默认是5672
        connectionFactory.setHost("172.0.0.1");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("test");
        connectionFactory.setPassword("test");
        connectionFactory.setVirtualHost("myhost");

        //3.创建连接
        Connection connection = connectionFactory.newConnection();

        //4.创建信道
        Channel channel = connection.createChannel();

        //5.在信道中去设置交换器
        channel.exchangeDeclare(TopicProduct.EXCHANGE_NAME, BuiltinExchangeType.TOPIC);

        //6.申明队列
        String queueName = channel.queueDeclare().getQueue();

        //7.绑定路由键,这里只匹配apple开头的消息
        String routeKey = "apple.#";
        channel.queueBind(queueName,TopicProduct.EXCHANGE_NAME,routeKey);
        System.out.println("waiting for message......");

        //8.申明消费者去消费
        final Consumer 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("received:["+envelope.getRoutingKey()+"]" + message);
            }
        };

        //9.消费者正式在一个指定的队列上消费
        channel.basicConsume(queueName,true,consumer);

    }
}

消息中间件传送门

消息中间件理论概述
一、消息中间件RabbitMQ之Linux安装过程
二、消息中间件RabbitMQ之入门使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值