先参考单个springboot使用rabbitmq和了解rabbitmq的五种模式
单个springboot整合rabbitmq_java-zh的博客-CSDN博客
1、先创建两个springboot项目,一个做生产者,一个做消费者
2、导包(生产者和消费者对应的内容都是一样)
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.4.1
com.mq
mqcloud
0.0.1-SNAPSHOT
2021.1
1.8
2.5.3
1.18.14
3.3.2
1.2.75
3.0.2
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-devtools
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-starter-aop
org.springframework.cloud
spring-cloud-starter-bootstrap
${spring-cloud-starter-bootstrap.version}
com.alibaba
fastjson
${alibaba.json.version}
org.projectlombok
lombok
${lombok.version}
true
io.jsonwebtoken
jjwt
0.9.0
com.google.guava
guava
31.1-jre
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
${spring-cloud-alibaba.version}
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
${spring-cloud-alibaba.version}
org.apache.commons
commons-lang3
3.12.0
com.common
base
1.0-SNAPSHOT
org.springframework.boot
spring-boot-starter-amqp
3.0.4
3、编写配置文件
这里的配置文件生产者和消费者都一样
spring:
rabbitmq:
#如果是集群,用,隔开
connection-timeout: 15000
username: admin
password: 123456
#虚拟host,可以不设置
virtual-host: /
listener:
simple:
acknowledge-mode: auto #manual:手动处理 auto:自动处理
#消费端监听个数(即@RabbitListenter开启几个线程去处理)
concurrency: 10
#消费端监听的最大个数
max-concurrency: 10
prefetch: 5
default-requeue-rejected: true #消费不成功的消息,拒绝入队
retry:
enabled: true #开启消息重试
max-attempts: 4 #重试次数
max-interval: 10000 #重试最大间隔时间
initial-interval: 2000 #重试初始间隔时间
#消息确认方式,通过correlated来确认
publisher-confirm-type: correlated
publisher-returns: true
host: 192.168.139.128
port: 5672
rabbitmq:
#订阅模式(扇形模式)
fanout:
exchange:
#交换机名称
name1: exchange.fanout
queue:
#通道名称
name1: exchange.fanout.queue_1
name2: exchange.fanout.queue_2
#交换机模式
direct:
exchange:
name1: exchange.direct
queue:
name1: exchange.direct.queue_1
name2: exchange.direct.queue_2
routing:
name1: exchange.direct.routing.1
name2: exchange.direct.routing.2
#主题模式
topic:
exchange:
name1: exchange.topic
queue:
name1: exchange.topic.queue_1
name2: exchange.topic.queue_2
routing:
name1: '#.routingkey.#'
name2: routingkey.*
这里以rabbitmq的订阅模式(扇形模式)、路由器模式、主题模式为案例
生产者
@Autowired
private RabbitTemplate rabbitTemplate;
// 订阅模式的交换机名称
@Value("${rabbitmq.fanout.exchange.name1}")
private String exchangeName;
/**
* 订阅模式(扇形模式)生产者
*
* @param context
*/
@GetMapping("/fanout/{context}")
public void sendMessage(@PathVariable String context) {
System.out.println("需要发送得内容为:" + context);
rabbitTemplate.convertAndSend(exchangeName, "", context);
}
消费者
注意:消费者绑定交换机和通道的值必须是固定常量值,所以我们直接从配置文件中读取
@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.fanout.exchange.name1}", type = ExchangeTypes.FANOUT),
value = @Queue(value = "${rabbitmq.fanout.queue.name1}")))
@RabbitHandler
public void consumerFanoutExchange(String context) {
System.out.println("订阅模式,通道一接收到的内容为内容:" + context);
}
@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.fanout.exchange.name1}", type = ExchangeTypes.FANOUT),
value = @Queue(value = "${rabbitmq.fanout.queue.name2}")))
@RabbitHandler
public void consumerFanoutExchange2(String context) {
System.out.println("订阅模式,通道二接收到的内容为内容:" + context);
}
生产者
@Autowired
private RabbitTemplate rabbitTemplate;
// 路由器模式的交换机名称
@Value("${rabbitmq.direct.exchange.name1}")
private String directName;
// 路由器模式的路由key1
@Value("${rabbitmq.direct.routing.name1}")
private String directRoutingKeyName1;
//路由器模式的路由key2
@Value("${rabbitmq.direct.routing.name2}")
private String directRoutingKeyName2;
/**
* 路由器模式
* @param context
* @param routingkey
*/
@GetMapping("/direct")
public void sendMessageDirect(@RequestParam("context") String context, @RequestParam("routingkey") Integer routingkey) {
if (1 == routingkey) {
rabbitTemplate.convertAndSend(directName, directRoutingKeyName1, context);
} else if (2 == routingkey) {
rabbitTemplate.convertAndSend(directName, directRoutingKeyName2, context);
} else {
System.out.println("数据非法");
}
}
消费者
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(value = "${rabbitmq.direct.exchange.name1}", type = ExchangeTypes.DIRECT),
value = @Queue(value = "${rabbitmq.direct.queue.name1}"),
key = "${rabbitmq.direct.routing.name1}"))
public void exchangeDirectRoutingKey1(String context, Message message) {
System.out.println("key1:" + message.getMessageProperties().getReceivedRoutingKey());
System.out.println("路由器模式1 接收到的消息为:" + context);
}
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(value = "${rabbitmq.direct.exchange.name1}", type = ExchangeTypes.DIRECT),
value = @Queue(value = "${rabbitmq.direct.queue.name2}"),
key = "${rabbitmq.direct.routing.name2}"))
public void exchangeDirectRoutingKey2(String context, Message message) {
System.out.println("key2:" + message.getMessageProperties().getReceivedRoutingKey());
System.out.println("路由器模式2 接收到的消息为" + context);
}
生产者
// 主题模式的交换机名称
@Value("${rabbitmq.topic.exchange.name1}")
private String topicName;
//用来匹配主题模式对应的key
public static final String EXCHANGE_TOPIC_CASE_KEY_1 = "topic.routingkey.case1";
//如果case_key_2这样写,那么绑定case_key_1的队列一样会接收到,因为case_key_2也一样和key1匹配上
public static final String EXCHANGE_TOPIC_CASE_KEY_2 = "routingkey.case2";
@GetMapping("/topic")
public void sendMessageTopic(@RequestParam("context") String context, @RequestParam("routingkey") Integer routingkey) {
if (1 == routingkey) {
rabbitTemplate.convertAndSend(topicName, EXCHANGE_TOPIC_CASE_KEY_1, context + routingkey);
} else if (2 == routingkey) {
rabbitTemplate.convertAndSend(topicName, EXCHANGE_TOPIC_CASE_KEY_2, context + routingkey);
} else {
System.out.println("数据非法");
}
}
消费者
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(value = "${rabbitmq.topic.exchange.name1", type = ExchangeTypes.TOPIC),
value = @Queue(value = "${rabbitmq.topic.queue.name1}"),
key = "${rabbitmq.topic.routing.name1}"))
@RabbitHandler
public void exchangeTopicRoutingKey1(String context, Message message) {
System.out.println("key1:"+message.getMessageProperties().getReceivedRoutingKey());
System.out.println("主题模式1:接收的内容为:"+ context);
}
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(value = "${rabbitmq.topic.exchange.name1", type = ExchangeTypes.TOPIC),
value = @Queue(value = "${rabbitmq.topic.queue.name2}"),
key = "${rabbitmq.topic.routing.name2}"))
@RabbitHandler
public void exchangeTopicRoutingKey2(String context, Message message) {
System.out.println("key2:"+message.getMessageProperties().getReceivedRoutingKey());
System.out.println("主题模式2:接收的内容为:"+ context);
}
生产者
@RestController
@RequiredArgsConstructor
@RequestMapping("/test/mq")
public class ProductController {
private final RabbitTemplate rabbitTemplate;
// 订阅模式的交换机名称
@Value("${rabbitmq.fanout.exchange.name1}")
private String exchangeName;
// 路由器模式的交换机名称
@Value("${rabbitmq.direct.exchange.name1}")
private String directName;
// 路由器模式的路由key1
@Value("${rabbitmq.direct.routing.name1}")
private String directRoutingKeyName1;
//路由器模式的路由key2
@Value("${rabbitmq.direct.routing.name2}")
private String directRoutingKeyName2;
// 主题模式的交换机名称
@Value("${rabbitmq.topic.exchange.name1}")
private String topicName;
//用来匹配主题模式对应的key
public static final String EXCHANGE_TOPIC_CASE_KEY_1 = "topic.routingkey.case1";
//如果case_key_2这样写,那么绑定case_key_1的队列一样会接收到,因为case_key_2也一样和key1匹配上
public static final String EXCHANGE_TOPIC_CASE_KEY_2 = "routingkey.case2";
/**
* 订阅模式(扇形模式)生产者
*
* @param context
*/
@GetMapping("/fanout/{context}")
public void sendMessage(@PathVariable String context) {
System.out.println("需要发送得内容为:" + context);
rabbitTemplate.convertAndSend(exchangeName, "", context);
}
/**
* 路由器模式
* @param context
* @param routingkey
*/
@GetMapping("/direct")
public void sendMessageDirect(@RequestParam("context") String context, @RequestParam("routingkey") Integer routingkey) {
if (1 == routingkey) {
rabbitTemplate.convertAndSend(directName, directRoutingKeyName1, context);
} else if (2 == routingkey) {
rabbitTemplate.convertAndSend(directName, directRoutingKeyName2, context);
} else {
System.out.println("数据非法");
}
}
@GetMapping("/topic")
public void sendMessageTopic(@RequestParam("context") String context, @RequestParam("routingkey") Integer routingkey) {
if (1 == routingkey) {
rabbitTemplate.convertAndSend(topicName, EXCHANGE_TOPIC_CASE_KEY_1, context + routingkey);
} else if (2 == routingkey) {
rabbitTemplate.convertAndSend(topicName, EXCHANGE_TOPIC_CASE_KEY_2, context + routingkey);
} else {
System.out.println("数据非法");
}
}
}
消费者
@Component
public class ConsumerTest {
@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.fanout.exchange.name1}", type = ExchangeTypes.FANOUT),
value = @Queue(value = "${rabbitmq.fanout.queue.name1}")))
@RabbitHandler
public void consumerFanoutExchange(String context) {
System.out.println("订阅模式,通道一接收到的内容为内容:" + context);
}
@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(value = "${rabbitmq.fanout.exchange.name1}", type = ExchangeTypes.FANOUT),
value = @Queue(value = "${rabbitmq.fanout.queue.name2}")))
@RabbitHandler
public void consumerFanoutExchange2(String context) {
System.out.println("订阅模式,通道二接收到的内容为内容:" + context);
}
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(value = "${rabbitmq.direct.exchange.name1}", type = ExchangeTypes.DIRECT),
value = @Queue(value = "${rabbitmq.direct.queue.name1}"),
key = "${rabbitmq.direct.routing.name1}"))
public void exchangeDirectRoutingKey1(String context, Message message) {
System.out.println("key1:" + message.getMessageProperties().getReceivedRoutingKey());
System.out.println("路由器模式1 接收到的消息为:" + context);
}
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(value = "${rabbitmq.direct.exchange.name1}", type = ExchangeTypes.DIRECT),
value = @Queue(value = "${rabbitmq.direct.queue.name2}"),
key = "${rabbitmq.direct.routing.name2}"))
public void exchangeDirectRoutingKey2(String context, Message message) {
System.out.println("key2:" + message.getMessageProperties().getReceivedRoutingKey());
System.out.println("路由器模式2 接收到的消息为" + context);
}
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(value = "${rabbitmq.topic.exchange.name1", type = ExchangeTypes.TOPIC),
value = @Queue(value = "${rabbitmq.topic.queue.name1}"),
key = "${rabbitmq.topic.routing.name1}"))
@RabbitHandler
public void exchangeTopicRoutingKey1(String context, Message message) {
System.out.println("key1:"+message.getMessageProperties().getReceivedRoutingKey());
System.out.println("主题模式1:接收的内容为:"+ context);
}
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(value = "${rabbitmq.topic.exchange.name1", type = ExchangeTypes.TOPIC),
value = @Queue(value = "${rabbitmq.topic.queue.name2}"),
key = "${rabbitmq.topic.routing.name2}"))
@RabbitHandler
public void exchangeTopicRoutingKey2(String context, Message message) {
System.out.println("key2:"+message.getMessageProperties().getReceivedRoutingKey());
System.out.println("主题模式2:接收的内容为:"+ context);
}
}