RabbitMQ的简单使用

大兔子大兔子 提交于 2019-12-06 04:46:00

RabbitMQ介绍

  MQMessageQueueRabbitMQerlangAMQPAdvancedMessageQueue广RabbitMQhttp://www.rabbitmq.com/

  1,任务异步处理

  2,应用程序解耦合

RabbitMQ的工作原理:

 

组成说明:

  BrokerExchangeQueue

  Exchange

  Queue

  ProducerMQ

  ConsumerMQ

快速入门(测试类,了解原理  没啥用

创建maven工程

1         <dependency>
2             <groupId>com.rabbitmq</groupId>
3             <artifactId>amqp-client</artifactId>
4             <version>4.0.3</version><!--此版本与spring boot 1.5.9版本匹配-->
5         </dependency>
6         <dependency>
7             <groupId>org.springframework.boot</groupId>
8             <artifactId>spring-boot-starter-logging</artifactId>
9         </dependency>

生产者

1,创建连接  2,创建通道  3,声明队列  4,发送消息

 1 public class Producer01 {
 2 
 3     //队列
 4     private static final String QUEUE = "helloworld";
 5 
 6     public static void main(String[] args) {
 7         //通过连接工厂创建新的连接和mq建立连接
 8         ConnectionFactory connectionFactory = new ConnectionFactory();
 9         connectionFactory.setHost("127.0.0.1");
10         connectionFactory.setPort(5672);//端口
11         connectionFactory.setUsername("guest");
12         connectionFactory.setPassword("guest");
13         //设置虚拟机,一个mq服务可以设置多个虚拟机,每个虚拟机就相当于一个独立的mq
14         connectionFactory.setVirtualHost("/");
15         Connection connection = null;
16         Channel channel = null;
17         try {
18             //建立新连接
19             connection = connectionFactory.newConnection();
20             //创建会话通道,生产者和mq服务所有通信都在channel通道中完成
21             channel = connection.createChannel();
22             //声明队列,如果队列在mq 中没有则要创建
23             //参数:String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
24             /**
25              * 参数明细
26              * 1、queue 队列名称
27              * 2、durable 是否持久化,如果持久化,mq重启后队列还在
28              * 3、exclusive 是否独占连接,队列只允许在该连接中访问,如果connection连接关闭队列则自动删除,如果将此参数设置true可用于临时队列的创建
29              * 4、autoDelete 自动删除,队列不再使用时是否自动删除此队列,如果将此参数和exclusive参数设置为true就可以实现临时队列(队列不用了就自动删除)
30              * 5、arguments 参数,可以设置一个队列的扩展参数,比如:可设置存活时间
31              */
32             channel.queueDeclare(QUEUE,true,false,false,null);
33             //发送消息
34             //参数:String exchange, String routingKey, BasicProperties props, byte[] body
35             /**
36              * 参数明细:
37              * 1、exchange,交换机,如果不指定将使用mq的默认交换机(设置为"")
38              * 2、routingKey,路由key,交换机根据路由key来将消息转发到指定的队列,如果使用默认交换机,routingKey设置为队列的名称
39              * 3、props,消息的属性
40              * 4、body,消息内容
41              */
42             //消息内容
43             String message = "hello world 黑马程序员";
44             channel.basicPublish("",QUEUE,null,message.getBytes());
45             System.out.println("send to mq "+message);
46         } catch (Exception e) {
47             e.printStackTrace();
48         } finally {
49             //关闭连接
50             //先关闭通道
51             try {
52                 channel.close();
53             } catch (IOException e) {
54                 e.printStackTrace();
55             } catch (TimeoutException e) {
56                 e.printStackTrace();
57             }
58             try {
59                 connection.close();
60             } catch (IOException e) {
61                 e.printStackTrace();
62             }
63         }
64     }
65 
66 }

消费者

接收端操作流程:1,创建连接  2,创建通道  3,声明队列  4,监听队列  5,接收消息

 1 public class Consumer01 {
 2 
 3     //队列
 4     private static final String QUEUE = "helloworld";
 5 
 6     public static void main(String[] args) throws IOException, TimeoutException {
 7         //通过连接工厂创建新的连接和mq建立连接
 8         ConnectionFactory connectionFactory = new ConnectionFactory();
 9         connectionFactory.setHost("127.0.0.1");
10         connectionFactory.setPort(5672);//端口
11         connectionFactory.setUsername("guest");//账户
12         connectionFactory.setPassword("guest");//密码
13         //设置虚拟机,一个mq服务可以设置多个虚拟机,每个虚拟机就相当于一个独立的mq
14         connectionFactory.setVirtualHost("/");
15 
16         //建立新连接
17         Connection connection = connectionFactory.newConnection();
18         //创建会话通道,生产者和mq服务所有通信都在channel通道中完成
19         Channel channel = connection.createChannel();
20 
21         //监听队列
22         //声明队列,如果队列在mq 中没有则要创建
23         //参数:String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
24         /**
25          * 参数明细
26          * 1、queue 队列名称
27          * 2、durable 是否持久化,如果持久化,mq重启后队列还在
28          * 3、exclusive 是否独占连接,队列只允许在该连接中访问,如果connection连接关闭队列则自动删除,如果将此参数设置true可用于临时队列的创建
29          * 4、autoDelete 自动删除,队列不再使用时是否自动删除此队列,如果将此参数和exclusive参数设置为true就可以实现临时队列(队列不用了就自动删除)
30          * 5、arguments 参数,可以设置一个队列的扩展参数,比如:可设置存活时间
31          */
32         channel.queueDeclare(QUEUE,true,false,false,null);
33 
34         //实现消费方法
35         DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
36 
37             /**
38              * 当接收到消息后此方法将被调用
39              * @param consumerTag  消费者标签,用来标识消费者的,在监听队列时设置channel.basicConsume
40              * @param envelope 信封,通过envelope
41              * @param properties 消息属性
42              * @param body 消息内容
43              * @throws IOException
44              */
45             @Override
46             public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
47                 //交换机
48                 String exchange = envelope.getExchange();
49                 //消息id,mq在channel中用来标识消息的id,可用于确认消息已接收
50                 long deliveryTag = envelope.getDeliveryTag();
51                 //消息内容
52                 String message= new String(body,"utf-8");
53                 System.out.println("receive message:"+message);
54             }
55         };
56 
57         //监听队列
58         //参数:String queue, boolean autoAck, Consumer callback
59         /**
60          * 参数明细:
61          * 1、queue 队列名称
62          * 2、autoAck 自动回复,当消费者接收到消息后要告诉mq消息已接收,如果将此参数设置为tru表示会自动回复mq,如果设置为false要通过编程实现回复
63          * 3、callback,消费方法,当消费者接收到消息要执行的方法
64          */
65         channel.basicConsume(QUEUE,true,defaultConsumer);
66 
67     }
68 }

