本文创建了三个模块producer 消息生产者模块,consumer消息消费者模块,base 通用模块(base模块中只定义了交换机、队列、路由键的值,方便被另外两个模块调用)
创建base模块,base模块中什么都没有,只有一个Constants的工具类
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
public class Constants {
//直连型交换机
public static final String DEFAULT_DIRECT_EXCHANGE = "defaultDirectExchange";
public static final String DEFAULT_DIRECT_QUEUE = "defaultDirectQueue";
public static final String DEFAULT_DIRECT_ROUTING_KEY = "defaultDirectRoutingKey";
//主题交换机
public static final String DEFAULT_TOPIC_EXCHANGE = "defaultTopicExchange";
public static final String MAN_TOPIC_QUEUE = "manTopicQueue";
public static final String TOTAL_TOPIC_QUEUE = "totalTopicQueue";
public static final String MAN_TOPIC_ROUTING_KEY = "user.man";
public static final String TOTAL_TOPIC_ROUTING_KEY = "user.#";
//扇形交换机
public static final String DEFAULT_FANOUT_EXCHANGE = "defaultFanoutExchange";
public static final String DEFAULT_FANOUT_QUEUE_1 = "defaultFanoutQueue1";
public static final String DEFAULT_FANOUT_QUEUE_2 = "defaultFanoutQueue2";
public static final String DEFAULT_FANOUT_QUEUE_3 = "defaultFanoutQueue3";
}
Direct Exchange 直连型交换机
创建producer消息生产者模块
<dependencies>
<!--引入通用模块-->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>base</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
</dependencies>
server:
port: 8090
spring:
application:
name: producer
rabbitmq:
host: 127.0.0.1 #配置rabbitmq的地址
port: 5672
username: guest
password: guest
这里为了方便理解,我将配置文件按照交换机分开了,首先是直连型交换机配置文件
@Configuration
public class DirectExchangeConfig {
@Bean
public DirectExchange defaultDirectExchange(){
//直连型交换机,持久化消息,不自动删除
return new DirectExchange(Constants.DEFAULT_DIRECT_EXCHANGE,true,false);
}
@Bean
public Queue defaultDirectQueue(){
//声明队列,持久化消息,非独有,不自动删除
return new Queue(Constants.DEFAULT_DIRECT_QUEUE,true,false,false,null);
}
@Bean
public Binding directBiding(){
//将队列和交换机绑定,并设置路由键
return BindingBuilder.bind(defaultDirectQueue()).to(defaultDirectExchange()).with(Constants.DEFAULT_DIRECT_ROUTING_KEY);
}
}
发送消息的入口
@RestController
public class ProducerController {
@Autowired
private RabbitTemplate rabbitTemplate;
@RequestMapping("/direct/sendMsg")
public void directSendMsg(){
String msg = "direct-msg";
//发送消息到交换机,并携带路由键
rabbitTemplate.convertAndSend(Constants.DEFAULT_DIRECT_EXCHANGE,Constants.DEFAULT_DIRECT_ROUTING_KEY,msg);
}
首先启动producer模块,调用接口发送消息,通过控制台可以发现,消息已经被发送成功,但是没有被消费
接下来创建consumer消费者模块
<dependencies>
<!--引入通用模块-->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>base</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
</dependencies>
server:
port: 8080
spring:
application:
name: consumer
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
监听消息
@Component
public class Consumer {
@RabbitListener(queues = Constants.DEFAULT_DIRECT_QUEUE)
public void directConsumer(String msg) throws IOException {
System.out.println("直连型交换机收到消息:"+msg);
}
}
启动服务,消费者会接收到消息
查一下rabbitmq控制台,发现消息被消费了
Topic Exchange 主题交换机
producer模块
创建配置文件,声明交换机、队列,并进行绑定
@Configuration
public class TopicExchangeConfig {
@Bean
public TopicExchange defaultTopicExchange(){
//主题交换机
return new TopicExchange(Constants.DEFAULT_TOPIC_EXCHANGE,true,false);
}
@Bean
public Queue manTopicQueue(){
//只会接受到user.man的数据
return new Queue(Constants.MAN_TOPIC_QUEUE,true,false,false,null);
}
@Bean
public Queue totalTopicQueue(){
//会接收到路由键为user.#的数据
return new Queue(Constants.TOTAL_TOPIC_QUEUE,true,false,false,null);
}
@Bean
public Binding manTopicBinding(){
return BindingBuilder.bind(manTopicQueue()).to(defaultTopicExchange()).with(Constants.MAN_TOPIC_ROUTING_KEY);
}
@Bean
public Binding totalTopicBinding(){
return BindingBuilder.bind(totalTopicQueue()).to(defaultTopicExchange()).with(Constants.TOTAL_TOPIC_ROUTING_KEY);
}
}
消息生产者中添加两个接口
@RequestMapping("/topic/man/sendMsg")
public void topicManSendMsg(){
String msg = "topic-man";
rabbitTemplate.convertAndSend(Constants.DEFAULT_TOPIC_EXCHANGE,Constants.MAN_TOPIC_ROUTING_KEY,msg);
}
@RequestMapping("/topic/total/sendMsg")
public void topicTotalSendMsg(){
String msg = "topic-total";
rabbitTemplate.convertAndSend(Constants.DEFAULT_TOPIC_EXCHANGE,Constants.TOTAL_TOPIC_ROUTING_KEY,msg);
}
consumer模块
添加监听队列
@RabbitListener(queues = Constants.MAN_TOPIC_QUEUE)
public void topicManConsumer(String msg) throws IOException {
System.out.println("主题交换机收到消息-man:"+msg);
}
@RabbitListener(queues = Constants.TOTAL_TOPIC_QUEUE)
public void topicTotalConsumer(String msg) throws IOException {
System.out.println("主题交换机收到消息-total:"+msg);
}
接下来分别启动两个模块,并发送消息(如果启动consumer模块报错,可能是因为rabbitmq还没有创建,交换机和队列的原因,可以先发送消息,再启动consumer模块)
Fanout 扇形交换机
producer模块
创建配置文件,声明交换机、队列,并进行绑定
@Configuration
public class FanoutExchangeConfig {
@Bean
public FanoutExchange defaultFanoutExchange(){
//扇形交换机
return new FanoutExchange(Constants.DEFAULT_FANOUT_EXCHANGE,true,false);
}
@Bean
public Queue defaultFanoutQueue1(){
return new Queue(Constants.DEFAULT_FANOUT_QUEUE_1,true,false,false,null);
}
@Bean
public Queue defaultFanoutQueue2(){
return new Queue(Constants.DEFAULT_FANOUT_QUEUE_2,true,false,false,null);
}
@Bean
public Queue defaultFanoutQueue3(){
return new Queue(Constants.DEFAULT_FANOUT_QUEUE_3,true,false,false,null);
}
@Bean
public Binding fanoutBinding1(){
//不需要配置路由键
return BindingBuilder.bind(defaultFanoutQueue1()).to(defaultFanoutExchange());
}
@Bean
public Binding fanoutBinding2(){
//不需要配置路由键
return BindingBuilder.bind(defaultFanoutQueue2()).to(defaultFanoutExchange());
}
@Bean
public Binding fanoutBinding3(){
//不需要配置路由键
return BindingBuilder.bind(defaultFanoutQueue3()).to(defaultFanoutExchange());
}
}
消息生产者中添加一个接口
@RequestMapping("/fanout/sendMsg")
public void fanoutSendMsg(){
String msg = "fanout-msg";
//不需要发送路由键
rabbitTemplate.convertAndSend(Constants.DEFAULT_FANOUT_EXCHANGE,"",msg);
}
consumer模块
添加监听队列
@RabbitListener(queues = Constants.DEFAULT_FANOUT_QUEUE_1)
public void fanoutConsumer1(String msg) throws IOException {
System.out.println("扇形交换机收到消息-1:"+msg);
}
@RabbitListener(queues = Constants.DEFAULT_FANOUT_QUEUE_2)
public void fanoutConsumer2(String msg) throws IOException {
System.out.println("扇形交换机收到消息-2:"+msg);
}
@RabbitListener(queues = Constants.DEFAULT_FANOUT_QUEUE_3)
public void fanoutConsumer3(String msg) throws IOException {
System.out.println("扇形交换机收到消息-3:"+msg);
}
分别启动两个服务,发送消息,消息接收成功
参考阅读:
Springboot 整合RabbitMq ,用心看完这一篇就够了
项目代码:项目代码
相关阅读:
RabbitMQ入门
RabbitMQ的消息确认机制,消息重试机制
RabbitMQ的死信队列与延时队列