一、安装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); } }
如果队列不存在,需要先启动消费者,才会先将生成队列,不然生产者发送的消息不知道路由到哪个队列,因为队列的声明,以及和交换机的绑定是在消费者这边做的。