工作模式(P:生产者,也就是要发送消息的程序  C:消费者:消息的接受者,会一直等待消息到来  queue:消息队列,图中红色部分  X:交换机)

Exchange(交换机)只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息会丢失!

1Work queues 工作队列

 

 work queues与入门程序相比,多了一个消费端,两个消费端共同消费同一个队列中的消息。

 

2Publish/Subscribe 发布订阅

 

 

 

 

3Routing 路由

 

 1routingkey。  2routingkey

(更好的对代码进行测试)

生产者

  声exchange_routing_inform  

  声routingkey  

  routingkey  

 

  1 public class Producer03_routing {
  2     //队列名称
  3     private static final String QUEUE_INFORM_EMAIL = "queue_inform_email";//队列
  4     private static final String QUEUE_INFORM_SMS = "queue_inform_sms";//队列
  5     private static final String EXCHANGE_ROUTING_INFORM="exchange_routing_inform";//交换机
  6     private static final String ROUTINGKEY_EMAIL="inform_email";//routingKey 路由key
  7     private static final String ROUTINGKEY_SMS="inform_sms";//routingKey 路由key
  8     public static void main(String[] args) {
  9         //通过连接工厂创建新的连接和mq建立连接
 10         ConnectionFactory connectionFactory = new ConnectionFactory();
 11         connectionFactory.setHost("127.0.0.1");
 12         connectionFactory.setPort(5672);//端口
 13         connectionFactory.setUsername("guest");
 14         connectionFactory.setPassword("guest");
 15         //设置虚拟机,一个mq服务可以设置多个虚拟机,每个虚拟机就相当于一个独立的mq
 16         connectionFactory.setVirtualHost("/");
 17 
 18         Connection connection = null;
 19         Channel channel = null;
 20         try {
 21             //建立新连接
 22             connection = connectionFactory.newConnection();
 23             //创建会话通道,生产者和mq服务所有通信都在channel通道中完成
 24             channel = connection.createChannel();
 25             //声明队列,如果队列在mq 中没有则要创建
 26             //参数:String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
 27             /**
 28              * 参数明细
 29              * 1、queue 队列名称
 30              * 2、durable 是否持久化,如果持久化,mq重启后队列还在
 31              * 3、exclusive 是否独占连接,队列只允许在该连接中访问,如果connection连接关闭队列则自动删除,如果将此参数设置true可用于临时队列的创建
 32              * 4、autoDelete 自动删除,队列不再使用时是否自动删除此队列,如果将此参数和exclusive参数设置为true就可以实现临时队列(队列不用了就自动删除)
 33              * 5、arguments 参数,可以设置一个队列的扩展参数,比如:可设置存活时间
 34              */
 35             channel.queueDeclare(QUEUE_INFORM_EMAIL,true,false,false,null);
 36             channel.queueDeclare(QUEUE_INFORM_SMS,true,false,false,null);
 37             //声明一个交换机
 38             //参数:String exchange, String type
 39             /**
 40              * 参数明细:
 41              * 1、交换机的名称
 42              * 2、交换机的类型
 43              * fanout:对应的rabbitmq的工作模式是 publish/subscribe
 44              * direct:对应的Routing    工作模式
 45              * topic:对应的Topics工作模式
 46              * headers: 对应的headers工作模式
 47              */
 48             channel.exchangeDeclare(EXCHANGE_ROUTING_INFORM, BuiltinExchangeType.DIRECT);
 49             //进行交换机和队列绑定
 50             //参数:String queue, String exchange, String routingKey
 51             /**
 52              * 参数明细:
 53              * 1、queue 队列名称
 54              * 2、exchange 交换机名称
 55              * 3、routingKey 路由key,作用是交换机根据路由key的值将消息转发到指定的队列中,在发布订阅模式中调协为空字符串
 56              */
 57             channel.queueBind(QUEUE_INFORM_EMAIL,EXCHANGE_ROUTING_INFORM,ROUTINGKEY_EMAIL);
 58             channel.queueBind(QUEUE_INFORM_EMAIL,EXCHANGE_ROUTING_INFORM,"inform");
 59             channel.queueBind(QUEUE_INFORM_SMS,EXCHANGE_ROUTING_INFORM,ROUTINGKEY_SMS);
 60             channel.queueBind(QUEUE_INFORM_SMS,EXCHANGE_ROUTING_INFORM,"inform");
 61             //发送消息
 62             //参数:String exchange, String routingKey, BasicProperties props, byte[] body
 63             /**
 64              * 参数明细:
 65              * 1、exchange,交换机,如果不指定将使用mq的默认交换机(设置为"")
 66              * 2、routingKey,路由key,交换机根据路由key来将消息转发到指定的队列,如果使用默认交换机,routingKey设置为队列的名称
 67              * 3、props,消息的属性
 68              * 4、body,消息内容
 69              */
 70            /* for(int i=0;i<5;i++){
 71                 //发送消息的时候指定routingKey
 72                 String message = "send email inform message to user";
 73                 channel.basicPublish(EXCHANGE_ROUTING_INFORM,ROUTINGKEY_EMAIL,null,message.getBytes());
 74                 System.out.println("send to mq "+message);
 75             }
 76             for(int i=0;i<5;i++){
 77                 //发送消息的时候指定routingKey
 78                 String message = "send sms inform message to user";
 79                 channel.basicPublish(EXCHANGE_ROUTING_INFORM,ROUTINGKEY_SMS,null,message.getBytes());
 80                 System.out.println("send to mq "+message);
 81             }*/
 82             for(int i=0;i<5;i++){
 83                 //发送消息的时候指定routingKey
 84                 String message = "send inform message to user";
 85                 channel.basicPublish(EXCHANGE_ROUTING_INFORM,"inform",null,message.getBytes());
 86                 System.out.println("send to mq "+message);
 87             }
 88 
 89         } catch (Exception e) {
 90             e.printStackTrace();
 91         } finally {
 92             //关闭连接
 93             //先关闭通道
 94             try {
 95                 channel.close();
 96             } catch (IOException e) {
 97                 e.printStackTrace();
 98             } catch (TimeoutException e) {
 99                 e.printStackTrace();
100             }
101             try {
102                 connection.close();
103             } catch (IOException e) {
104                 e.printStackTrace();
105             }
106         }
107 
108 
109     }
110 }

 

