一、简介

RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。

消息队列都涉及的生产者消费者模型,不做详解,本文只作为快速使用的参考文档。

消息队列主要有点对点和发布订阅模式。

其主要用途是异步、削峰,充当一个缓存的作用。只有可以异步处理时才可以使用消息队列。

官方参考文档地址:

https://www.rabbitmq.com/getstarted.html

需要添加jar包:

amqp-client-3.5.6.jar hamcrest-core-1.3.jar

本文jdk版本1.8。

二、直接使用队列

1、简单队列

特点是生产者消费者一一对应。

生产者一般效率很高,生产者很低,所以一一对应是不对的。所以这个一般不使用。

其结构如图所示:

先创建一个工具类:

  1. package com.bunny.rabbit;
  2. /**
  3. *
  4. * @author bunny~~我是兔子我会喵,我叫喵星兔。
  5. * 连接工具类
  6. */
  7.  
  8. import com.rabbitmq.client.Connection;
  9. import com.rabbitmq.client.ConnectionFactory;
  10.  
  11. public class LianjieGongjulei {
  12. public static final String SIMPLE_QUEUE_NAME = "simplequeue";
  13. public static final String WORK_QUEUE_NAME = "workqueue";
  14. public static final String PUBSUB_EXCHANGE_NAME = "pubsubexchange";
  15. public static final String ROUTING_EXCHANGE_NAME = "routingexchange";
  16. public static final String TOPIC_EXCHANGE_NAME = "topicexchange";
  17. public static final String PUBSUB_QUEUE_NAME1 = "pubsubqueue1";
  18. public static final String PUBSUB_QUEUE_NAME2 = "pubsubqueue2";
  19. public static final String ROUTING_QUEUE_NAME1 = "routingqueue1";
  20. public static final String ROUTING_QUEUE_NAME2 = "routingqueue2";
  21. public static final String TOPIC_QUEUE_NAME1 = "topicqueue1";
  22. public static final String TOPIC_QUEUE_NAME2 = "topicqueue2";
  23.  
  24. public static Connection getConnection() {
  25. try {
  26. ConnectionFactory cf = new ConnectionFactory();
  27. cf.setHost("127.0.0.1");
  28. cf.setPort();
  29. cf.setVirtualHost("/mybunny");
  30. cf.setUsername("bunny");
  31. cf.setPassword("bunny");
  32. return cf.newConnection();
  33. } catch (Exception e) {
  34. e.printStackTrace();
  35. }
  36. return null;
  37. }
  38.  
  39. }

生产者:

  1. package com.bunny.rabbit.simple;
  2.  
  3. import java.io.IOException;
  4.  
  5. import com.bunny.rabbit.LianjieGongjulei;
  6. import com.rabbitmq.client.Channel;
  7. import com.rabbitmq.client.Connection;
  8.  
  9. /**
  10. *
  11. * @author bunny~~我是兔子我会喵,我叫喵星兔。
  12. * 简单队列生产者
  13. */
  14. public class Shengchanzhe {
  15. public static void main(String[] args) throws Exception {
  16. Connection c = LianjieGongjulei.getConnection();
  17. Channel ch = c.createChannel();
  18. //如果已经存在,可以不声明,声明的话也没错。所以不管是否存在都可以声明。
  19. ch.queueDeclare(LianjieGongjulei.SIMPLE_QUEUE_NAME, false, false, false, null);
  20.  
  21. String mes = "Hello Kitty!";
  22. ch.basicPublish("", LianjieGongjulei.SIMPLE_QUEUE_NAME, null, mes.getBytes());
  23. System.out.println(" bunny Sent '" + mes + "'");
  24.  
  25. ch.close();
  26. c.close();
  27.  
  28. }
  29. }

