一、安裝RabbitMQ
安裝直接用docker安裝,如果手動安裝的話比較繁瑣,還要安裝erlang語言的環境。在安裝有docker機器上執行官網提供的指令(https://www.rabbitmq.com/download.html):docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management
安裝好之後 瀏覽器訪問15672端口,可以看到web管理端。默認的是用戶名密碼都是guest
二、AMQP協議(Advanced message queue protocol 高級消息隊列協議)核心概念和RabbitMQ整體架構
RabbitMQ是通過Erlang語言基於AMQP協議開發的。erlang語言常用於交換機上,因爲它的高效,自然rabbitMQ也很高效了。
這些概念在rabbitMQ的web控制檯都可以看見:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> <version>2.1.7.RELEASE</version> </dependency>
package com.nijunyang.rabbitmq.util; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import java.io.IOException; import java.util.concurrent.TimeoutException; /** * Description: * Created by nijunyang on 2020/5/27 10:24 */ public abstract class RabbitMQUtils { private static ConnectionFactory connectionFactory = new ConnectionFactory(); //設置連接工廠信息 static { connectionFactory.setHost("*.*.*.*"); connectionFactory.setPort(5672); connectionFactory.setUsername("guest"); connectionFactory.setPassword("guest"); } public static Connection getConnection() throws IOException, TimeoutException { Connection connection = connectionFactory.newConnection(); return connection; } public static void close(AutoCloseable...closeables) throws Exception { for (AutoCloseable closeable : closeables) { closeable.close(); } } }
消費者獲取連接,創建channel,聲明交換機和隊列,綁定交換機和隊列,準備接收消息
package com.nijunyang.rabbitmq.consumer; import ch.qos.logback.core.net.SyslogOutputStream; import com.nijunyang.rabbitmq.util.RabbitMQUtils; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.Consumer; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; import java.io.IOException; /** * Description: * Created by nijunyang on 2020/5/27 10:42 */ public class RabbitMQConsumer { public static void main(String[] args) throws Exception { Connection connection = RabbitMQUtils.getConnection(); Channel channel = connection.createChannel(); /*------------------*/ //1:默認消息投遞 消費 // String queueName = "hello.queue"; // //聲明一個隊列(如果沒有這個隊列,第一次是在消費者這邊在聲明的,所以要先啓動消費者,生產者消息纔有地方投遞) // channel.queueDeclare(queueName,true,false,true,null); /*------------------*/ //2:直連交換機 // String exchangeName = "njy.directchange"; //// String exchangeType = "direct"; //// //// String routingKey = "directchange.key";//發送和消費的要一模一樣 //// String queueName = "direct.queue"; //// //聲明一個交換機和隊列 //// channel.exchangeDeclare(exchangeName, exchangeType,true,false,null); //// channel.queueDeclare(queueName,true,false,false,null); //// //隊列和交換機通過routingKey綁定 //// channel.queueBind(queueName, exchangeName, routingKey); //// /*------------------*/ //3:topic交換機 String exchangeName = "njy.topicchange"; String routingKey = "directchange.#"; //.分割,#匹配多個,*匹配一個 String exchangeType = "topic"; String queueName = "topic.queue"; //聲明一個交換機和隊列 channel.exchangeDeclare(exchangeName, exchangeType,true,false,null); channel.queueDeclare(queueName,true,false,false,null); //隊列和交換機通過routingKey綁定 channel.queueBind(queueName, exchangeName, routingKey); /*------------------*/ //創建消費者 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(message); } }; channel.basicConsume(queueName,true, consumer); } }
生產者消費者獲取連接,創建channel,發送消息
package com.nijunyang.rabbitmq.producer; import com.nijunyang.rabbitmq.util.RabbitMQUtils; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import java.util.Random; /** * Description: * Created by nijunyang on 2020/5/27 10:18 */ public class RabbitMQProducer { public static void main(String[] args) throws Exception { Connection connection = RabbitMQUtils.getConnection(); Channel channel = connection.createChannel(); String message = "hello rabbitMQ." + new Random().nextInt(100); /*------------------*/ //1:默認消息投遞 // //參數String exchange, String routingKey, AMQP.BasicProperties props, byte[] body // //不設置交換機會發送到默認上面 // channel.basicPublish("", "hello.queue", null, message.getBytes("utf-8")); /*------------------*/ //2:直連交換機 // String exchangeName = "njy.directchange"; // String routingKey = "directchange.key"; //發送和消費的要一模一樣 /*------------------*/ //3.topic交換機 String exchangeName = "njy.topicchange"; String routingKey = "directchange.key"; //.分割,#匹配多個,*匹配一個 channel.basicPublish(exchangeName, routingKey, null, message.getBytes("utf-8")); /*------------------*/ RabbitMQUtils.close(channel, connection); } }
如果隊列不存在,需要先啓動消費者,纔會先將生成隊列,不然生產者發送的消息不知道路由到哪個隊列,因爲隊列的聲明,以及和交換機的綁定是在消費者這邊做的。