RabbitMQ:交换机
可以指定交换机Type:
direct,fanout,headers,topic
交换机是不存储数据的,如果没有消费者接收数据,数据就会直接丢弃
群发模式:Fanout
群发一般用fanout
给fanout交换机指定一个名称:logs
channel.exchangeDeclare("logs", "fanout");
待补充。。。
路由模式:Direct
原理:
交换机类型用的是direct
路由键:消息上自带的一个关键词,由路由键决定消息发送到哪个队列
绑定键:队列和交换机绑定时指定的关键词
如果路由键和绑定键都不匹配的话,该消息直接被丢弃
注意事项:
在声明队列的时候,不需要声明队列名,而是需要声明一个交换机,设置类型为DIRECT
c.exchangeDeclare("direct_logs", BuiltinExchangeType.DIRECT);
消费者可以绑定多个关键词,需要分别指定
Demo:
Provider
Channel c = common.simpleConnection("");
c.exchangeDeclare("direct_logs", BuiltinExchangeType.DIRECT);
while(true) {
System.out.println("输入消息:");
String msg = new Scanner(System.in).nextLine();
System.out.println("输入路由键:");
String key = new Scanner(System.in).nextLine();
//第二个参数是路由键,用路由键做关键词匹配决定把消息发送到哪个队列
//原来第二个参数是队列名,但是现在用路由键模式,就直接用路由键匹配
c.basicPublish("direct_logs", key, null, msg.getBytes());
}
Consumer
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.64.140");
factory.setPort(5672);
factory.setUsername("admin");
factory.setPassword("admin");
Channel c = factory.newConnection().createChannel();
//定义交换机
c.exchangeDeclare("direct_logs", BuiltinExchangeType.DIRECT);
//定义随机队列,获取服务器队列名称
String queue = c.queueDeclare().getQueue();
System.out.println("输入绑定键,用空格隔开:"); ///aaa bbb ccc
String s = new Scanner(System.in).nextLine();
String[] a = s.split("\\s+");
for(String key : a) {
c.queueBind(queue, "direct_logs", key);
}
DeliverCallback deliverCallback = new DeliverCallback() {
@Override
public void handle(String consumerTag, Delivery message) throws IOException {
//取出消息数据,路由键
String str = new String(message.getBody());
String routingKey = message.getEnvelope().getRoutingKey();
System.out.println("收到的路由键:"+routingKey);
System.out.println("收到的消息:"+ str);
}
};
CancelCallback cancelCallback = new CancelCallback() {
@Override
public void handle(String consumerTag) throws IOException {
// TODO Auto-generated method stub
}
};
c.basicConsume(queue, true, deliverCallback, cancelCallback);
}
主题模式:Topic
实际上也是路由模式
*可以匹配一个关键词,#可以匹配多个关键词
绑定键指定为:
Q1:
*.orange.*
Q2:
*.*.rabbit
lazy.#
路由键如果指定为:lazy.orange.rabbit
那么和这三个绑定键都是匹配的,但是由于只有2个队列,所以消息每个队列中只会发一次
路由键如果指定为:aaa.orange.bbb
那么只会匹配到队列Q1
代码基本和路由模式相同
Provider:
public static void main(String[] args) throws Exception {
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140");
f.setUsername("admin");
f.setPassword("admin");
Channel c = f.newConnection().createChannel();
c.exchangeDeclare("topic_logs", BuiltinExchangeType.TOPIC);
while(true) {
System.out.println("输入消息:");
String msg = new Scanner(System.in).nextLine();
System.out.println("输入路由键:");
String key = new Scanner(System.in).nextLine();
c.basicPublish("topic_logs", key, null, msg.getBytes());
}
}
Consumer:
public static void main(String[] args) throws Exception {
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140");
f.setUsername("admin");
f.setPassword("admin");
Channel c = f.newConnection().createChannel();
c.exchangeDeclare("topic_logs", BuiltinExchangeType.TOPIC);
String queue = c.queueDeclare().getQueue();
System.out.println("输入绑定键,用空格隔开:");
String str = new Scanner(System.in).nextLine();
String[] a = str.split("\\s+");
for (String key : a) {
c.queueBind(queue, "topic_logs", key);
}
DeliverCallback deliverCallback = new DeliverCallback() {
@Override
public void handle(String consumerTag, Delivery message) throws IOException {
String routingKey = message.getEnvelope().getRoutingKey();
System.out.println("绑定键:"+routingKey);
String msg = new String(message.getBody());
System.out.println("消息内容:"+msg);
}
};
CancelCallback cancelCallback = new CancelCallback() {
@Override
public void handle(String consumerTag) throws IOException {
// TODO Auto-generated method stub
}
};
c.basicConsume(queue,true, deliverCallback, cancelCallback);
}