RabbitMq的介绍

RabbitMq的基本原理可以自行上网查阅,或者点击传送门:​​RabbitMQ的基本原理​​。

使用配置

1、老规矩,先在pom.xml中添加相关依赖:

1. ​​<!--消息队列模块-->​​
2. ​​<dependency>​​
3. ​​<groupId>org.springframework.boot</groupId>​​
4. ​​<artifactId>spring-boot-starter-amqp</artifactId>​​
5. ​​</dependency>​​

2、在application.properties添加rabbitmq的相关信息:

1. ​​spring.application.name=spirng-boot-rabbitmq​​
2. ​​spring.rabbitmq.host=127.0.0.1​​
3. ​​spring.rabbitmq.port=5672​​
4. ​​spring.rabbitmq.username=guest​​
5. ​​spring.rabbitmq.password=guest​​

端口、用户名和密码都是默认的,根据自己的实际情况配置,rabbitmq的安装教程网上很多了,这里暂时不介绍,以后有时间补上。

3、配置队列:

 

1. ​​package com.lyh.demo;​​
2.
3. ​​import org.springframework.amqp.core.Queue;​​
4. ​​import org.springframework.context.annotation.Bean;​​
5. ​​import org.springframework.context.annotation.Configuration;​​
6.
7. ​​/**​​
8. ​​* @Author:linyuanhuang​​
9. ​​* @Description:队列配置,队列的名称,发送者和接受者的名称必须一致,否则接收不到消息​​
10. ​​* @Date:2017/12/11 14:50​​
11. ​​*/​​
12. ​​@Configuration​​
13. ​​public class RabbitMqConfig {​​
14. ​​@Bean​​
15. ​​public Queue Queue1() {​​
16. ​​return new Queue("lyhTest1");​​
17. ​​}​​
18. ​​}​​

4、发送者通过Controller类发送消息:

1. ​​package com.lyh.demo.controller;​​
2.
3. ​​import org.springframework.amqp.core.AmqpTemplate;​​
4. ​​import org.springframework.beans.factory.annotation.Autowired;​​
5. ​​import org.springframework.web.bind.annotation.RequestMapping;​​
6. ​​import org.springframework.web.bind.annotation.RestController;​​
7.
8. ​​import java.util.Date;​​
9.
10. ​​@RestController​​
11. ​​public class SendController {​​
12. ​​@Autowired​​
13. ​​private AmqpTemplate amqpTemplate;​​
14.
15. ​​@RequestMapping("/send")​​
16. ​​public String send(){​​
17. ​​String content="Date:"+new Date();​​
18. ​​amqpTemplate.convertAndSend("lyhTest1",content);​​
19. ​​return content;​​
20. ​​}​​
21. ​​}​​

5、创建接受者Receiver1,新建类:

1. ​​package com.lyh.demo.Receiver;​​
2.
3. ​​import org.springframework.amqp.rabbit.annotation.RabbitHandler;​​
4. ​​import org.springframework.amqp.rabbit.annotation.RabbitListener;​​
5. ​​import org.springframework.stereotype.Component;​​
6.
7. ​​@Component​​
8. ​​@RabbitListener(queues = "lyhTest1")​​
9. ​​public class Receiver1 {​​
10.
11. ​​@RabbitHandler​​
12. ​​public void receiver(String msg){​​
13. ​​System.out.println("Test1 receiver1:"+msg);​​
14. ​​}​​
15. ​​}​​

6、测试

浏览器访问地址:http://localhost:8080/send,如下图:

Spring Boot——RabbitMQ_RabbitMQ

终端输出接受的内容:

Spring Boot——RabbitMQ_spring_02

查看RabbitMQ的Web客户端​​http://localhost:15672​​,需要自己安装RabbitMQ的客户端,可以自己上网查阅相关教程。帐号密码和配置文件一样,如下图:可以在列表里看到之前创建的队列。

Spring Boot——RabbitMQ_spring_03

一对多的使用配置

1、一对多,一个发送者发送消息,多个接受者接受同一个消息,添加新的接收者Receiver2:

1. ​​package com.lyh.demo.Receiver;​​
2.
3. ​​import org.springframework.amqp.rabbit.annotation.RabbitHandler;​​
4. ​​import org.springframework.amqp.rabbit.annotation.RabbitListener;​​
5. ​​import org.springframework.stereotype.Component;​​
6.
7. ​​@Component​​
8. ​​@RabbitListener(queues = "lyhTest1")​​
9. ​​public class Receiver2 {​​
10.
11. ​​@RabbitHandler​​
12. ​​public void receiver(String msg){​​
13. ​​System.out.println("Test1 receiver2:"+msg);​​
14. ​​}​​
15. ​​}​​

2、发送者循环发送10个消息,在SendController添加一对多发送方法:

 

1. ​​@RequestMapping("/multiSend")​​
2. ​​public String multiSend(){​​
3. ​​StringBuilder times=new StringBuilder();​​
4. ​​for(int i=0;i<10;i++){​​
5. ​​long time=System.nanoTime();​​
6. ​​amqpTemplate.convertAndSend("lyhTest1","第"+i+"次发送的时间:"+time);​​
7. ​​times.append(time+"<br>");​​
8. ​​}​​
9. ​​return times.toString();​​
10. ​​}​​

3、测试,浏览器访问​​http://localhost:8080/multiSend​​,如下图:

 

Spring Boot——RabbitMQ_接受者_04


 

4、终端输出接收数据:

 

Test1 receiver2:第1次发送的时间:25953655163399
Test1 receiver1:第0次发送的时间:25953641137213
Test1 receiver2:第2次发送的时间:25953655403734
Test1 receiver1:第3次发送的时间:25953655591967
Test1 receiver1:第5次发送的时间:25953655949458
Test1 receiver2:第4次发送的时间:25953655772971
Test1 receiver1:第6次发送的时间:25953656111790
Test1 receiver1:第8次发送的时间:25953656492471
Test1 receiver1:第9次发送的时间:25953656687330
Test1 receiver2:第7次发送的时间:25953656277133

可以看到发送者发送一个消息被多个接收者接收,注意这里的消息只能被消费一次

多对多的使用配置

1、在配置类RabbbitMqConfig添加新的队列名lyhTest2:

 

1. ​​@Configuration​​
2. ​​public class RabbitMqConfig {​​
3. ​​@Bean​​
4. ​​public Queue Queue1() {​​
5. ​​return new Queue("lyhTest1");​​
6. ​​}​​
7. ​​@Bean​​
8. ​​public Queue Queue2() {​​
9. ​​return new Queue("lyhTest2");​​
10. ​​}​​
11. ​​}​​

2、修改Receiver2接收队列名为lyhTest2:

1. ​​@Component​​
2. ​​@RabbitListener(queues = "lyhTest2")​​
3. ​​//这里的lyhTest2是多对多,如果要测试一对多改成lyhTest1​​
4. ​​public class Receiver2 {​​
5.
6. ​​@RabbitHandler​​
7. ​​public void receiver(String msg){​​
8. ​​System.out.println("Test2 receiver2:"+msg);​​
9. ​​}​​
10. ​​}​​

3、在SendController添加多对多发送消息的方法:

1. ​​@RequestMapping("/multi2MultiSend")​​
2. ​​public String mutil2MutilSend(){​​
3. ​​StringBuilder times=new StringBuilder();​​
4. ​​for(int i=0;i<10;i++){​​
5. ​​long time=System.nanoTime();​​
6. ​​amqpTemplate.convertAndSend("lyhTest1","第"+i+"次发送的时间:"+time);​​
7. ​​amqpTemplate.convertAndSend("lyhTest2","第"+i+"次发送的时间:"+time);​​
8. ​​times.append(time+"<br>");​​
9. ​​}​​
10. ​​return times.toString();​​
11. ​​}​​

4、测试,浏览器访问:​​http://localhost:8080/multi2MultiSend​​,如下图:

Spring Boot——RabbitMQ_RabbitMQ_05