消费者1(

 1 public class Consumer03_routing_email {
 2     //队列名称
 3     private static final String QUEUE_INFORM_EMAIL = "queue_inform_email";//队列
 4     private static final String EXCHANGE_ROUTING_INFORM="exchange_routing_inform";//交换机
 5     private static final String ROUTINGKEY_EMAIL="inform_email";//routingKey 路由key 和生产者相匹配
 6 
 7     public static void main(String[] args) throws IOException, TimeoutException {
 8         //通过连接工厂创建新的连接和mq建立连接
 9         ConnectionFactory connectionFactory = new ConnectionFactory();
10         connectionFactory.setHost("127.0.0.1");
11         connectionFactory.setPort(5672);//端口
12         connectionFactory.setUsername("guest");
13         connectionFactory.setPassword("guest");
14         //设置虚拟机,一个mq服务可以设置多个虚拟机,每个虚拟机就相当于一个独立的mq
15         connectionFactory.setVirtualHost("/");
16 
17         //建立新连接
18         Connection connection = connectionFactory.newConnection();
19         //创建会话通道,生产者和mq服务所有通信都在channel通道中完成
20         Channel channel = connection.createChannel();
21 
22         /**
23          * 参数明细
24          * 1、queue 队列名称
25          * 2、durable 是否持久化,如果持久化,mq重启后队列还在
26          * 3、exclusive 是否独占连接,队列只允许在该连接中访问,如果connection连接关闭队列则自动删除,如果将此参数设置true可用于临时队列的创建
27          * 4、autoDelete 自动删除,队列不再使用时是否自动删除此队列,如果将此参数和exclusive参数设置为true就可以实现临时队列(队列不用了就自动删除)
28          * 5、arguments 参数,可以设置一个队列的扩展参数,比如:可设置存活时间
29          */
30         channel.queueDeclare(QUEUE_INFORM_EMAIL,true,false,false,null);
31         //声明一个交换机
32         //参数:String exchange, String type
33         /**
34          * 参数明细:
35          * 1、交换机的名称
36          * 2、交换机的类型
37          * fanout:对应的rabbitmq的工作模式是 publish/subscribe
38          * direct:对应的Routing    工作模式
39          * topic:对应的Topics工作模式
40          * headers: 对应的headers工作模式
41          */
42         channel.exchangeDeclare(EXCHANGE_ROUTING_INFORM, BuiltinExchangeType.DIRECT);
43         //进行交换机和队列绑定
44         //参数:String queue, String exchange, String routingKey
45         /**
46          * 参数明细:
47          * 1、queue 队列名称
48          * 2、exchange 交换机名称
49          * 3、routingKey 路由key,作用是交换机根据路由key的值将消息转发到指定的队列中,在发布订阅模式中调协为空字符串
50          */
51         channel.queueBind(QUEUE_INFORM_EMAIL, EXCHANGE_ROUTING_INFORM,ROUTINGKEY_EMAIL);
52 
53         //实现消费方法
54         DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
55 
56             /**
57              * 当接收到消息后此方法将被调用
58              * @param consumerTag  消费者标签,用来标识消费者的,在监听队列时设置channel.basicConsume
59              * @param envelope 信封,通过envelope
60              * @param properties 消息属性
61              * @param body 消息内容
62              * @throws IOException
63              */
64             @Override
65             public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
66                 //交换机
67                 String exchange = envelope.getExchange();
68                 //消息id,mq在channel中用来标识消息的id,可用于确认消息已接收
69                 long deliveryTag = envelope.getDeliveryTag();
70                 //消息内容
71                 String message= new String(body,"utf-8");
72                 System.out.println("receive message:"+message);
73             }
74         };
75 
76         //监听队列
77         //参数:String queue, boolean autoAck, Consumer callback
78         /**
79          * 参数明细:
80          * 1、queue 队列名称
81          * 2、autoAck 自动回复,当消费者接收到消息后要告诉mq消息已接收,如果将此参数设置为tru表示会自动回复mq,如果设置为false要通过编程实现回复
82          * 3、callback,消费方法,当消费者接收到消息要执行的方法
83          */
84         channel.basicConsume(QUEUE_INFORM_EMAIL,true,defaultConsumer);
85 
86     }
87 }

