導讀
由於工作上需要,客戶那指定要使用RabbitMQ,之前學過RocketMQ(點我直達1,點我直達2)、ActiveMQ(點我直達1,點我直達2)都沒用上。項目時間又趕,今天下午先在自己的阿里雲服務器上搭建好RabbitMQ(點我直達),然後去github,百度上找一大堆資料,發現跑不通,沒辦法,快速學習,整理一套SpringBoot整合RabbitMQ的5種模式(hello world、work queue、Publish/Subscribe、Routing、Topics)。
項目結構
項目演示
阿里雲服務器搭建RabbitMQ
生產者項目
項目結構
生產者代碼
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.ybchen</groupId> <artifactId>springboot-rabbitmq-producer</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springboot-rabbitmq-producer</name> <description>SpringBoot整合RabbitMQ-生產者</description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <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> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency> <!--SpringBoot整合RabbitMQ--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
server.port=8888
spring.rabbitmq.host=xxx.xxx.xxx.xxx
spring.rabbitmq.port=5672
spring.rabbitmq.username=xxxx
spring.rabbitmq.password=xxxxx
package com.ybchen.producer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootRabbitmqProducerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootRabbitmqProducerApplication.class, args);
}
}
package com.ybchen.producer.entity;
public class Clz{
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Clz{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}
package com.ybchen.producer.controller;
import com.ybchen.producer.entity.Clz;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @Description:hello world模型
* @Author:chenyanbin
* @Date:2021/1/6 5:35 下午
* @Versiion:1.0
*/
@RestController
@RequestMapping("/api/v1")
public class ProducerV1Controller {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* hello world模型
* @param data
* @return
*/
@PostMapping("sendMQ")
public String sendMQ(@RequestBody Clz data) {
System.out.println("接收到參數:"+data);
//第一個參數:隊列名稱
//第二個參數:javaBean
rabbitTemplate.convertAndSend("hello", "hello ,rabbitmq, now is :" + data);
return "ok";
}
}
package com.ybchen.producer.controller; import com.ybchen.producer.entity.Clz; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @Description:Work queues工作隊列 * 假設一個生產者生產2條消息 * 有2個消費者,此時,會通過輪詢方式,每個消費者消費一條消息 * @Author:chenyanbin * @Date:2021/1/6 9:32 下午 * @Versiion:1.0 */ @RestController @RequestMapping("/api/v2") public class ProducerV2Controller { @Autowired private RabbitTemplate rabbitTemplate; /** * 公平消費 * @param data * @return */ @PostMapping("sendMQ") public String sendMQ(@RequestBody Clz data) { System.out.println("接收到參數:"+data); //第一個參數:隊列名稱 //第二個參數:javaBean for (int i = 0; i < 10; i++) { rabbitTemplate.convertAndSend("work", "work模型:" + data); } return "ok"; } }
package com.ybchen.producer.controller;
import com.ybchen.producer.entity.Clz;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description:發佈訂閱模型,fanout
* @Author:chenyanbin
* @Date:2021/1/6 9:47 下午
* @Versiion:1.0
*/
@RestController
@RequestMapping("/api/v3")
public class ProducerV3Controller {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 公平消費
*
* @param data
* @return
*/
@PostMapping("sendMQ")
public String sendMQ(@RequestBody Clz data) {
System.out.println("接收到參數:" + data);
//第一個參數:隊列名稱
//第二個參數:javaBean
rabbitTemplate.convertAndSend("logs", "", "fanout模型:" + data);
return "ok";
}
}
package com.ybchen.producer.controller;
import com.ybchen.producer.entity.Clz;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description:路由模型
* @Author:chenyanbin
* @Date:2021/1/6 9:59 下午
* @Versiion:1.0
*/
@RestController
@RequestMapping("/api/v4")
public class ProducerV4Controller {
@Autowired
private RabbitTemplate rabbitTemplate;
@PostMapping("sendMQ")
public String sendMQ(@RequestBody Clz data) {
System.out.println("接收到參數:" + data);
//第一個參數:交換機名字
//第二個參數:info相關的信息
//第三個參數:javaBean
rabbitTemplate.convertAndSend("directs", "info", "路由模型:" + data);
return "ok";
}
@PostMapping("sendMQ2")
public String sendMQ2(@RequestBody Clz data) {
System.out.println("接收到參數:" + data);
//第一個參數:交換機名字
//第二個參數:info相關的信息
//第三個參數:javaBean
rabbitTemplate.convertAndSend("directs", "error", "路由模型:" + data);
return "ok";
}
}
package com.ybchen.producer.controller;
import com.ybchen.producer.entity.Clz;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description:訂閱模式,topic
* @Author:chenyanbin
* @Date:2021/1/6 10:22 下午
* @Versiion:1.0
*/
@RestController
@RequestMapping("/api/v5")
public class ProducerV5Controller {
@Autowired
private RabbitTemplate rabbitTemplate;
@PostMapping("sendMQ")
public String sendMQ(@RequestBody Clz data) {
System.out.println("接收到參數:" + data);
//第一個參數:交換機名字
//第二個參數:info相關的信息
//第三個參數:javaBean
rabbitTemplate.convertAndSend("topics", "user.save", "訂閱模型:" + data);
return "ok";
}
@PostMapping("sendMQ2")
public String sendMQ2(@RequestBody Clz data) {
System.out.println("接收到參數:" + data);
//第一個參數:交換機名字
//第二個參數:info相關的信息
//第三個參數:javaBean
rabbitTemplate.convertAndSend("topics", "order.save", "訂閱模型:" + data);
return "ok";
}
}
消費者項目
項目結構
消費者代碼
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.ybchen</groupId> <artifactId>springboot-rabbitmq-consumer</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springboot-rabbitmq-consumer</name> <description>SpringBoot整合RabbitMQ-消費者</description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <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> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency> <!--SpringBoot整合RabbitMQ--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
server.port=9999
spring.rabbitmq.host=xxx.xxx.xxx.xxx
spring.rabbitmq.port=5672
spring.rabbitmq.username=xxx
spring.rabbitmq.password=xxx
package com.ybchen.consumer; import org.springframework.amqp.rabbit.annotation.EnableRabbit; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @EnableRabbit public class SpringbootRabbitmqConsumerApplication { public static void main(String[] args) { SpringApplication.run(SpringbootRabbitmqConsumerApplication.class, args); } }
package com.ybchen.consumer.controller; import org.springframework.amqp.rabbit.annotation.Queue; import org.springframework.amqp.rabbit.annotation.RabbitHandler; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; /** * @Description:hello world模型 * @Author:chenyanbin * @Date:2021/1/6 6:03 下午 * @Versiion:1.0 */ //被spring掃描到 @Component //@Queue:沒有的話,創建隊列 //declare:不持久化,默認:true //autoDelete:是否自動刪除 //@Queue(value = "hello",declare = "false",autoDelete = "true") @RabbitListener(queuesToDeclare = @Queue(value = "hello",declare = "false",autoDelete = "true")) public class ConsumerV1 { //監聽mq裏的隊列,接收那個隊列裏的消息,沒有隊列的話,去聲明一個隊列 /** * @RabbitHandler:從隊列中拿到消息的回調方法 * @param message */ @RabbitHandler public void helloWorld(String message) { System.out.println(message); } }
package com.ybchen.consumer.controller; import org.springframework.amqp.rabbit.annotation.Queue; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; /** * @Description:Work queues工作隊列 * @Author:chenyanbin * @Date:2021/1/6 9:33 下午 * @Versiion:1.0 */ @Component public class ConsumerV2 { //加在方法上,代表會監聽這個方法的回調 //消費者-1 @RabbitListener(queuesToDeclare = @Queue("work")) public void receive_1(String message) { System.out.println("work模型 receive_1====>" + message); } //加在方法上,代表會監聽這個方法的回調 //消費者-2 @RabbitListener(queuesToDeclare = @Queue("work")) public void receive_2(String message) { System.out.println("work模型 receive_2====>" + message); } }
package com.ybchen.consumer.controller; import org.springframework.amqp.rabbit.annotation.Exchange; import org.springframework.amqp.rabbit.annotation.Queue; import org.springframework.amqp.rabbit.annotation.QueueBinding; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; /** * @Description:發佈訂閱模型,fanout * @Author:chenyanbin * @Date:2021/1/6 9:47 下午 * @Versiion:1.0 */ @Component public class ConsumerV3 { //加在方法上,代表會監聽這個方法的回調 //消費者-1 @RabbitListener(bindings = { @QueueBinding( value = @Queue, //創建臨時隊列 exchange = //交換機 @Exchange( value = "logs",type = "fanout" //交換機名字,類型 ) ) }) public void receive_1(String message) { System.out.println("發佈訂閱模型 receive_1====>" + message); } //加在方法上,代表會監聽這個方法的回調 //消費者-1 @RabbitListener(bindings = { @QueueBinding( value = @Queue, //創建臨時隊列 exchange = //交換機 @Exchange( value = "logs",type = "fanout" //交換機名字,類型 ) ) }) public void receive_2(String message) { System.out.println("發佈訂閱模型 receive_2====>" + message); } }
package com.ybchen.consumer.controller; import org.springframework.amqp.rabbit.annotation.Exchange; import org.springframework.amqp.rabbit.annotation.Queue; import org.springframework.amqp.rabbit.annotation.QueueBinding; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; /** * @Description:路由模型 * @Author:chenyanbin * @Date:2021/1/6 10:00 下午 * @Versiion:1.0 */ @Component public class ConsumerV4 { /** * 會接受info、error、warn信息 * @param message */ @RabbitListener( bindings = { @QueueBinding( value = @Queue, //創建臨時隊列 exchange = @Exchange( value = "directs", type = "direct" //交換機名稱和類型 ), key = {"info", "error", "warn"} //接收路由的信心 ) } ) public void receive_1(String message) { System.out.println("路由-1:" + message); } /** * 只會接受error的路由信息 * @param message */ @RabbitListener( bindings = { @QueueBinding( value = @Queue, //創建臨時隊列 exchange = @Exchange( value = "directs", type = "direct" //交換機名稱和類型 ), key = {"error"} //接收路由的信心 ) } ) public void receive_2(String message) { System.out.println("路由-2:" + message); } }
package com.ybchen.consumer.controller; import org.springframework.amqp.rabbit.annotation.Exchange; import org.springframework.amqp.rabbit.annotation.Queue; import org.springframework.amqp.rabbit.annotation.QueueBinding; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; /** * @Description:訂閱模式,topic * @Author:chenyanbin * @Date:2021/1/6 10:25 下午 * @Versiion:1.0 */ @Component public class ConsumerV5 { @RabbitListener( bindings = @QueueBinding( value = @Queue, //創建臨時隊列 exchange = @Exchange( //交換機 type = "topic", name = "topics" //類型和名稱 ), key = {"user.save", "user.*"} ) ) public void receive_1(String message) { System.out.println("訂閱模型 receive_1====>" + message); } @RabbitListener( bindings = @QueueBinding( value = @Queue, //創建臨時隊列 exchange = @Exchange( //交換機 type = "topic", name = "topics" //類型和名稱 ), key = {"order.#", "produce.#","user.*"} //可以使用正則方式 ) ) public void receive_2(String message) { System.out.println("訂閱模型 receive_2====>" + message); } }
案例源碼下載
鏈接: https://pan.baidu.com/s/1SnutjcAJlQG9Io1Z_F9kJA 密碼: itn4
尾聲
滿打滿算RabbitMQ算是告一段落,今天只是停留在會簡單的使用,具體配置項還不是很瞭解,各種調優啥的,未來還是要在認真的系統學習一遍滴,今天先到這,洗洗睡啦,ヾ(ToT)Bye~Bye~