消费者:

  1. package com.bunny.rabbit.simple;
  2.  
  3. import java.io.IOException;
  4.  
  5. import com.bunny.rabbit.LianjieGongjulei;
  6. import com.rabbitmq.client.Channel;
  7. import com.rabbitmq.client.Connection;
  8. import com.rabbitmq.client.QueueingConsumer;
  9.  
  10. /**
  11. *
  12. * @author bunny~~我是兔子我会喵,我叫喵星兔。
  13. * 简单队列消费者
  14. */
  15. public class Xiaofeizhe {
  16. public static void main(String[] args) throws Exception {
  17. Connection c = LianjieGongjulei.getConnection();
  18. Channel ch = c.createChannel();
  19. //如果已经存在,可以不声明,声明的话也没错。所以不管是否存在都可以声明。
  20. ch.queueDeclare(LianjieGongjulei.SIMPLE_QUEUE_NAME, false, false, false, null);
  21.  
  22. // 定义消费者
  23. QueueingConsumer consumer = new QueueingConsumer(ch);
  24. ch.basicConsume(LianjieGongjulei.SIMPLE_QUEUE_NAME, true, consumer);
  25.  
  26. // 获取消息
  27. while (true) {
  28. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
  29. String message = new String(delivery.getBody());
  30. System.out.println(" bunny Received '" + message + "'");
  31. }
  32.  
  33. }
  34. }

2work队列

手工确认则会按照消费端的能力进行分发(公平分发),否则是按照生产者的规则分发(轮询)。

一个消费者队列可以有多个消费者实例,只有其中一个消费者实例会消费。

如图所示:

生产者:

  1. package com.bunny.rabbit.work;
  2.  
  3. import com.bunny.rabbit.LianjieGongjulei;
  4. import com.rabbitmq.client.Channel;
  5. import com.rabbitmq.client.Connection;
  6.  
  7. /**
  8. *
  9. * @author bunny~~我是兔子我会喵,我叫喵星兔。
  10. *
  11. */
  12. public class Shengchanzhe {
  13. public static void main(String[] args) throws Exception {
  14. Connection c = LianjieGongjulei.getConnection();
  15. Channel ch = c.createChannel();
  16. ch.queueDeclare(LianjieGongjulei.WORK_QUEUE_NAME, false, false, false, null);
  17. for (int i = ; i < ; i++, Thread.sleep()) {
  18. String mes = "kitty" + i;
  19. ch.basicPublish("", LianjieGongjulei.WORK_QUEUE_NAME, null, mes.getBytes());
  20. System.out.println(" bunny Sent '" + mes + "'");
  21. }
  22. ch.close();
  23. c.close();
  24. }
  25. }

消费者1:

  1. package com.bunny.rabbit.work;
  2.  
  3. import com.bunny.rabbit.LianjieGongjulei;
  4. import com.rabbitmq.client.Channel;
  5. import com.rabbitmq.client.Connection;
  6. import com.rabbitmq.client.DefaultConsumer;
  7. import com.rabbitmq.client.QueueingConsumer;
  8.  
  9. /**
  10. *
  11. * @author bunny~~我是兔子我会喵,我叫喵星兔。
  12. *
  13. */
  14. public class Xiaofeizhe1 {
  15. public static void main(String[] args) throws Exception {
  16. Connection c = LianjieGongjulei.getConnection();
  17. Channel ch = c.createChannel();
  18. ch.queueDeclare(LianjieGongjulei.WORK_QUEUE_NAME, false, false, false, null);
  19.  
  20. QueueingConsumer consumer = new QueueingConsumer(ch);
  21. // 监听队列,false表示手动返回完成状态,true表示自动
  22. ch.basicConsume(LianjieGongjulei.WORK_QUEUE_NAME, true, consumer);
  23.  
  24. while (true) {
  25. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
  26. String message = new String(delivery.getBody());
  27. System.out.println(" kitty Received '" + message + "'");
  28. Thread.sleep();
  29.  
  30. }
  31.  
  32. }
  33. }