消费者2(短者())

 

 

 

 

4Topics 通配符

 

 Routingkey一般都是有一个或多个单词组成,多个单词之间以”.”分割,例如:item.insert

通配符规则:#:匹配一个或多个词  *:匹配不多不少恰好1个词

举例:item.#:能够匹配item.insert.abc或者item.insert

   item.*:只能匹配item.inser

 

 

 

5Header Header 转发器

6RPC 远程过程调用

 

 SpringRibbitMQ

maven依赖

 1         <dependency>
 2             <groupId>org.springframework.boot</groupId>
 3             <artifactId>spring-boot-starter-amqp</artifactId>
 4         </dependency>
 5         <dependency>
 6             <groupId>org.springframework.boot</groupId>
 7             <artifactId>spring-boot-starter-test</artifactId>
 8         </dependency>
 9         <dependency>
10             <groupId>org.springframework.boot</groupId>
11             <artifactId>spring-boot-starter-logging</artifactId>
12         </dependency>

配置

1application.yml

rabbitmq

 1 server:
 2   port: 44000
 3 spring:
 4   application:
 5     name: test-rabbitmq-producer
 6   rabbitmq:
 7     host: 127.0.0.1
 8     port: 5672
 9     username: guest
10     password: guest
11     virtualHost: /

2RabbitConfigExchangeQueue

