rabbitMQ入门2

3、Pub/Sub 订阅模式
交换机需要与队列进行绑定,绑定之后。一个消息同时被多个消费者收到。消费者收到的都是一样的消息;
代码实现;队列能自动创建,交换机不能,必须提前创建,否则会报错;交换机可以用程序来创建,后面有;
交换机类型:
Fanout 广播:讲消息交给所有绑定的交换机队列;我们目前要使用这种交换机;
发布者代码
第一个参数交换机名字 其他参数和之前的一样
channel.basicPublish(“jiaohuanjiName”,"" , null , input.getBytes());
消费者代码
声明队列信息
channel.queueDeclare(“duilieName” false, false, false, null);
queueBind用于将队列与交换机绑定
参数1:队列名 参数2:交互机名 参数三:路由key(暂时用不到)
channel.queueBind(“duilieName”, ”jianhuanjiName“, “”);
//只多了这一行,其他跟之前的简单模式一样
4、Routing 路由模式
队列与交换机的绑定不能是任意绑定而是要指定一个RoutingKey(路由key)
消息的发送方在向Exchange发送消息时,也必须指定消息的Routingkey,指定的消息交给指定的key的消费者
交换机选择direct交换机;

发布者代码实现:
Map area = new LinkedHashMap<String, String>();
area.put(“key1”, “value1”);
area.put(“key2”, “value2”);
area.put(“key3”, “value3”);
area.put(“key4”, “value4”);
area.put(“key5”, “value5”);
area.put(“key6”, “value6”);
area.put(“key7”, “value7”);
area.put(“key8”, “value8”);
Connection connection = RabbitUtils.getConnection();//获取连接由自己的代码实现
Channel channel = connection.createChannel();
Iterator<Map.Entry<String, String>> itr = area.entrySet().iterator();
while (itr.hasNext()) {
Map.Entry<String, String> me = itr.next();
//第一个参数交换机名字 第二个参数作为 消息的routing key
channel.basicPublish(”jianhuanjiName“,me.getKey() , null , me.getValue().getBytes());
}
消费者代码实现
//获取TCP长连接
Connection connection = RabbitUtils.getConnection();
//获取虚拟连接
final Channel channel = connection.createChannel();
//声明队列信息
channel.queueDeclare(“duilieName”, false, false, false, null);

//指定队列与交换机以及routing key之间的关系
channel.queueBind(“duilieName”, “jiaohuanjiName”, “key1”);
channel.queueBind(“duilieName”, “jiaohuanjiName”, “key2”);
channel.queueBind(“duilieName”, “jiaohuanjiName”, “key3”);
channel.queueBind(“duilieName”, “jiaohuanjiName”, “key4”);

channel.basicQos(1);
channel.basicConsume(“duilieName” , false , new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(“第一个消费者:” + new String(body));
channel.basicAck(envelope.getDeliveryTag() , false);
}
});
可以有多个消费者
//获取TCP长连接
Connection connection = RabbitUtils.getConnection();
//获取虚拟连接
final Channel channel = connection.createChannel();
//声明队列信息
channel.queueDeclare(“duilieName2”, false, false, false, null);

//指定队列与交换机以及routing key之间的关系
channel.queueBind(“duilieName2”, “jiaohuanjiName”, “key6”);
channel.queueBind(“duilieName2”, “jiaohuanjiName”, “key5”);
channel.basicQos(1);
channel.basicConsume(“duilieName2” , false , new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(“第二个消费者:” + new String(body));
channel.basicAck(envelope.getDeliveryTag() , false);
}
});
5、通配符模式 topic
要比上面那种路由模式灵活一些,根据一一些通配符去匹配恰当key
通配符规则:
#:匹配一个或者多个词
:匹配一个词
例如:aaa.# 能匹配 aaa.bbb.vvv.dddd
aaa.
只能匹配 aaa.bbb 或者aaa.ccc之类的
发布者代码实现:
首先在rabbitMQ创建topic
在这里插入图片描述
代码实现:
发布者的实现:
代码实现与上面的路由模式一模一样,指定不同的key和value
Map area = new LinkedHashMap<String, String>();
area.put(“keyOne.aaa”, “aaaaa”);
area.put(“keyOne.bbb.ccc”, “bbbb”);
area.put(“keyOne.ddd”, “cccccc”);
area.put(“keyTwo.eeee.fffff”, “eeeeee”);
area.put(“keyTwo.dddd”, “gggg”);
area.put(“keyTwo.eeee.tttt”, “hhh”);
area.put(“keyTwo.eeee.aaaa”, “iiiii”);
消费者的代码也一模一样只是指定不同的key
//参数1:队列名 参数2:交互机名 参数三:路由key
channel.queueBind(“duilieName”, “weather_topic”, “keyOne.*”);
结果:
keyOne:cccccc
channel.queueBind(“duilieName”, “weather_topic”, “keyTwo.#”);
结果:
keyTwo:eeeeee
keyTwo:gggg
keyTwo:hhh
keyTwo:iiiii
工作模式总结
1、简单模式
一个生产者,一个消费者,不需要设置交换机
2、工作队列模式
一个生产者,多个消费者,不需要设置交换机
3、发布订阅模式
交换机设置:fanout
发送消息到绑定的多个队列上,都是一样的消息
4、路由模式
交换机设置:direct
指定key,发送到交换机上后,消息发送到指定的队列上
5、通配符模式(使用最多,最灵活)
交换机设置:topic
根据通配符规则,发送消息到符合规则的队列上
消息确认机制与发布者相关,与消费者无关
Confirm
ack代表数据已经被接收了
nack代表消息被拒绝接收
Return:
代表消息被正常接收后,但是没有对应的队列处理消息
在上面那个路由模式下生产者添加代码
//开启confirm监听模式
channel.confirmSelect();
channel.addConfirmListener(new ConfirmListener() {
public void handleAck(long l, boolean b) throws IOException {
//第二个参数代表接收的数据是否为批量接收,一般我们用不到。
System.out.println(“消息已被Broker接收,Tag:” + l );
}

        public void handleNack(long l, boolean b) throws IOException {
            System.out.println("消息已被Broker拒收,Tag:" + l);
        }
    });
    channel.addReturnListener(new ReturnCallback() {
        public void handle(Return r) {
            System.err.println("===========================");
            System.err.println("Return编码:" + r.getReplyCode() + "-Return描述:" + r.getReplyText());
            System.err.println("交换机:" + r.getExchange() + "-路由key:" + r.getRoutingKey() );
            System.err.println("Return主题:" + new String(r.getBody()));
            System.err.println("===========================");
        }
    });

并且取消关闭连接,因为我们需要监听返回的消息
注释掉
channel.close();
connection.close();
再修改
//第三个参数为:mandatory true代表如果消息无法正常投递则return回生产者,如果false,则直接将消息放弃。
多了一个参数
channel.basicPublish(“jiaohuanjiName”,me.getKey() ,true, null , me.getValue().getBytes());
返回的结果:
Return编码:312-Return描述:NO_ROUTE
交换机:weather_topic-路由key:keyOne
Return主题:aaaaa
Return编码:312-Return描述:NO_ROUTE
交换机:weather_topic-路由key:keyOne.bbb.ccc
Return主题:bbbb
消息已被Broker接收,Tag:1
消息已被Broker接收,Tag:2
消息已被Broker接收,Tag:5
消息已被Broker接收,Tag:7

没有被队列接收的就在return中返回回来,正常接收的就从监听器中返回回来

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值