消费者2:

  1. package com.bunny.rabbit.work;
  2.  
  3. import java.io.IOException;
  4.  
  5. import com.bunny.rabbit.LianjieGongjulei;
  6. import com.rabbitmq.client.Channel;
  7. import com.rabbitmq.client.Connection;
  8. import com.rabbitmq.client.QueueingConsumer;
  9.  
  10. /**
  11. *
  12. * @author bunny~~我是兔子我会喵,我叫喵星兔。
  13. *
  14. */
  15. public class Xiaofeizhe2 {
  16. public static void main(String[] args) throws Exception {
  17. Connection c = LianjieGongjulei.getConnection();
  18. Channel ch = c.createChannel();
  19. ch.queueDeclare(LianjieGongjulei.WORK_QUEUE_NAME, false, false, false, null);
  20.  
  21. //手工确认用
  22. ch.basicQos();
  23.  
  24. // 定义队列的消费者
  25. QueueingConsumer consumer = new QueueingConsumer(ch);
  26. // 监听队列,false表示手动返回完成状态,true表示自动
  27. ch.basicConsume(LianjieGongjulei.WORK_QUEUE_NAME, false, consumer);
  28.  
  29. while (true) {
  30. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
  31. String message = new String(delivery.getBody());
  32. System.out.println(" bunny Received '" + message + "'");
  33.  
  34. Thread.sleep();
  35. // 表示手动返回完成状态,如果没有下面的一行,将只能获取到上面ch.basicQos(1)里面写的数量
  36. ch.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
  37. }
  38.  
  39. }
  40. }

三、通过交换机

1、发布订阅

1个生产者,多个消费者。

每一个消费者都有自己的一个队列。

生产者没有将消息直接发送到队列,而是发送到了交换机。

每个队列都要绑定到交换机。

生产者发送的消息,经过交换机,到达队列,实现一个消息被多个消费者获取的目的。

消息发送到没有队列绑定的交换机时,消息将丢失,因为,交换机没有存储消息的能力,消息只能存在在队列中。

如图:

生产者:

  1. package com.bunny.rabbit.pubsub;
  2.  
  3. import com.bunny.rabbit.LianjieGongjulei;
  4. import com.rabbitmq.client.Channel;
  5. import com.rabbitmq.client.Connection;
  6. /**
  7. *
  8. * @author bunny~~我是兔子我会喵,我叫喵星兔。
  9. *
  10. */
  11. public class Fabuzhe {
  12.  
  13. public static void main(String[] args) throws Exception {
  14. Connection c = LianjieGongjulei.getConnection();
  15. Channel ch = c.createChannel();
  16. //交换器的类型,常见的有direct,fanout,topic等,其中“fanout”是发布订阅
  17. ch.exchangeDeclare(LianjieGongjulei.PUBSUB_EXCHANGE_NAME, "fanout");
  18. String mes = "发布订阅信息";
  19. ch.basicPublish(LianjieGongjulei.PUBSUB_EXCHANGE_NAME, "", null, mes.getBytes());
  20. System.out.println(" pubsub Sent '" + mes + "'");
  21. ch.close();
  22. c.close();
  23.  
  24. }
  25.  
  26. }

消费者1:

  1. package com.bunny.rabbit.pubsub;
  2.  
  3. import com.bunny.rabbit.LianjieGongjulei;
  4. import com.rabbitmq.client.Channel;
  5. import com.rabbitmq.client.Connection;
  6. import com.rabbitmq.client.QueueingConsumer;
  7. /**
  8. *
  9. * @author bunny~~我是兔子我会喵,我叫喵星兔。
  10. *
  11. */
  12. public class Dingyuezhe1 {
  13. public static void main(String[] args) throws Exception {
  14. Connection c = LianjieGongjulei.getConnection();
  15. Channel ch = c.createChannel();
  16. ch.queueDeclare(LianjieGongjulei.PUBSUB_QUEUE_NAME1, false, false, false, null);
  17.  
  18. // 绑定队列到交换机
  19. ch.queueBind(LianjieGongjulei.PUBSUB_QUEUE_NAME1, LianjieGongjulei.PUBSUB_EXCHANGE_NAME, "");
  20.  
  21. // 监听队列,手动返回完成
  22. ch.basicQos();
  23. QueueingConsumer consumer = new QueueingConsumer(ch);
  24. // 监听队列,手动返回完成
  25. ch.basicConsume(LianjieGongjulei.PUBSUB_QUEUE_NAME1, false, consumer);
  26.  
  27. while (true) {
  28. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
  29. String mes = new String(delivery.getBody());
  30. System.out.println(" 订阅者1 Received '" + mes + "'");
  31. Thread.sleep();
  32. // 监听队列,手动返回完成
  33. ch.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
  34. }
  35.  
  36. }
  37. }

