新建工具类获取MQ的连接,代码如下:
public class ConnectionUtil
{
public static Connection getConnection() throws Exception {
//定义连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置服务地址
factory.setHost("localhost");
//端口
factory.setPort(5672);
//设置账号信息,用户名、密码、vhost
factory.setVirtualHost("/");
factory.setUsername("guest");
factory.setPassword("guest");
// 通过工程获取连接
Connection connection = factory.newConnection();
return connection;
}
}
1.不用交换机的队列
API介绍
/*
* 创建队列
* queue:队列名称
* durable:队列持久化标志,ture为持久化
* exclusive:排他队列
* autoDelete:自动删除
* arguments:Map类型,关于队列及队列中消息的详细设置
*/
channel.queueDeclare(queue, durable, exclusive, autoDelete, arguments)
创建生产者:
public static void main(String[] argv) throws Exception {
// 获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
// 从连接中创建通道
Channel channel = connection.createChannel();
// 声明(创建)队列
channel.queueDeclare("q_test_01", false, false, false, null);
// 消息内容
String message = "Hello World!";
channel.basicPublish("", "q_test_01", null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
//关闭通道和连接
channel.close();
connection.close();
}
创建一个名为q_test_01的队列并向其发送Hello World!消息,运行代码,在浏览器里输入http://localhost:15672/#/在管理工具中查看:
在管理平台上我们看到队列中已经有一个名为q_test_01的队列,点击队列名称,查询具体的队列中的信息:
创建消费者:
public static void main(String[] argv) throws Exception {
// 获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
// 从连接中创建通道
Channel channel = connection.createChannel();
// 声明队列
channel.queueDeclare("q_test_01", false, false, false, null);
// 定义队列的消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 监听队列
channel.basicConsume("q_test_01", true, consumer);
// 获取消息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
}
}
运行代码,查看控制台日志:
2.fanout类型的交换机
消息与队列匹配规则:fanout类型交换机会将接收到的消息广播给所有与之绑定的队列。 如图所示:这种广播机制,生产者P只关心发给哪个交换机X,消费者C只关心订阅了哪个队列
创建生产者:
public static void main(String[] argv) throws Exception {
// 获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
// 从连接中创建通道
Channel channel = connection.createChannel();
// 声明转发器和类型
channel.exchangeDeclare("fanout_exchange", "fanout" );
// 消息内容
String message = "Hello World fanout!";
channel.basicPublish("fanout_exchange", "", null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
//关闭通道和连接
channel.close();
connection.close();
}
在代码里我们声明了一个类型为fanout类型名称为fanout_exchange的转换器,并向该转换器发送了一个"Hello World fanout!"的消息,运行代码,在管理平台查看:
我们可以看到在管理平台的交换器列表中已经有我们之前创建的队列了。
创建消费者:
public static void main(String[] argv) throws Exception {
// 获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
// 从连接中创建通道
Channel channel = connection.createChannel();
// 声明转发器和类型
channel.exchangeDeclare("fanout_exchange", "fanout" );
// 创建一个非持久的、唯一的且自动删除的队列
String queueName = channel.queueDeclare().getQueue();
// 为转发器指定队列,设置binding
channel.queueBind(queueName, "fanout_exchange", "");
// 定义队列的消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 监听队列
channel.basicConsume(queueName, true, consumer);
// 获取消息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
}
}
声明 fanout_exchange转发器,并创建一个非持久的、唯一的且自动删除的队列和转发器关联。运行代码,查看控制台:
访问管理平台:
我们看到队列列表中多了一个临时的非持久的队列amq.gen-F7SJ57L8iXcBI-0Te1KB2Q,点击amq.gen-F7SJ57L8iXcBI-0Te1KB2Q:
点击Bindings,我们可以看到它已经和fanout_exchange转换器绑定到了一起。
3.direct类型的交换机
消息分发规则:消息会被推送至绑定键(binding key)和消息发布附带的选择键(routing key)完全匹配的队列。
创建生产者:
public static void main(String[] argv) throws Exception {
// 获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
// 从连接中创建通道
Channel channel = connection.createChannel();
// 声明转发器和类型
channel.exchangeDeclare("direct_exchange", "direct" );
// 消息内容
channel.basicPublish("direct_exchange", "error", null, "error routingkey".getBytes());
channel.basicPublish("direct_exchange", "info", null, "info routingkey".getBytes());
//关闭通道和连接
channel.close();
connection.close();
}
创建direct转换器direct_exchange,并向转换器发送routingkey为error的消息“error routingkey"和routingkey为info的消息“info routingkey"
创建消费者:
public static void main(String[] argv) throws Exception {
// 获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
// 从连接中创建通道
Channel channel = connection.createChannel();
// 声明转发器和类型
channel.exchangeDeclare("direct_exchange", "direct" );
// 创建一个非持久的、唯一的且自动删除的队列
String queueName = channel.queueDeclare().getQueue();
// 为转发器指定队列,设置binding
channel.queueBind(queueName, "direct_exchange", "error");
channel.queueBind(queueName, "direct_exchange", "info");
// 定义队列的消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 监听队列
channel.basicConsume(queueName, true, consumer);
// 获取消息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
}
}
指定binding_key将消息队列和转换器连接,运行代码查看控制台输出:
4.topic类型的交换机
消息分发规则:一个附带特殊的选择键将会被转发到绑定键与之匹配的队列中。可以简单理解为模糊匹配
创建生产者:
public static void main(String[] argv) throws Exception {
// 获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
// 从连接中创建通道
Channel channel = connection.createChannel();
// 声明转发器和类型
channel.exchangeDeclare("topic_exchange", "topic" );
// 消息内容
channel.basicPublish("topic_exchange", "fast.orange.yang", null, "I'm a topic message".getBytes());
//关闭通道和连接
channel.close();
connection.close();
}
在生产者代码里我们声明了一个topic类型的交换机topic_exchange,并向它发送了一个routingkey为fast.orange.yang的消息"I'm a topic message"
创建消费者:
public static void main(String[] argv) throws Exception {
// 获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
// 从连接中创建通道
Channel channel = connection.createChannel();
// 声明转发器和类型
channel.exchangeDeclare("topic_exchange", "topic" );
// 创建一个非持久的、唯一的且自动删除的队列
String queueName = channel.queueDeclare().getQueue();
// 为转发器指定队列,设置binding
channel.queueBind(queueName, "topic_exchange", "#.orange.#");
// 定义队列的消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 监听队列
channel.basicConsume(queueName, true, consumer);
// 获取消息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
}
}
创建一个队列与交换器绑定,binding_key为#.orange.#,先运行消费者在运行生产者,查看控制台输出:
5.headers类型的交换机
消息分发规则:headers类型的交换机分发消息不依赖routingKey,是使用发送消息时basicProperties对象中的headers来匹配的。headers是一个键值对类型,发送者发送消息时将这些键值对放到basicProperties对象中的headers字段中,队列绑定交换机时绑定一些键值对,当两者匹配时,队列就可以收到消息。匹配模式有两种,在队列绑定到交换机时用x-match来指定,all代表定义的多个键值对都要满足,而any则代码只要满足一个就可以了。fanout,direct,topic exchange的routingKey都需要要字符串形式的,而headers exchange则没有这个要求,因为键值对的值可以是任何类型。
创建生产者:
public static void main(String[] argv) throws Exception {
// 获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
// 从连接中创建通道
Channel channel = connection.createChannel();
//声明转发器和类型headers
channel.exchangeDeclare("headers_exchange", "headers", false,true,null);
Map<String,Object> headers = new Hashtable<String, Object>();
headers.put("aaa", "01234");
Builder properties = new BasicProperties.Builder();
properties.headers(headers);
// 指定消息发送到的转发器,绑定键值对headers键值对
channel.basicPublish("headers_exchange", "",properties.build(), "I'm a headers message".getBytes());
//关闭通道和连接
channel.close();
connection.close();
}
创建消费者:
public static void main(String[] argv) throws Exception {
// 获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
// 从连接中创建通道
Channel channel = connection.createChannel();
//声明转发器和类型headers
channel.exchangeDeclare("headers_exchange", "headers",false,true,null);
channel.queueDeclare("headers_queue",false, false, true,null);
Map<String, Object> headers = new Hashtable<>();
headers.put("x-match", "any");//all any
headers.put("aaa", "01234");
headers.put("bbb", "56789");
// 为转发器指定队列,设置binding 绑定header键值对
channel.queueBind("headers_queue", "headers_exchange","", headers);
// 定义队列的消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 监听队列
channel.basicConsume("headers_queue", true, consumer);
// 获取消息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
}
}
运行生产者和消费者代码查看控制台输出: