文章目录
Exchange 交换机: 接收消息,并根据路由键转发消息到所绑定的队列。
交换机属性
属性名称 | 介绍 |
---|---|
name | 交换机名称 |
type | 交换机类型 :direct,topic,fanout,headers |
Durability | 是否进行持久化 |
Auto Delete | 当最后一个绑定到Exchange上的队列删除后,自动删除 |
Internal | 当前Exchange是否用于RabbitMQ内部使用,默认为False。(大部分不需要) |
Arguments | 扩展参数,用户扩展AMQP协议,定制化使用 |
Exchange Type 简介:
type | 介绍 |
---|---|
Direct Exchange | 所有发送到Direct Exchange的消息被转发到RouteKey中指定的Queue |
Topic Exchange | 所有发送到Topic Exchange的消息被转发到所有关心RouteKey中指定的Topic的Queue上。 Exchange 将RoutKey和某Topic进行模糊匹配,此时队列需要绑定一个Topic |
Fanout Exchange | 不处理路由键,只需要简单的将队列绑定到交换机上。发送到交换机上都会转发到与该交换机绑定的所有队列上。Fanout 交换机发消息是最快的。 |
Header Exchange | 通过消息头进行路由(不常用) |
Exchange Type 详解:
Direct Exchange
介绍
Direct Exchange : 所有发送到Direct Exchange的消息被转发到RouteKey中指定的Queue
注意:Direct模式可以使用RabbitMQ自带的Exchange:default Exchange,所以不需要将Exchange进行任何绑定(bingding)操作,消息传递时,RouteKey必须完全匹配才会被队列接收,否则会被抛弃。
代码实现
public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
//1,创建工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//2,获取连接
Connection connection = connectionFactory.newConnection();
//3,通过connection创建一个channel
Channel channel = connection.createChannel();
//4,exchange, routingkey, queue, 并将queue和交换机绑定
String queueName = "test001";
//设置交换机
String exchangeName = "exchange001";
String exchangeType = "direct";
String routingKey = "routingKey001";
//声明一个交换机
channel.exchangeDeclare(exchangeName, exchangeType, true, false, false, null);
//声明一个队列
channel.queueDeclare(queueName, true, false, false, null);
//建立关系
channel.queueBind(queueName, exchangeName, routingKey);
//5,创建消费者//
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
//6,设置channel
channel.basicConsume(queueName, true, queueingConsumer);
//7,获取消息
while (true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
String msg = new String(delivery.getBody());
System.out.println(msg);
}
}
}
//生产者
public class producer {
public static void main(String[] args) throws IOException, TimeoutException {
//创建工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//获取连接
Connection connection = connectionFactory.newConnection();
//通过connection创建一个channel
Channel channel = connection.createChannel();
String exchangeName = "exchange001";
String routingKey = "routingKey0011";
//发布消息
for(int i = 0; i < 5; i++){
String msg = "hello rabbitmq " + i;
//1.exchange 2.routing key
//默认交换器隐式绑定到每个队列,其路由键等于队列名. 如果没有队列名,则会被删除
channel.basicPublish(exchangeName, routingKey, null, msg.getBytes());
}
channel.close();
connection.close();
}
}
Topic Exchange
介绍
Topic Exchange: 所有发送到Topic Exchange的消息被转发到所有关心RouteKey中指定的Topic的Queue上。Exchange 将RoutKey和某Topic进行模糊匹配,此时队列需要绑定一个Topic。
注意:可以使用通配符进行模糊匹配。
通配符 | 通配符简介 |
---|---|
# | 匹配一个词或多个词。eg: log.# 可以匹配到 log.info.add |
* | 只能匹配一个词。 eg: log.* 只能匹配到 log.info |
代码实现
import com.rabbitmq.client.*;
import javax.security.auth.callback.Callback;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 消费者类
*/
public class ConsumerTopic {
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
//1,创建工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//2,获取连接
Connection connection = connectionFactory.newConnection();
//3,通过connection创建一个channel
Channel channel = connection.createChannel();
//4,exchange, routingkey, queue, 并将queue和交换机绑定
String queueName = "topic001";
//设置交换机
String exchangeName = "exchange_topic";
String exchangeType = "topic";
String routingKey = "user.*";
//声明一个交换机
channel.exchangeDeclare(exchangeName, exchangeType, true, false, false, null);
//声明一个队列
channel.queueDeclare(queueName, true, false, false, null);
//建立关系
channel.queueBind(queueName, exchangeName, routingKey);
//5,创建消费者//
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
//6,设置channel
channel.basicConsume(queueName, true, queueingConsumer);
//7,获取消息
while (true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
String msg = new String(delivery.getBody());
System.out.println(msg);
}
}
}
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 生产者
*/
public class producer {
public static void main(String[] args) throws IOException, TimeoutException {
//创建工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//获取连接
Connection connection = connectionFactory.newConnection();
//通过connection创建一个channel
Channel channel = connection.createChannel();
String exchangeName = "exchange001";
String routingKey = "routingKey0011";
//发布消息
for(int i = 0; i < 5; i++){
String msg = "hello rabbitmq " + i;
//1.exchange 2.routing key
//默认交换器隐式绑定到每个队列,其路由键等于队列名. 如果没有队列名,则会被删除
channel.basicPublish(exchangeName, routingKey, null, msg.getBytes());
}
channel.close();
connection.close();
}
}
Fanout Exchange
介绍
Fanout Exchange: 不处理路由键,只需要简单的将队列绑定到交换机上。发送到交换机上都会转发到与该交换机绑定的所有队列上。Fanout 交换机发消息是最快的。
代码实现
package com.example.rabbitmq.fanout;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 消费者类
*/
public class ConsumerFanout {
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
//1,创建工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//2,获取连接
Connection connection = connectionFactory.newConnection();
//3,通过connection创建一个channel
Channel channel = connection.createChannel();
//4,exchange, routingkey, queue, 并将queue和交换机绑定
String queueName = "fanout001";
String queueName2 = "fanout002";
//设置交换机
String exchangeName = "exchange_fanout";
String exchangeType = "fanout";
String routingKey = "";
//声明一个交换机
channel.exchangeDeclare(exchangeName, exchangeType, true, false, false, null);
//声明一个队列
channel.queueDeclare(queueName, true, false, false, null);
channel.queueDeclare(queueName2, true, false, false, null);
//建立关系
channel.queueBind(queueName, exchangeName, routingKey);
channel.queueBind(queueName2, exchangeName, routingKey);
//5,创建消费者//
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
//6,设置channel
channel.basicConsume(queueName, true, queueingConsumer);
//7,获取消息
while (true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
String msg = new String(delivery.getBody());
System.out.println(msg);
}
}
}
package com.example.rabbitmq.fanout;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 生产者类
*/
public class producerFanout {
public static void main(String[] args) throws IOException, TimeoutException {
//创建工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//获取连接
Connection connection = connectionFactory.newConnection();
//通过connection创建一个channel
Channel chennel = connection.createChannel();
String exchangeName = "exchange_fanout";
String routingKey = "";
//发布消息
for(int i = 0; i < 5; i++){
String msg = "hello rabbitmq " + i;
//1.exchange 2.routing key
//默认交换器隐式绑定到每个队列,其路由键等于队列名. 如果没有队列名,则会被删除
chennel.basicPublish(exchangeName, routingKey, null, msg.getBytes());
}
chennel.close();
connection.close();
}
}
Headers Exchange
介绍
通过消息头进行路由(不常用)。
关键参数,x-match: 为all表示要匹配所有的header, 如果为any则表示只要匹配其中的一个header即可
//绑定队列时配置一个header
Map<String, Object> headerOne = new HashMap<>();
headerOne.put("college", "computer science");
headerOne.put("class", "001");
headerOne.put("x-match", "all"); //关键参数,x-match: 为all表示要匹配所有的header, 如果为any则表示只要匹配其中的一个header即可
channel.queueBind(queueNameOne, exchangeName, routingKey, headerOne);
具体代码如下:
package com.example.rabbitmq.header;
import com.example.rabbitmq.consumer.MyConsumer;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;
/**
* 消费者
*/
public class ConsumerHeader {
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
//1,创建工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//2,获取连接
Connection connection = connectionFactory.newConnection();
//3,通过connection创建一个channel
Channel channel = connection.createChannel();
//4,exchange, routingkey, queue, 并将queue和交换机绑定
String queueNameOne = "header001";
String queueNameTwo = "header002";
//设置交换机
String exchangeName = "exchange_headers";
String exchangeType = "headers";
String routingKey = "test.header";
//声明一个交换机
channel.exchangeDeclare(exchangeName, exchangeType, true, false, false, null);
//声明两个个队列
channel.queueDeclare(queueNameOne, true, false, false, null);
channel.queueDeclare(queueNameTwo, true, false, false, null);
//建立关系
//headerOne, 绑定队列时使用该headers
Map<String, Object> headerOne = new HashMap<>();
headerOne.put("college", "computer science");
headerOne.put("class", "001");
headerOne.put("x-match", "all"); //x-match: 为all表示要匹配所有的header, 如果为any则表示只要匹配其中的一个header即可
channel.queueBind(queueNameOne, exchangeName, routingKey, headerOne);
//headerOne, 绑定队列时使用该headers
Map<String, Object> headerTwo = new HashMap<>();
headerTwo.put("college", "computer science");
headerTwo.put("class", "001");
headerTwo.put("x-match", "any"); //x-match: 为all表示要匹配所有的header, 如果为any则表示只要匹配其中的一个header即可
channel.queueBind(queueNameTwo, exchangeName, routingKey, headerTwo);
//5,创建消费者One, 监听queueNameOne
channel.basicConsume(queueNameOne, true, new MyConsumerOne(channel));
//创建消费者Two, 监听queueNameTwo
channel.basicConsume(queueNameTwo, true, new MyConsumerTwo(channel));
}
static class MyConsumerOne extends DefaultConsumer {
public MyConsumerOne(Channel channel) {
super(channel);
}
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties basicProperties, byte[] body){
System.out.println("----- consumerOne message -----");
System.out.println("body = " + new String(body));
System.out.println("");
}
}
static class MyConsumerTwo extends DefaultConsumer {
public MyConsumerTwo(Channel channel) {
super(channel);
}
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties basicProperties, byte[] body){
System.out.println("----- consumerTwo message -----");
System.out.println("body = " + new String(body));
System.out.println("");
}
}
}
package com.example.rabbitmq.header;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;
/**
* 生产者
*/
public class producerHeader {
public static void main(String[] args) throws IOException, TimeoutException {
//创建工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//获取连接
Connection connection = connectionFactory.newConnection();
//通过connection创建一个channel
Channel chennel = connection.createChannel();
String exchangeName = "exchange_headers";
String routingKey = "";
//消息one, 发送到queue001
String msg = "hello rabbitmq one ";
//消息one的header
Map<String, Object> headerOne = new HashMap<>();
headerOne.put("college", "computer science");
headerOne.put("class", "001");
//配置消息的属性
AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
.headers(headerOne)
.build();
chennel.basicPublish(exchangeName, routingKey, properties, msg.getBytes());
//消息two, 发送到queue002
String msgTwo = "hello rabbitmq two ";
//消息one的header
Map<String, Object> headerTwo = new HashMap<>();
headerTwo.put("college", "computer science");
//配置消息的属性
AMQP.BasicProperties propertiesTwo = new AMQP.BasicProperties.Builder()
.headers(headerTwo)
.build();
chennel.basicPublish(exchangeName, routingKey, propertiesTwo, msgTwo.getBytes());
//关闭连接
chennel.close();
connection.close();
}
}
– 生成的exchange如下:
虽然配置了Routingkey 但是不生效