消费者2:

  1. package com.bunny.rabbit.pubsub;
  2.  
  3. import java.io.IOException;
  4.  
  5. import com.bunny.rabbit.LianjieGongjulei;
  6. import com.rabbitmq.client.Channel;
  7. import com.rabbitmq.client.Connection;
  8. import com.rabbitmq.client.QueueingConsumer;
  9. /**
  10. *
  11. * @author bunny~~我是兔子我会喵,我叫喵星兔。
  12. *
  13. */
  14. public class Dingyuezhe2 {
  15. public static void main(String[] args) throws Exception {
  16. Connection c = LianjieGongjulei.getConnection();
  17. Channel ch = c.createChannel();
  18. ch.queueDeclare(LianjieGongjulei.PUBSUB_QUEUE_NAME2, false, false, false, null);
  19.  
  20. // 绑定队列到交换机
  21. ch.queueBind(LianjieGongjulei.PUBSUB_QUEUE_NAME2, LianjieGongjulei.PUBSUB_EXCHANGE_NAME, "");
  22.  
  23. // 监听队列,手动返回完成
  24. ch.basicQos();
  25. QueueingConsumer consumer = new QueueingConsumer(ch);
  26. // 监听队列,手动返回完成
  27. ch.basicConsume(LianjieGongjulei.PUBSUB_QUEUE_NAME2, false, consumer);
  28.  
  29. while (true) {
  30. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
  31. String mes = new String(delivery.getBody());
  32. System.out.println(" 订阅者2 Received '" + mes + "'");
  33. Thread.sleep();
  34. // 监听队列,手动返回完成
  35. ch.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
  36. }
  37.  
  38. }
  39. }

2、路由模式

在前面基础上,改变交换机类型,添加key信息。

如图:

生产者:

  1. package com.bunny.rabbit.routing;
  2.  
  3. import com.bunny.rabbit.LianjieGongjulei;
  4. import com.rabbitmq.client.Channel;
  5. import com.rabbitmq.client.Connection;
  6. /**
  7. *
  8. * @author bunny~~我是兔子我会喵,我叫喵星兔。
  9. *
  10. */
  11. public class Fabuzhe {
  12.  
  13. public static void main(String[] args) throws Exception {
  14. Connection c = LianjieGongjulei.getConnection();
  15. Channel ch = c.createChannel();
  16. //交换器的类型,常见的有direct,fanout,topic等,其中“direct”是路由
  17. ch.exchangeDeclare(LianjieGongjulei.ROUTING_EXCHANGE_NAME, "direct");
  18. String mes1 = "路由直连信息1";
  19. String mes2 = "路由直连信息2";
  20. //第二个参数是消息key用于路由用
  21. ch.basicPublish(LianjieGongjulei.ROUTING_EXCHANGE_NAME, "meskey1", null, mes1.getBytes());
  22. ch.basicPublish(LianjieGongjulei.ROUTING_EXCHANGE_NAME, "meskey2", null, mes2.getBytes());
  23. System.out.println(" pubsub Sent '" + mes1 + "'");
  24. System.out.println(" pubsub Sent '" + mes2 + "'");
  25. ch.close();
  26. c.close();
  27.  
  28. }
  29.  
  30. }

