案例
由于该类型的交换机会导致消息的丢失,所以建议先启动消息的消费者。
接受方:
消费者1:
public class Reseive {
public static void main(String[] args) {
ConnectionFactory factory=new ConnectionFactory();
factory.setHost("192.168.79.140");
factory.setPort(5672);
factory.setUsername("admin");
factory.setPassword("123456");
/**通道资源和连接资源不需要关闭
* 关闭小概率会抛出异常
* */
Connection connection=null;
Channel channel=null;
try {
connection=factory.newConnection();
channel=connection.createChannel();
/**创建队列
* */
channel.queueDeclare("topicQueue01",true,
false,false,null);
/**创建交换机
* */
channel.exchangeDeclare("topicExchange",
"topic",true);
/**由于Fanout类型的交换机不需要绑定RoutingKey所以这里为空字符串
* */
channel.queueBind("topicQueue01",
"topicExchange","aa");
/**获取消息
* */
channel.basicConsume("topicQueue01",
true,"",
new DefaultConsumer(channel){
/**获取队列中消息函数
* */
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body) throws IOException {
String message =new String(body);
System.out.println("消息消费者aa:"+message);
}
});
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
消费者2:xiaof
public class Reseive02 {
public static void main(String[] args) {
ConnectionFactory factory=new ConnectionFactory();
factory.setHost("192.168.79.140");
factory.setPort(5672);
factory.setUsername("admin");
factory.setPassword("123456");
Connection connection=null;
Channel channel=null;
try {
connection=factory.newConnection();
channel=connection.createChannel();
/**创建队列
* */
channel.queueDeclare("topicQueue02",true,
false,false,null);
/**创建交换机
* */
channel.exchangeDeclare("topicExchange",
"topic",true);
/**由于Fanout类型的交换机不需要绑定RoutingKey所以这里为空字符串
* */
channel.queueBind("topicQueue02",
"topicExchange","aa.*");
/**获取消息
* */
channel.basicConsume("topicQueue02",
true,"",
new DefaultConsumer(channel){
/**获取队列中消息函数
* */
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body) throws IOException {
String message =new String(body);
System.out.println("消息消费者aa.*:"+message);
}
});
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
消费者3:
public class Reseive03 {
public static void main(String[] args) {
ConnectionFactory factory=new ConnectionFactory();
factory.setHost("192.168.79.140");
factory.setPort(5672);
factory.setUsername("admin");
factory.setPassword("123456");
Connection connection=null;
Channel channel=null;
try {
connection=factory.newConnection();
channel=connection.createChannel();
/**创建队列
* */
channel.queueDeclare("topicQueue03",true,
false,false,null);
/**创建交换机
* */
channel.exchangeDeclare("topicExchange",
"topic",true);
/**由于Fanout类型的交换机不需要绑定RoutingKey所以这里为空字符串
* */
channel.queueBind("topicQueue03",
"topicExchange","aa.#");
/**获取消息
* */
channel.basicConsume("topicQueue03",
true,"",
new DefaultConsumer(channel){
/**获取队列中消息函数
* */
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body) throws IOException {
String message =new String(body);
System.out.println("消息消费者aa.#:"+message);
}
});
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
执行结果:
发送方:
public class Send {
public static void main(String[] args) {
ConnectionFactory factory=new ConnectionFactory();
factory.setHost("192.168.79.140");
factory.setPort(5672);
factory.setUsername("admin");
factory.setPassword("123456");
Connection connection=null;
Channel channel=null;
try {
connection=factory.newConnection();
channel=connection.createChannel();
channel.exchangeDeclare("topicExchange","topic",true);
/**发送消息
* */
String message="topic交换机测试消息";
/**发送消息到队列
* */
channel.basicPublish("topicExchange",
"aa",null,
message.getBytes("utf-8"));
System.out.println("消息发送成功");
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}finally{
if(channel!=null){
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
RoutingKey为aa的执行结果
可以看到只有RountingKey为aa和aa.#的队列接收到了消息,这与交换机的原理案例一致。
Topic交换机和Fanout交换机使用场景对比
Fanout
Fanout交换机适用于一个功能不同的进程来获取数据,例如手机app中的消息推送,一个app可能会还有很多个用户来进行安装,然后他们都会启动一个随机的队列来接收自己的消息
Topic
Topic交换机更适合不同的功能来接收同一个消息,例如商城下单成功后生成的一些物流消息可以使用该类型的交换机。
Topic可以使用随机的队列名称,也可以使用明确的队列名称。但如果应用在和订单有关的功能中,建议是有个明确的队列名称并且持久化的