各位看官可以關注博主個人博客,瞭解更多信息。
作者:Surpasser
鏈接地址:https://surpass.org.cn
前言
上篇我們說到了消息隊列RabbitMQ的模式概念,那麼這裏將會針對模式使用SpringBoot聯合RabbitMQ做一個案例,實現消息的生產和消費。
這一篇也是這個主題的最後一篇了,建議配合着看。助於理解。
博主會將Demo工程放在Gitee上,有興趣的可以拉下來自己試試。
Gitee地址:https://gitee.com/lemon_ant/os.git
正文
準備工作
新建SpringBoot項目
添加配置文件
server.port=8080
spring.application.name=cl
#RabbitMq所在服務器IP
spring.rabbitmq.host=127.0.0.1
#連接端口號
spring.rabbitmq.port=5672
#用戶名
spring.rabbitmq.username=root
#用戶密碼
spring.rabbitmq.password=123456
# 開啓發送確認
spring.rabbitmq.publisher-confirm-type=correlated
# 開啓發送失敗退回
spring.rabbitmq.publisher-returns=true
spring.rabbitmq.virtual-host=/
添加pom文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
啓動類
@SpringBootApplication
public class OsApplication {
public static void main(String[] args) {
SpringApplication.run(OsApplication.class, args);
}
}
點對點模式
-
隊列初始化
//當沒有這個隊列的時候會自動創建 @Configuration public class PointInitialization { @Bean Queue toPoint(){ Queue queue = new Queue("point.to.point",true); return queue; } }
-
生產者
@Component public class PointProducer { @Autowired private RabbitTemplate rabbitTemplate; public void send(String name){ String sendMsg = "點對點隊列:" + name + " " + new Date(); //指定隊列 this.rabbitTemplate.convertAndSend("point.to.point",sendMsg); } }
-
消費者
@Component public class PointConsumer { //監聽的隊列名 @RabbitListener(queues = "point.to.point") public void processOne(String name) { System.out.println("point.to.point:" + name); } }
-
測試類(模仿控制層)
@RestController @RequestMapping("/Point") public class PointController { @Autowired private PointProducer sayProducer; @RequestMapping("/point/{name}") public String send(@PathVariable String name){ sayProducer.send(name); return "發送成功"; } }
-
使用postman模擬請求
- 控制檯結果
work模式
-
隊列初始化
@Configuration public class WorkInitialization { //當沒有這個隊列的時候會自動創建 @Bean Queue work(){ Queue queue = new Queue("WorkingMode",true); return queue; } }
-
生產者
@Component public class WorkProducer { @Autowired private RabbitTemplate rabbitTemplate; public void send(String name){ String sendMsg = "工作模式:" + name + " " + new Date(); //指定隊列 this.rabbitTemplate.convertAndSend("WorkingMode",sendMsg); } }
-
消費者
//三個隊列同時監聽 @Component public class WorkConsumer { @RabbitListener(queues = "WorkingMode") public void processOne(String name) { System.out.println("WorkingMode1:" + name); } @RabbitListener(queues = "WorkingMode") public void processTwo(String name) { System.out.println("WorkingMode2:" + name); } @RabbitListener(queues = "WorkingMode") public void processThree(String name) { System.out.println("WorkingMode3:" + name); } }
-
測試類(模仿控制層)
@RestController @RequestMapping("/work") public class WorkController { @Autowired private WorkProducer sayProducer; @RequestMapping("/work/{name}") public String send(@PathVariable String name){ sayProducer.send(name); return "發送成功"; } }
-
使用postman模擬請求
- 控制檯結果
注意看時間,說明消息是輪詢分發的,一個消息只由一個消費者消費。
發佈/訂閱者模式(Publish/Subscribe)
-
隊列初始化
//類型爲fanout @Configuration public class PublishInitialization { //當沒有這個隊列的時候會自動創建 @Bean Queue publishOne(){ Queue queue = new Queue("queue.publish.one",true); return queue; } @Bean Queue publishTwo(){ Queue queue = new Queue("queue.publish.two",true); return queue; } @Bean Queue publishThree(){ Queue queue = new Queue("queue.publish.three",true); return queue; } //創建交換器 @Bean FanoutExchange pulishExchange(){ FanoutExchange directExchange = new FanoutExchange("publishExchange"); return directExchange; } //綁定隊列(不用指定routing key),參數名字要和bean名字一致 @Bean Binding bindingPublishOne(Queue publishOne,FanoutExchange pulishExchange){ Binding binding = BindingBuilder.bind(publishOne).to(pulishExchange); return binding; } @Bean Binding bindingPublishTwo(Queue publishTwo,FanoutExchange pulishExchange){ Binding binding = BindingBuilder.bind(publishTwo).to(pulishExchange); return binding; } @Bean Binding bindingPublishThree(Queue publishThree,FanoutExchange pulishExchange){ Binding binding = BindingBuilder.bind(publishThree).to(pulishExchange); return binding; } }
-
生產者
@Component public class PublishProducer { @Autowired private RabbitTemplate rabbitTemplate; public void send(String name){ String sendMsg = "發佈訂閱模式:" + name + " " + new Date(); //指定隊列 this.rabbitTemplate.convertAndSend("publishExchange","",sendMsg); } }
-
消費者
@Component public class PublishConsumer { @RabbitListener(queues = "queue.publish.one") public void processOne(String name) { System.out.println("queue.publish.one:" + name); } @RabbitListener(queues = "queue.publish.two") public void processTwo(String name) { System.out.println("queue.publish.two:" + name); } @RabbitListener(queues = "queue.publish.three") public void processThree(String name) { System.out.println("queue.publish.three:" + name); } }
-
測試類(模仿控制層)
@RestController @RequestMapping("/Publish") public class PublishController { @Autowired private PublishProducer sayProducer; @RequestMapping("/publish/{name}") public String send(@PathVariable String name){ sayProducer.send(name); return "發送成功"; } }
-
使用postman模擬請求
- 控制檯結果
注意看時間,交換機會將消息推送到所有綁定到它的隊列。
路由模式
-
隊列初始化
//類型爲direct @Configuration public class RoutingInitialization { //當沒有這個隊列的時候會自動創建 @Bean Queue routingOne(){ Queue queue = new Queue("queue.routing.one",true); return queue; } @Bean Queue routingTwo(){ Queue queue = new Queue("queue.routing.two",true); return queue; } @Bean Queue routingThree(){ Queue queue = new Queue("queue.routing.three",true); return queue; } //創建交換器 @Bean DirectExchange routingExchange(){ DirectExchange directExchange = new DirectExchange("routingExchange"); return directExchange; } //綁定隊列 @Bean Binding bindingRoutingOne(Queue routingOne,DirectExchange routingExchange){ Binding binding = BindingBuilder.bind(routingOne).to(routingExchange).with("1"); return binding; } @Bean Binding bindingRoutingTwo(Queue routingTwo,DirectExchange routingExchange){ Binding binding = BindingBuilder.bind(routingTwo).to(routingExchange).with("2"); return binding; } @Bean Binding bindingRoutingThree(Queue routingThree,DirectExchange routingExchange){ Binding binding = BindingBuilder.bind(routingThree).to(routingExchange).with("3"); return binding; } }
-
生產者
@Component public class RoutingProducer { @Autowired private RabbitTemplate rabbitTemplate; public void send(String type){ String sendMsg = "路由模式:" + type + " " + new Date(); //指定隊列 if (type.equals("1")){ this.rabbitTemplate.convertAndSend("routingExchange","1",sendMsg); } if (type.equals("2")){ this.rabbitTemplate.convertAndSend("routingExchange","2",sendMsg); } if (type.equals("3")){ this.rabbitTemplate.convertAndSend("routingExchange","3",sendMsg); } } }
-
消費者
@Component public class RoutingConsumer { @RabbitListener(queues = "queue.routing.one") public void processOne(String name) { System.out.println("queue.routing.one:" + name); } @RabbitListener(queues = "queue.routing.two") public void processTwo(String name) { System.out.println("queue.routing.two:" + name); } @RabbitListener(queues = "queue.routing.three") public void processThree(String name) { System.out.println("queue.routing.three:" + name); } }
-
測試類(模仿控制層)
@RestController @RequestMapping("/Routing") public class RoutingController { @Autowired private RoutingProducer sayProducer; @RequestMapping("/routing/{name}") public String send(@PathVariable String name){ sayProducer.send(name); return "發送成功"; } }
-
使用postman模擬請求
我這裏測試傳的就是routing key,方便看。
- 控制檯結果
這裏用時間來區別。
主題模式(Topic)
-
隊列初始化
//類型爲topic @Configuration public class TopicInitialization { //當沒有這個隊列的時候會自動創建 @Bean Queue topicOne(){ Queue queue = new Queue("queue.topic.one",true); return queue; } @Bean Queue topicTwo(){ Queue queue = new Queue("queue.topic.two",true); return queue; } @Bean Queue topicThree(){ Queue queue = new Queue("queue.topic.three",true); return queue; } //創建交換器 @Bean TopicExchange topicExchange(){ TopicExchange directExchange = new TopicExchange("topicExchange"); return directExchange; } //綁定隊列 @Bean Binding bindingTopicOne(Queue topicOne,TopicExchange topicExchange){ Binding binding = BindingBuilder.bind(topicOne).to(topicExchange).with("#.error"); return binding; } @Bean Binding bindingTopicTwo(Queue topicTwo,TopicExchange topicExchange){ Binding binding = BindingBuilder.bind(topicTwo).to(topicExchange).with("#.log"); return binding; } @Bean Binding bindingTopicThree(Queue topicThree,TopicExchange topicExchange){ Binding binding = BindingBuilder.bind(topicThree).to(topicExchange).with("good.#.timer"); return binding; } }
-
生產者
@Component public class TopicProducer { @Autowired private RabbitTemplate rabbitTemplate; public void send(String routing){ String sendMsg = "主題模式:" + routing + " " + new Date(); //指定隊列 this.rabbitTemplate.convertAndSend("topicExchange",routing,sendMsg); } }
-
消費者
@Component public class TopicConsumer { @RabbitListener(queues = "queue.topic.one") public void processOne(String name) { System.out.println("queue.topic.one:" + name); } @RabbitListener(queues = "queue.topic.two") public void processTwo(String name) { System.out.println("queue.topic.two:" + name); } @RabbitListener(queues = "queue.topic.three") public void processThree(String name) { System.out.println("queue.topic.three:" + name); } }
-
測試類(模仿控制層)
@RestController @RequestMapping("/Topic") public class TopicController { @Autowired private TopicProducer sayProducer; @RequestMapping("/topic/{type}") public String send(@PathVariable String type){ sayProducer.send(type); return "發送成功"; } }
-
請求以及對應結果
-
注意看請求的key和打印日誌的對應關係。
-
尾言
消息隊列在這裏基本就結束了,結合前面兩篇基本就能夠了解隊列的基本概念和用法了。