消费者1:

  1. package com.bunny.rabbit.routing;
  2.  
  3. import com.bunny.rabbit.LianjieGongjulei;
  4. import com.rabbitmq.client.Channel;
  5. import com.rabbitmq.client.Connection;
  6. import com.rabbitmq.client.QueueingConsumer;
  7. /**
  8. *
  9. * @author bunny~~我是兔子我会喵,我叫喵星兔。
  10. *
  11. */
  12. public class Dingyuezhe1 {
  13. public static void main(String[] args) throws Exception {
  14. Connection c = LianjieGongjulei.getConnection();
  15. Channel ch = c.createChannel();
  16. ch.queueDeclare(LianjieGongjulei.ROUTING_QUEUE_NAME1, false, false, false, null);
  17.  
  18. // 绑定队列到交换机,第三个参数是key
  19. ch.queueBind(LianjieGongjulei.ROUTING_QUEUE_NAME1, LianjieGongjulei.ROUTING_EXCHANGE_NAME, "meskey1");
  20. ch.queueBind(LianjieGongjulei.ROUTING_QUEUE_NAME1, LianjieGongjulei.ROUTING_EXCHANGE_NAME, "meskey2");
  21.  
  22. // 监听队列,手动返回完成
  23. ch.basicQos();
  24. QueueingConsumer consumer = new QueueingConsumer(ch);
  25. // 监听队列,手动返回完成
  26. ch.basicConsume(LianjieGongjulei.ROUTING_QUEUE_NAME1, false, consumer);
  27.  
  28. while (true) {
  29. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
  30. String mes = new String(delivery.getBody());
  31. System.out.println(" 订阅者1 Received '" + mes + "'");
  32. Thread.sleep();
  33. // 监听队列,手动返回完成
  34. ch.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
  35. }
  36.  
  37. }
  38. }

消费者2:

  1. package com.bunny.rabbit.routing;
  2.  
  3. import java.io.IOException;
  4.  
  5. import com.bunny.rabbit.LianjieGongjulei;
  6. import com.rabbitmq.client.Channel;
  7. import com.rabbitmq.client.Connection;
  8. import com.rabbitmq.client.QueueingConsumer;
  9. /**
  10. *
  11. * @author bunny~~我是兔子我会喵,我叫喵星兔。
  12. *
  13. */
  14. public class Dingyuezhe2 {
  15. public static void main(String[] args) throws Exception {
  16. Connection c = LianjieGongjulei.getConnection();
  17. Channel ch = c.createChannel();
  18. ch.queueDeclare(LianjieGongjulei.ROUTING_QUEUE_NAME2, false, false, false, null);
  19.  
  20. // 绑定队列到交换机
  21. ch.queueBind(LianjieGongjulei.ROUTING_QUEUE_NAME2, LianjieGongjulei.ROUTING_EXCHANGE_NAME, "meskey1");
  22.  
  23. // 监听队列,手动返回完成
  24. ch.basicQos();
  25. QueueingConsumer consumer = new QueueingConsumer(ch);
  26. // 监听队列,手动返回完成
  27. ch.basicConsume(LianjieGongjulei.ROUTING_QUEUE_NAME2, false, consumer);
  28.  
  29. while (true) {
  30. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
  31. String mes = new String(delivery.getBody());
  32. System.out.println(" 订阅者2 Received '" + mes + "'");
  33. Thread.sleep();
  34. // 监听队列,手动返回完成
  35. ch.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
  36. }
  37.  
  38. }
  39. }

3、主题模式

在路由基础上,模糊匹配。至于匹配规则,简单来说就是*代表一个单词,#代表多个单词。单词指的是字符串被“.”分割的部分。可以实际操作之后观察结果。

如图:

