交换机与队列进行绑定的方式
1.配置类config(消费者端和生产者端)推荐
2.注解(在消费者端使用@RabbitListener(bindings = @QueueBinding()进行绑定)
3.页面绑定(不推荐)
springboot整合RabbitMQ
业务场景,模拟用户下单,交换机进行消息分发
生产者和消费者分属不同的模块
工程架构
Fanout 模式(交换机与队列绑定在生产者端)
引入依赖项
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
配置文件application.yml
# 服务端口
server:
port: 8080
# 配置rabbitmq服务
spring:
rabbitmq:
username: ems
password: ems
virtual-host: /ems
host: 39.105.××× //阿里云服务器地址,先开端口号
port: 5672
生产者
service发送消息
package com.yhd.rabbitmq.service;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;
/**
* @author 袁浩东
* @description
* @date 2021/7/20 20:53
*/
@Service
public class OrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
public void makeOrder(String userid,String productid,int num){
//1.根据商品id查询库存是否足够
//2.保存订单
String orderId = UUID.randomUUID().toString();
System.out.println("订单生产成功:"+orderId);
//3.通过MQ来完成消息的分发
//参数1:交换机 参数2:路由key/queue队列名称 参数3:消息内容
String exchangeName = "fanout_order_exchange";
String routingKey = "";
rabbitTemplate.convertAndSend(exchangeName,routingKey,orderId);
}
}
使用配置类完成交换机和队列的绑定关系
package com.yhd.rabbitmq.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author 袁浩东
* @description
* @date 2021/7/20 20:56
*/
@Configuration
public class RabbitMqConfiguration {
//1.声明注册fanout模式的交换机
@Bean
public FanoutExchange fanoutExchange(){
//参数1,交换机名字 参数2,交换机是否持久化 参数3,是否自动删除
return new FanoutExchange("fanout_order_exchange",true,false);
}
//2.声明3个队列
@Bean
public Queue smsQueue(){
//参数1,队列名称 参数2,是否持久化
return new Queue("sms.fanout.queue",true);
}
@Bean
public Queue duanxinQueue(){
return new Queue("duanxin.fanout.queue",true);
}
@Bean
public Queue emailQueue(){
return new Queue("email.fanout.queue",true);
}
//3.完成队列和交换机的绑定关系
@Bean
public Binding smsBingding(){
return BindingBuilder.bind(smsQueue()).to(fanoutExchange());
}
@Bean
public Binding duanxinBingding(){
return BindingBuilder.bind(duanxinQueue()).to(fanoutExchange());
}
@Bean
public Binding emailBingding(){
return BindingBuilder.bind(emailQueue()).to(fanoutExchange());
}
}
测试类注入并调用
package com.yhd.rabbitmq;
import com.yhd.rabbitmq.service.OrderService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class RabbitmqApplicationTests {
@Autowired
private OrderService orderService;
@Test
void contextLoads() {
orderService.makeOrder("1","1",12);
}
}
运行结果
交换机
队列中的绑定交换机的信息
消费者
依赖项
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
配置文件application.yml
# 服务端口
server:
port: 8081 //避免端口号冲突
# 配置rabbitmq服务
spring:
rabbitmq:
username: ems
password: ems
virtual-host: /ems
host: 39.105.××××
port: 5672
消息监听并进行消费(短信,Email,SMS三个消费者)
短信
package com.yhd.rabbitmq.service.fanout;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* @author 袁浩东
* @description
* @date 2021/7/20 22:15
*/
//spring 容器托管`在这里插入代码片`
@Component
//声明消费者,并绑定队列
@RabbitListener(queues = "duanxin.fanout.queue")
public class FanoutDuanxinConsumer {
@RabbitHandler //回调,message就是消息内容
public void reviceMessage(String message){
System.out.println("duanxin接收到了的订单信息是:"+message);
}
}
package com.yhd.rabbitmq.service.fanout;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* @author 袁浩东
* @description
* @date 2021/7/20 22:17
*/
@Component
@RabbitListener(queues = "email.fanout.queue")
public class FanoutEmailConsumer {
@RabbitHandler
public void reviceMessage(String message){
System.out.println("email接收到了的订单信息是:"+message);
}
}
SMS
package com.yhd.rabbitmq.service.fanout;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* @author 袁浩东
* @description
* @date 2021/7/20 22:17
*/
@Component
@RabbitListener(queues = "sms.fanout.queue")
public class FanoutSMSConsumer {
@RabbitHandler
public void reviceMessage(String message){
System.out.println("sms接收到了的订单信息是:"+message);
}
}
运行结果
消息队列中的消息已经被消费掉了
总结
生产者:使用service完成消息发送,使用config配置类完成队列和交换机的绑定,使用测试类进行测试
消费者:声明为消费者,进行队列绑定,消息回调
步骤:
1.生产者声明交换机
2.生产者声明队列
3.生产者完成交换机与队列的绑定
4.消费者通过队列与生产者建立联系
Direct 模式(交换机与队列的绑定在消费者端)
Direct模式与Finout模式类似,仅多了一个路由key的绑定。故直接上代码
生产者
service
//模拟用户下单
public void makeOrderDirect(String userid,String productid,int num){
//1.根据商品id查询库存是否足够
//2.保存订单
String orderId = UUID.randomUUID().toString();
System.out.println("订单生产成功:"+orderId);
//3.通过MQ来完成消息的分发
//参数1:交换机 参数2:路由key/queue队列名称 参数3:消息内容
String exchangeName = "direct_order_exchange";
String routingKey = "";
rabbitTemplate.convertAndSend(exchangeName,"email",orderId);
rabbitTemplate.convertAndSend(exchangeName,"duanxin",orderId);
}
测试类
@Test
void testorderDerect() {
orderService.makeOrderDirect("1","1",12);
}
消费者
交换机与队列的绑定(配置类)
package com.yhd.rabbitmq.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author 袁浩东
* @description
* @date 2021/7/20 22:53
*/
@Configuration
public class RabbitMqConfiguration {
//1.声明注册direct模式的交换机
@Bean
public DirectExchange directExchange(){
return new DirectExchange("direct_order_exchange",true,false);
}
//2.声明队列
@Bean
public Queue directSmsQueue(){
return new Queue("sms.direct.queue",true);
}
@Bean
public Queue driectDuanxinQueue(){
return new Queue("duanxin.direct.queue",true);
}
@Bean
public Queue driectEmailQueue(){
return new Queue("email.direct.queue",true);
}
//3.完成绑定关系
@Bean
public Binding smsBingding(){
return BindingBuilder.bind(directSmsQueue()).to(directExchange()).with("sms");
}
@Bean
public Binding duanxinBingding(){
return BindingBuilder.bind(driectDuanxinQueue()).to(directExchange()).with("duanxin");
}
@Bean
public Binding emailBingding(){
return BindingBuilder.bind(driectEmailQueue()).to(directExchange()).with("email");
}
}
消息监听与消费(短信,Email,SMS)
短信
package com.yhd.rabbitmq.service.driect;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* @author 袁浩东
* @description
* @date 2021/7/20 22:15
*/
//spring 容器托管
@Component
//声明消费者,并绑定队列
@RabbitListener(queues = "duanxin.direct.queue")
public class DriectDuanxinConsumer {
@RabbitHandler //回调,message就是消息内容
public void reviceMessage(String message){
System.out.println("duanxin接收到了的订单信息是:"+message);
}
}
package com.yhd.rabbitmq.service.driect;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* @author 袁浩东
* @description
* @date 2021/7/20 22:17
*/
@Component
@RabbitListener(queues = "email.direct.queue")
public class DriectEmailConsumer {
@RabbitHandler
public void reviceMessage(String message){
System.out.println("email接收到了的订单信息是:"+message);
}
}
SMS
package com.yhd.rabbitmq.service.driect;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* @author 袁浩东
* @description
* @date 2021/7/20 22:17
*/
@Component
@RabbitListener(queues = "sms.direct.queue")
public class DriectSMSConsumer {
@RabbitHandler
public void reviceMessage(String message){
System.out.println("sms接收到了的订单信息是:"+message);
}
}
运行结果
总结
在进行交换机与队列绑定的时候要进行路由key的设置
Topic 模式(注解绑定)
Topic模式与Direct模式类似,都需要绑定路由key从而完成消息的匹配与转发,不同之处在于,Topic模式使用通配符模式,更灵活。
生产者
service
//--------------------------topic--------------------------------
//模拟用户下单
public void makeOrderTopic(String userid,String productid,int num){
//1.根据商品id查询库存是否足够
//2.保存订单
String orderId = UUID.randomUUID().toString();
System.out.println("订单生产成功:"+orderId);
//3.通过MQ来完成消息的分发
//参数1:交换机 参数2:路由key/queue队列名称 参数3:消息内容
String exchangeName = "topic_order_exchange";
String routingKey = "com.duanxin";
rabbitTemplate.convertAndSend(exchangeName,routingKey,orderId);
}
测试类
@Test
void testorderTopic() {
orderService.makeOrderTopic("1","1",12);
}
消费者(短信,Email,SMS三个消费者)
短信
package com.yhd.rabbitmq.service.topic;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
/**
* @author 袁浩东
* @description
* @date 2021/7/20 22:15
*/
//spring 容器托管
@Component
//声明消费者,并绑定队列
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "duanxin.topic.queue",durable = "true",autoDelete = "false"),
exchange = @Exchange(value = "topic_order_exchange",type = ExchangeTypes.TOPIC),
key = "#.duanxin.#"
) )
public class TopicDuanxinConsumer {
@RabbitHandler //回调,message就是消息内容
public void reviceMessage(String message){
System.out.println("duanxin接收到了的订单信息是:"+message);
}
}
package com.yhd.rabbitmq.service.topic;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
/**
* @author 袁浩东
* @description
* @date 2021/7/20 22:17
*/
@Component
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "email.topic.queue",durable = "true",autoDelete = "false"),
exchange = @Exchange(value = "topic_order_exchange",type = ExchangeTypes.TOPIC),
key = "#.email.#"
))
public class TopciEmailConsumer {
@RabbitHandler
public void reviceMessage(String message){
System.out.println("email接收到了的订单信息是:"+message);
}
}
SMS
package com.yhd.rabbitmq.service.topic;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
/**
* @author 袁浩东
* @description
* @date 2021/7/20 22:17
*/
@Component
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "sms.topic.queue",durable = "true",autoDelete = "false"),
exchange = @Exchange(value = "topic_order_exchange",type = ExchangeTypes.TOPIC),
key = "com.#"
))
public class TopicSMSConsumer {
@RabbitHandler
public void reviceMessage(String message){
System.out.println("sms接收到了的订单信息是:"+message);
}
}
运行结果
消费者启动后
生产者启动后
总结
使用注解进行交换机和队列的绑定