5、终端输出接收数据:

 

Test1 receiver1:第0次发送的时间:27607875773748
Test2 receiver2:第0次发送的时间:27607875773748
Test2 receiver2:第1次发送的时间:27607882272138
Test2 receiver2:第2次发送的时间:27607882429049
Test1 receiver1:第1次发送的时间:27607882272138
Test2 receiver2:第3次发送的时间:27607882594693
Test1 receiver1:第2次发送的时间:27607882429049
Test2 receiver2:第4次发送的时间:27607882897371
Test1 receiver1:第3次发送的时间:27607882594693
Test2 receiver2:第5次发送的时间:27607883163005
Test1 receiver1:第4次发送的时间:27607882897371
Test2 receiver2:第6次发送的时间:27607883319916
Test2 receiver2:第7次发送的时间:27607883489777
Test1 receiver1:第5次发送的时间:27607883163005
Test1 receiver1:第6次发送的时间:27607883319916
Test2 receiver2:第8次发送的时间:27607883957798
Test2 receiver2:第9次发送的时间:27607884305953
Test1 receiver1:第7次发送的时间:27607883489777
Test1 receiver1:第8次发送的时间:27607883957798
Test1 receiver1:第9次发送的时间:27607884305953

       可以看到不同的接收者接收不同发送者发送的消息,消息也可以是实体对象,这里就不做演示。

Topic Exchange的使用配置

Topic Exchange是RabbitMQ中最灵活的一种方式,它能够根据routing_key自由的绑定不同的队列,可以适用绝大部分的项目需求

1、新建RabbitMqTopicConfig配置类:

 

package com.lyh.demo;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @Author:linyuanhuang
* @Description:Topic Exchange配置类
* @Date:2017/12/11 17:13
*/
@Configuration
public class {
//只接一个topic
final static String message = "topic.message";
//接收多个topic
final static String messages = "topic.messages";

@Bean
public Queue queueMessage() {
return new Queue(RabbitMqTopicConfig.message);
}

@Bean
public Queue queueMessages() {
return new Queue(RabbitMqTopicConfig.messages);
}

@Bean
TopicExchange exchange() {
return new TopicExchange("exchange");
}

@Bean
Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {
return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
}

@Bean
Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {
//这里的#表示零个或多个词。
return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
}

2、在SendController添加发送消息方法:

@RequestMapping("/topicSend1")
public String topicSend1() {
String context = "my topic 1";
System.out.println("发送者说 : " + context);
this.amqpTemplate.convertAndSend("exchange", "topic.message", context);
return context;
}
@RequestMapping("/topicSend2")
public String topicSend2() {
String context = "my topic 2";
System.out.println("发送者说 : " + context);
this.amqpTemplate.convertAndSend("exchange", "topic.messages", context);
return context;

3、创建接收者的方法TopicReceiver1和TopicReceiver2:

 

TopicReceiver1:

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
@RabbitListener(queues = "topic.message")
public class TopicReceiver1 {
@RabbitHandler
public void process(String msg) {
System.out.println("TopicReceiver1:" + msg);
}

}
TopicReceiver2:
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
@RabbitListener(queues = "topic.messages")
public class TopicReceiver2 {
@RabbitHandler
public void process(String msg) {
System.out.println("TopicReceiver2 :" + msg);
}

4、测试:

浏览器访问​​http://localhost:8080/topicSend1​​,终端输出:

发送者说 : my topic 1
TopicReceiver1:my topic 1
TopicReceiver2 :my topic 1

浏览器访问​​http://localhost:8080/topicSend2​​,终端输出:

发送者说 : my topic 2
TopicReceiver2 :my topic 2
5、总结:

这里的Topic Exchange 转发消息主要是根据通配符,队列topic.message只能匹配topic.message的路由。而topic.messages匹配路由规则是topic.#,所以它可以匹配topic.开头的全部路由。而topic.#发送的消息也只能是topic.#的接受者才能接收。

GitHub地址:​​https://github.com/lyhkmm/spring-boot-examples/tree/master/spring-boot-rabbitmq​