生产者:

  1. package com.bunny.rabbit.topic;
  2.  
  3. import com.bunny.rabbit.LianjieGongjulei;
  4. import com.rabbitmq.client.Channel;
  5. import com.rabbitmq.client.Connection;
  6. /**
  7. *
  8. * @author bunny~~我是兔子我会喵,我叫喵星兔。
  9. *
  10. */
  11. public class Fabuzhe {
  12.  
  13. public static void main(String[] args) throws Exception {
  14. Connection c = LianjieGongjulei.getConnection();
  15. Channel ch = c.createChannel();
  16. //交换器的类型,常见的有direct,fanout,topic等,其中“direct”是路由
  17. ch.exchangeDeclare(LianjieGongjulei.TOPIC_EXCHANGE_NAME, "topic");
  18. String mes1 = "主题信息1";
  19. String mes2 = "主题信息2";
  20. String mes3 = "主题信息3";
  21. String mes4 = "主题信息4";
  22. //第二个参数是消息key用于路由用
  23. ch.basicPublish(LianjieGongjulei.TOPIC_EXCHANGE_NAME, "mes.key.bunny", null, mes1.getBytes());
  24. ch.basicPublish(LianjieGongjulei.TOPIC_EXCHANGE_NAME, "bunny", null, mes2.getBytes());
  25. ch.basicPublish(LianjieGongjulei.TOPIC_EXCHANGE_NAME, "mes", null, mes3.getBytes());
  26. ch.basicPublish(LianjieGongjulei.TOPIC_EXCHANGE_NAME, "key.ee", null, mes4.getBytes());
  27. System.out.println(" topic Sent '" + mes1 + "'");
  28. System.out.println(" topic Sent '" + mes2 + "'");
  29. System.out.println(" topic Sent '" + mes3 + "'");
  30. System.out.println(" topic Sent '" + mes4 + "'");
  31. ch.close();
  32. c.close();
  33.  
  34. }
  35.  
  36. }

消费者1:

  1. package com.bunny.rabbit.topic;
  2.  
  3. import com.bunny.rabbit.LianjieGongjulei;
  4. import com.rabbitmq.client.Channel;
  5. import com.rabbitmq.client.Connection;
  6. import com.rabbitmq.client.QueueingConsumer;
  7. /**
  8. *
  9. * @author bunny~~我是兔子我会喵,我叫喵星兔。
  10. *
  11. */
  12. public class Dingyuezhe1 {
  13. public static void main(String[] args) throws Exception {
  14. Connection c = LianjieGongjulei.getConnection();
  15. Channel ch = c.createChannel();
  16. ch.queueDeclare(LianjieGongjulei.TOPIC_QUEUE_NAME1, false, false, false, null);
  17.  
  18. // 绑定队列到交换机,第三个参数是key
  19. ch.queueBind(LianjieGongjulei.TOPIC_QUEUE_NAME1, LianjieGongjulei.TOPIC_EXCHANGE_NAME, "*");
  20. ch.queueBind(LianjieGongjulei.TOPIC_QUEUE_NAME1, LianjieGongjulei.TOPIC_EXCHANGE_NAME, "mes.#");
  21.  
  22. // 监听队列,手动返回完成
  23. ch.basicQos();
  24. QueueingConsumer consumer = new QueueingConsumer(ch);
  25. // 监听队列,手动返回完成
  26. ch.basicConsume(LianjieGongjulei.TOPIC_QUEUE_NAME1, false, consumer);
  27.  
  28. while (true) {
  29. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
  30. String mes = new String(delivery.getBody());
  31. System.out.println(" 订阅者1 Received '" + mes + "'");
  32. Thread.sleep();
  33. // 监听队列,手动返回完成
  34. ch.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
  35. }
  36.  
  37. }
  38. }