Topic

 1 @Configuration
 2 public class RabbitmqConfig {
 3     public static final String QUEUE_INFORM_EMAIL = "queue_inform_email";//队列
 4     public static final String QUEUE_INFORM_SMS = "queue_inform_sms";
 5     public static final String EXCHANGE_TOPICS_INFORM="exchange_topics_inform";//交换机
 6     public static final String ROUTINGKEY_EMAIL="inform.#.email.#";//routingKey
 7     public static final String ROUTINGKEY_SMS="inform.#.sms.#";//routingKey
 8 
 9     //声明交换机
10     @Bean(EXCHANGE_TOPICS_INFORM)
11     public Exchange EXCHANGE_TOPICS_INFORM(){
12         //durable(true) 持久化,mq重启之后交换机还在
13         return ExchangeBuilder.topicExchange(EXCHANGE_TOPICS_INFORM).durable(true).build();
14     }
15 
16     //声明QUEUE_INFORM_EMAIL队列
17     @Bean(QUEUE_INFORM_EMAIL)
18     public Queue QUEUE_INFORM_EMAIL(){
19         return new Queue(QUEUE_INFORM_EMAIL);
20     }
21     //声明QUEUE_INFORM_SMS队列
22     @Bean(QUEUE_INFORM_SMS)
23     public Queue QUEUE_INFORM_SMS(){
24         return new Queue(QUEUE_INFORM_SMS);
25     }
26 
27     //ROUTINGKEY_EMAIL队列绑定交换机,指定routingKey
28     @Bean
29     public Binding BINDING_QUEUE_INFORM_EMAIL(@Qualifier(QUEUE_INFORM_EMAIL) Queue queue,
30                                               @Qualifier(EXCHANGE_TOPICS_INFORM) Exchange exchange){
31         return BindingBuilder.bind(queue).to(exchange).with(ROUTINGKEY_EMAIL).noargs();
32     }
33     //ROUTINGKEY_SMS队列绑定交换机,指定routingKey
34     @Bean
35     public Binding BINDING_ROUTINGKEY_SMS(@Qualifier(QUEUE_INFORM_SMS) Queue queue,
36                                               @Qualifier(EXCHANGE_TOPICS_INFORM) Exchange exchange){
37         return BindingBuilder.bind(queue).to(exchange).with(ROUTINGKEY_SMS).noargs();
38     }
39 }

生产者

 

 1 public class Producer05_topics_springboot {
 2     @Autowired
 3     RabbitTemplate rabbitTemplate;
 4 
 5     //使用rabbitTemplate发送消息
 6     @Test
 7     public void testSendEmail(){
 8 
 9         String message = "send email message to user";
10         /**
11          * 参数:
12          * 1、交换机名称
13          * 2、routingKey
14          * 3、消息内容
15          */
16         rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_TOPICS_INFORM,"inform.email",message);
17 
18     }
19 
20     //使用rabbitTemplate发送消息
21     @Test
22     public void testSendPostPage(){
23 
24         Map message = new HashMap<>();
25         message.put("pageId","5a795ac7dd573c04508f3a56");
26         //将消息对象转成json串
27         String messageString = JSON.toJSONString(message);
28         //路由key,就是站点ID
29         String routingKey = "5a751fab6abb5044e0d19ea1";
30         /**
31          * 参数:
32          * 1、交换机名称
33          * 2、routingKey
34          * 3、消息内容
35          */
36         rabbitTemplate.convertAndSend("ex_routing_cms_postpage",routingKey,messageString);
37 
38     }
39 
40 }

 

消费者

1 @Component
2 public class ReceiveHandler {
3 
4     @RabbitListener(queues = {RabbitmqConfig.QUEUE_INFORM_EMAIL})
5     public void send_email(String msg,Message message,Channel channel){
6         System.out.println("receive message is:"+msg);
7     }
8 
9 }

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!