publish_subcribe订阅模式
解读:
- 一个生产者,多个消费者.
- 每一个消费者都有自己的队列.
- 生产者没有直接把消息发送到队列,而是发送到了交换机,转发器exchange.
- 每个队列都要绑定到交换机上.
- 生产者发送的消息,经过交换机,到达队列,就能实现一个消息被多个消费者消费.
注册—>邮件
注册—>短信
环境搭建
package com.mmr.rabbit.ps;
import com.mmr.rabbit.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
public class Send {
private static final String EXCHANGE_NAME="test_exchange_fanout";
public static void main(String[] args) throws Exception {
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel();
//声明交换机
channel.exchangeDeclare(EXCHANGE_NAME,"fanout");//分发
//发送消息
String msg="hello ps";
channel.basicPublish(EXCHANGE_NAME, "", null, msg.getBytes());
System.err.println("Send :"+msg);
channel.close();
connection.close();
}
}
//直接发送,消息会丢失,因为交换机没有存储的能力,在rabbitmq中只有队列有存储能力.因为这时候还没有队列绑定到这个交换机,所以数据丢失了.
package com.mmr.rabbit.ps;
import java.io.IOException;
import com.mmr.rabbit.util.ConnectionUtils;
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;
public class Recv1 {
private static final String QUEUE_NAME="test_queue_fanout_message";
private static final String EXCHANGE_NAME="test_exchange_fanout";
public static void main(String[] args) throws Exception {
Connection connection = ConnectionUtils.getConnection();
final Channel channel = connection.createChannel();
//队列声明
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
//绑定队列到交换机转发器
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");
//保证每次只分发一个
channel.basicQos(1);
//定义一个消费者
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.err.println("[1] Recv:" + message + "");
try{
Thread.sleep(2000);
}catch(Exception e){
e.printStackTrace();
}finally{
System.err.println("[1] done");
channel.basicAck(envelope.getDeliveryTag(), false);
}
}
};
boolean autoAck = false;//自动应答
channel.basicConsume(QUEUE_NAME,autoAck,consumer);
}
}
package com.mmr.rabbit.ps;
import java.io.IOException;
import com.mmr.rabbit.util.ConnectionUtils;
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;
public class Recv2 {
private static final String QUEUE_NAME="test_queue_fanout_email";
private static final String EXCHANGE_NAME="test_exchange_fanout";
public static void main(String[] args) throws Exception {
Connection connection = ConnectionUtils.getConnection();
final Channel channel = connection.createChannel();
//队列声明
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
//绑定队列到交换机转发器
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");
//保证每次只分发一个
channel.basicQos(1);
//定义一个消费者
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.err.println("[2] Recv:" + message + "");
try{
Thread.sleep(2000);
}catch(Exception e){
e.printStackTrace();
}finally{
System.err.println("[2] done");
channel.basicAck(envelope.getDeliveryTag(), false);
}
}
};
boolean autoAck = false;//自动应答
channel.basicConsume(QUEUE_NAME,autoAck,consumer);
}
}