消费者2:

  1. package com.bunny.rabbit.topic;
  2.  
  3. import java.io.IOException;
  4.  
  5. import com.bunny.rabbit.LianjieGongjulei;
  6. import com.rabbitmq.client.Channel;
  7. import com.rabbitmq.client.Connection;
  8. import com.rabbitmq.client.QueueingConsumer;
  9. /**
  10. *
  11. * @author bunny~~我是兔子我会喵,我叫喵星兔。
  12. *
  13. */
  14. public class Dingyuezhe2 {
  15. public static void main(String[] args) throws Exception {
  16. Connection c = LianjieGongjulei.getConnection();
  17. Channel ch = c.createChannel();
  18. ch.queueDeclare(LianjieGongjulei.TOPIC_QUEUE_NAME2, false, false, false, null);
  19.  
  20. // 绑定队列到交换机
  21. ch.queueBind(LianjieGongjulei.TOPIC_QUEUE_NAME2, LianjieGongjulei.TOPIC_EXCHANGE_NAME, "#");
  22.  
  23. // 监听队列,手动返回完成
  24. ch.basicQos();
  25. QueueingConsumer consumer = new QueueingConsumer(ch);
  26. // 监听队列,手动返回完成
  27. ch.basicConsume(LianjieGongjulei.TOPIC_QUEUE_NAME2, false, consumer);
  28.  
  29. while (true) {
  30. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
  31. String mes = new String(delivery.getBody());
  32. System.out.println(" 订阅者2 Received '" + mes + "'");
  33. Thread.sleep();
  34. // 监听队列,手动返回完成
  35. ch.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
  36. }
  37.  
  38. }
  39. }

四、总结

队列中数据只会被处理一次,交换机的数据处理次数和发送的队列有关。所以针对消息队列而言,交换机不是必须的。

每一个消息队列中的数据只会被消费一次。交换机把数据发到几个队列,那么数据就应该被消费几次,完全取决于队列数量。

上面的所有涉及路由的都只有一个消费者对应一个队列,其实都可以是多个消费者对应一个队列。

无论是生产者还是消费者,创建队列和交换机、队列和交换机的绑定,这些操作都是一次性的,如果第二次运行会发现已经处理了就不需要作。同样的,改变代码后并没有解除之前的设置、绑定等。不会因为有创建命令就重新创建。所以如果一个交换机开始设置成路由,那么代码修改为topic将会失败。

上面任何一步使用队列或者交换机,如果之前没创建,将会报错,这就意味着上面的代码有执行顺序。但是按照不报错的执行也不行,因为有些没效果,可以考虑先从头到尾执行一遍,无视错误。然后把运行中的终端关掉,这样环境就准备好了。然后在运行查看结果。

ps:项目地址  svn://47.105.188.20/kitty/2%E3%80%81code/rabbitclient  用户名密码:reader/reader

