一、简单demo
本节主要学习生产者如何发布消息,本次使用direct交换器
如图,生产者主要是和交换器互动
1、准备创建连接、连接到RabbitMQ
这里采用工厂模式,先创建工厂
ConnectionFactory connectionFactory= new ConnectionFactory();
2、指定连接的MQ地址(这里使用默认端口5672)
connectionFactory.setHost("localhost");
3、创建连接(TCP连接)
Connection connection =connectionFactory.newConnection();
4、创建信道(复用TCP连接,节省资源)
Channel channel =connection.createChannel();
5、指定信道访问MQ中的哪个交换器,及其类型
这里演示direct交换器,也就是 一对一(一个路由键对应一个队列)
channel.exchangeDeclare(EXCHANGE_NAME,BuiltinExchangeType.DIRECT);
6、申明路由键,并向MQ发布消息
String[] routeKeys ={"zc1","zc2","zc3"};
for (int i=0;i<6;i++){
String routeKey = routeKeys[i%3];
String msg = "Hello,RabbitMQ"+(i+1);
//发布消息
/* EXCHANGE_NAME 交换器名
* routeKey 路由键
* null 控制
* msg.getBytes() 消息内容
* */
channel.basicPublish(EXCHANGE_NAME,routeKey,null,msg.getBytes());
System.out.println("Sent:"+routeKey+":"+msg);
}
7、关闭信道及连接
channel.close();
connection.close();
以上就是生产者发布消息的几个步骤
接下来介绍消费者,前几步和生产者类似
//创建连接、连接到RabbitMQ
ConnectionFactory connectionFactory= new ConnectionFactory();
//设置下连接工厂的连接地址(使用默认端口5672)
connectionFactory.setHost("localhost");
//创建连接
Connection connection =connectionFactory.newConnection();
//创建信道
Channel channel =connection.createChannel();
//在信道中设置交换器
channel.exchangeDeclare(DirectProducer.EXCHANGE_NAME,BuiltinExchangeType.DIRECT);
1、申明一个队列,后期就是从该队列取消息
String queueName="zcQueue";
channel.queueDeclare(queueName,false,false,false,null);
2、绑定
将队列(zcQueue)与交换器通过 路由键 绑定(zc)
这样生产者把消息发给交换器,交换器就知道将这条消息发给哪个队列中去了
String routeKey ="zc";
channel.queueBind(queueName,DirectProducer.EXCHANGE_NAME,routeKey);
System.out.println("waiting for message ......");
3、申明一个消费者
final Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String s, Envelope envelope, AMQP.BasicProperties basicProperties, byte[] bytes) throws IOException {
String message = new String(bytes,"UTF-8");
System.out.println("Received["+envelope.getRoutingKey()+"]"+message);
}
};
4、设置消息的响应
//消息者正是开始在指定队列上消费。
//TODO 这里第二个参数是自动确认参数,如果是true则是自动确认
channel.basicConsume(queueName,true,consumer);
至此,消费者也完成
完整代码如下:
生产者
public class DirectProducer {
public final static String EXCHANGE_NAME = "exchangeName";
public static void main(String[] args)
throws IOException, TimeoutException {
//创建连接、连接到RabbitMQ
ConnectionFactory connectionFactory= new ConnectionFactory();
//指定连接的MQ地址(这里使用默认端口5672)
connectionFactory.setHost("localhost");
//创建连接(TCP连接)
Connection connection =connectionFactory.newConnection();
//创建信道(复用TCP连接,节省资源)
Channel channel =connection.createChannel();
//指定信道访问MQ中的哪个交换器,及其类型
channel.exchangeDeclare(EXCHANGE_NAME,BuiltinExchangeType.DIRECT);
//申明队列(放在消费者中去做)
//申明路由键\消息体
String[] routeKeys ={"zc1","zc2","zc3"};
for (int i=0;i<6;i++){
String routeKey = routeKeys[i%3];
String msg = "Hello,RabbitMQ"+(i+1);
//发布消息
/* EXCHANGE_NAME 交换器名
* routeKey 路由键
* null 控制
* msg.getBytes() 消息内容
* */
channel.basicPublish(EXCHANGE_NAME,routeKey,null,msg.getBytes());
System.out.println("Sent:"+routeKey+":"+msg);
}
channel.close();
connection.close();
}
}
消费者
public class NormalConsumer {
public static void main(String[] argv)
throws IOException, TimeoutException {
//创建连接、连接到RabbitMQ
ConnectionFactory connectionFactory= new ConnectionFactory();
//设置下连接工厂的连接地址(使用默认端口5672)
connectionFactory.setHost("localhost");
//创建连接
Connection connection =connectionFactory.newConnection();
//创建信道
Channel channel =connection.createChannel();
//在信道中设置交换器
channel.exchangeDeclare(DirectProducer.EXCHANGE_NAME,BuiltinExchangeType.DIRECT);
//声明队列(单独绑定,下面还有多重绑定)
String queueName="zcQueuq";
channel.queueDeclare(queueName,false,false,false,null);
//绑定:将队列(zcQueuq)与交换器通过 路由键 绑定(zc)
String routeKey ="zc";
channel.queueBind(queueName,DirectProducer.EXCHANGE_NAME,routeKey);
System.out.println("waiting for message ......");
//申明一个消费者
final Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String s, Envelope envelope, AMQP.BasicProperties basicProperties, byte[] bytes) throws IOException {
String message = new String(bytes,"UTF-8");
System.out.println("Received["+envelope.getRoutingKey()+"]"+message);
}
};
//消息者正是开始在指定队列上消费。(queue-king)
//TODO 这里第二个参数是自动确认参数,如果是true则是自动确认
channel.basicConsume(queueName,true,consumer);
}
}
二、多重绑定
在上面展示中,消费者指定了,队列和交换器通过一个路由键进行绑定
//声明队列(单独绑定,下面还有多重绑定)
String queueName="zcQueuq";
channel.queueDeclare(queueName,false,false,false,null);
也可以绑定多个路由键,这样多个路由键也可以指定同一个队列了
//声明一个随机队列
String queueName = channel.queueDeclare().getQueue();
//TODO
/*队列绑定到交换器上时,是允许绑定多个路由键的,也就是多重绑定*/
String[] routekeys={"zc1","zc2","zc3"};
for(String routekey:routekeys){
channel.queueBind(queueName,DirectProducer.EXCHANGE_NAME,
routekey);
}
三、一个队列多个消费者
通过线程的方式指定多个消费者,去消费同一个队列上的消息
public class MultiConsumerOneQueue {
private static class ConsumerWorker implements Runnable{
final Connection connection;
final String queueName;
public ConsumerWorker(Connection connection,String queueName) {
this.connection = connection;
this.queueName = queueName;
}
public void run() {
try {
/*创建一个信道,意味着每个线程单独一个信道*/
final Channel channel = connection.createChannel();
//信道设置交换器类型(direct)
channel.exchangeDeclare(DirectProducer.EXCHANGE_NAME,BuiltinExchangeType.DIRECT);
/*声明一个队列,rabbitmq,如果队列已存在,不会重复创建*/
channel.queueDeclare(queueName, false,false, false,null);
//消费者名字,打印输出用
final String consumerName = Thread.currentThread().getName();
/*队列绑定到交换器上时,是允许绑定多个路由键的,也就是多重绑定*/
String[] routekeys={"zc1","zc2","zc3"};
for(String routekey:routekeys){
channel.queueBind(queueName,DirectProducer.EXCHANGE_NAME,
routekey);
}
System.out.println(" ["+consumerName+"] Waiting for messages:");
// 创建队列消费者
final Consumer consumerA = 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 + "'");
}
};
channel.basicConsume(queueName, true, consumerA);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] argv) throws IOException,
InterruptedException, TimeoutException {
//连接工厂
ConnectionFactory factory = new ConnectionFactory();
//连接rabbitMq的地址
factory.setHost("127.0.0.1");
// 打开连接和创建频道,与发送端一样
Connection connection = factory.newConnection();
//TODO
//3个线程,线程之间共享队列,一个队列多个消费者
String queueName = "focusAll";
for(int i=0;i<3;i++){
/*将队列名作为参数,传递给每个线程*/
Thread worker =new Thread(new ConsumerWorker(connection,queueName));
worker.start();
}
}
}