喵星之旅-狂奔的兔子-rabbitmq的java客户端使用入门的更多相关文章

  1. 喵星之旅-狂奔的兔子-基于docker的rabbitmq安装

    docker安装参考:喵星之旅-狂奔的兔子-docker安装和基本使用 一.查询镜像名称 由于我们要安装的是有web管理页面的,不能直接拉取,需要指定版本. 登录docker仓库查询:https:// ...

  2. 喵星之旅-狂奔的兔子-docker安装和基本使用

      一.前提条件 目前,CentOS 仅发行版本中的内核支持 Docker. 位.系统内核版本为 3.10 以上. 位系统.参考喵星之旅-狂奔的兔子-linux安装 二.CentOS 7下安装 Doc ...

  3. 喵星之旅-狂奔的兔子-myeclipse搭建ssm

    . 可以使用试用期限内的myeclipse,也可以找到有授权的机器进行操作.搭建好的项目框架可以直接移植到免费软件eclipse使用.或者直接购买myeclipse授权. 一.创建一个java web ...

  4. 喵星之旅-狂奔的兔子-centos7一键安装redmine

    一.安装环境 CentOS-7-x86_64-DVD-1908.iso 二.获取安装文件 从官网获取,在下载页面提供了多种安装,最下方是一键安装版本,里面有两种选择,一个是安装包,一个是虚拟机硬盘文件 ...

  5. 喵星之旅-狂奔的兔子-centos7安装MySQL 5.5

    安装环境:https://www.cnblogs.com/kittybunny/p/12296078.html 一.下载安装文件 下载地址 https://downloads.mysql.com/ar ...

  6. 喵星之旅-狂奔的兔子-linux安装

    一.前言 本文演示虚拟机安装,和真机区别可能在网卡驱动上有差异. 真机环境:CentOS Linux release 7.6.1810 (Core) 虚拟机(虽然centos系统自带虚拟机软件,但是习 ...

  7. 喵星之旅-狂奔的兔子-redis使用

    一.命令行使用 redis大概有200多命令,这里只是入门级别,列举了一些非常常见的内容,如果这些会了就可以开启redis进一步学习了. 1.登录数据库 我们需要知道ip地址.端口号.密码(如果有). ...

  8. 喵星之旅-狂奔的兔子-svn安装及使用

    一.服务端安装配置 1.安装svn 创建版本库并配置 以root用户登录,或者具有sudo权限的用户,这里选择root. yum install subversion 都选择y 2.创建版本库并配置 ...

  9. 喵星之旅-狂奔的兔子-redis安装

    一.前置条件 服务器版本CentOS-8-x86_64-1905-dvd1,在此版本上安装最新版redis.centos7以上版本都可以,不建议6以前的版本. 二.下载redis,并上传到服务器 登录 ...

随机推荐

  1. 【Unity|C#】基础篇(4)——函数参数类型(值参/ref/out/params)

    [学习资料] <C#图解教程>(第5章):https://www.cnblogs.com/moonache/p/7687551.html 电子书下载:https://pan.baidu.c ...

  2. Windows下解决github push failed (remote: Permission to userA/XXXX.git denied to userB.) 上传gitHub失败报错

    Windows环境下解决 github push failed (remote: Permission to userA/XXXX.git denied to userB.) · 初学GitHub的朋 ...

  3. Java开发新闻管理系统(前后端)+爬虫百度、新浪等新闻

                  ForFuture News  新闻管理系统                      项目演示地址:http://www.ganquanzhong.top [注]:文档下 ...

  4. Codeforces Round #613 (Div. 2) A-E简要题解

    contest链接:https://codeforces.com/contest/1285 A. Mezo Playing Zoma 签到 #include<iostream> #incl ...

  5. ubuntu查看系统负载和程序运行状况

    1,没有图形化界面 纯文字:top 美化的文字界面:htop 2,图形界面查看系统状态: gnome-system-monitor(或者在搜索界面中搜索system monitor) 3,jetson ...

  6. IntelliJ IDEA 2017.3尚硅谷-----版本控制(Version Control)

    不管是个人开发还是团队开发,版本控制都会被使用.而 IDEA 也很好的集成了 版本控制的相关结构. Git 的 msysGit 官网下载:https://git-scm.com/ Git 客户端 To ...

  7. # node中的url常用方法解析

    url字符串是一个结构化的字符串,由好几个有意义部分组成.我们在工作中不可避免的会用到其中的某个部分,最原始的通过字符串截取和正则匹配的方法难免用起来会不太方便和美观,所以在我们的nodejs中提供了 ...

  8. vue的$on,$emit

    使用 $on(eventName) 监听事件使用 $emit(eventName) 触发事件 Api 中的解释: vm.$emit( event, […args] ) 参数: {string} eve ...

  9. C++-CodeForces-1307A/1307B/1307C

    假装自己打比赛嘿嘿嘿 #include <bits/stdc++.h> using namespace std; ]; int main(){ for(cin>>t;t--;) ...

  10. 代码架构.md

    代码架构 待办 昨天待办 decription decription 我的流程逻辑(异常处理方式) 1568097677501.drawio.html 29.94 KB 异常的两种处理方式 异常的两种 ...