在SpringBoot中使用RabbitMQ
1. 添加pom依赖
1 <dependency> 2 <groupId>org.projectlombok</groupId> 3 <artifactId>lombok</artifactId> 4 <version>1.16.22</version> 5 </dependency> 6 7 8 <dependency> 9 <groupId>org.springframework.boot</groupId> 10 <artifactId>spring-boot-starter-amqp</artifactId> 11 <version>2.1.8.RELEASE</version> 12 </dependency> 13 14 <dependency> 15 <groupId>org.springframework.boot</groupId> 16 <artifactId>spring-boot-test</artifactId> 17 <version>2.2.6.RELEASE</version> 18 </dependency> 19 <dependency> 20 <groupId>junit</groupId> 21 <artifactId>junit</artifactId> 22 <version>4.12</version> 23 </dependency> 24 <dependency> 25 <groupId>org.springframework</groupId> 26 <artifactId>spring-test</artifactId> 27 <version>5.2.5.RELEASE</version> 28 </dependency>
2. 定义消息队列的一些常量
1 package com.devin.order.config; 2 3 /** 4 * @author Devin Zhang 5 * @className RabbitConstants 6 * @description TODO 7 * @date 2020/4/25 10:11 8 */ 9 10 public class RabbitConstants { 11 12 /** 13 * 分列模式 14 */ 15 public final static String FANOUT_MODE_QUEUE = "fanout.mode"; 16 17 /** 18 * 日志打印队列 19 */ 20 public final static String QUEUE_LOG_PRINT = "queue.log.recode"; 21 22 /** 23 * 主题模式 24 */ 25 public final static String TOPIC_MODE_QUEUE = "topic.mode"; 26 27 /** 28 * 主题模式 29 */ 30 public final static String TOPIC_ROUTING_KEY = "topic.*"; 31 32 }
3. 设置RabbitMQ的配置类
1 package com.devin.order.config; 2 3 /** 4 * @author Devin Zhang 5 * @className RabbitMqConfig 6 * @description TODO 7 * @date 2020/4/25 10:12 8 */ 9 10 11 import lombok.extern.slf4j.Slf4j; 12 import org.springframework.amqp.core.*; 13 import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; 14 import org.springframework.amqp.rabbit.core.RabbitTemplate; 15 import org.springframework.context.annotation.Bean; 16 import org.springframework.context.annotation.Configuration; 17 18 @Slf4j 19 @Configuration 20 public class RabbitMqConfig { 21 22 @Bean 23 public RabbitTemplate rabbitTemplate(CachingConnectionFactory connectionFactory) { 24 connectionFactory.setPublisherConfirms(true); 25 connectionFactory.setPublisherReturns(true); 26 RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); 27 rabbitTemplate.setMandatory(true); 28 rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> log.info("消息发送成功:correlationData[{}],ack[{}],cause[{}]", correlationData, ack, cause)); 29 rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> log.info("消息丢失:exchange[{}],route[{}],replyCode[{}],replyText[{}],message:{}", exchange, routingKey, replyCode, replyText, message)); 30 return rabbitTemplate; 31 } 32 33 /** 34 * 日志打印队列 35 */ 36 @Bean 37 public Queue logPrintQueue() { 38 return new Queue(RabbitConstants.QUEUE_LOG_PRINT); 39 } 40 41 /** 42 * 分列模式队列 43 */ 44 @Bean 45 public FanoutExchange fanoutExchange() { 46 return new FanoutExchange(RabbitConstants.FANOUT_MODE_QUEUE); 47 } 48 49 /** 50 * 分列模式绑定队列 51 * 52 * @param logPrintQueue 绑定队列 53 * @param fanoutExchange 分列模式交换器 54 */ 55 @Bean 56 public Binding fanoutBinding(Queue logPrintQueue, FanoutExchange fanoutExchange) { 57 return BindingBuilder.bind(logPrintQueue).to(fanoutExchange); 58 } 59 60 /** 61 * 主题队列 62 */ 63 @Bean 64 public Queue topicQueue() { 65 return new Queue(RabbitConstants.TOPIC_ROUTING_KEY); 66 } 67 68 /** 69 * 主题模式队列 70 * <li>路由格式必须以 . 分隔,比如 user.email 或者 user.aaa.email</li> 71 * <li>通配符 * ,代表一个占位符,或者说一个单词,比如路由为 user.*,那么 user.email 可以匹配,但是 user.aaa.email 就匹配不了</li> 72 * <li>通配符 # ,代表一个或多个占位符,或者说一个或多个单词,比如路由为 user.#,那么 user.email 可以匹配,user.aaa.email 也可以匹配</li> 73 */ 74 @Bean 75 public TopicExchange topicExchange() { 76 return new TopicExchange(RabbitConstants.TOPIC_MODE_QUEUE); 77 } 78 79 /** 80 * 主题模式绑定队列2 81 * 82 * @param topicQueue 主题队列 83 * @param topicExchange 主题模式交换器 84 */ 85 @Bean 86 public Binding topicBinding(Queue topicQueue, TopicExchange topicExchange) { 87 return BindingBuilder.bind(topicQueue).to(topicExchange).with(RabbitConstants.TOPIC_ROUTING_KEY); 88 } 89 90 }
4. 消息的处理类
1 package com.devin.order.Service; 2 3 /** 4 * 【消息队列处理器】 5 * 6 * @author Devin Zhang 7 * @className RabbitMqHandler 8 * @description TODO 9 * @date 2020/4/25 10:54 10 */ 11 12 13 import com.devin.order.config.RabbitConstants; 14 import com.devin.order.mapper.OrderMapper; 15 import com.devin.order.model.Order; 16 import com.devin.order.util.RedisClient; 17 import lombok.extern.slf4j.Slf4j; 18 import org.springframework.amqp.rabbit.annotation.RabbitListener; 19 import org.springframework.stereotype.Component; 20 21 import javax.annotation.Resource; 22 23 24 @Slf4j 25 @Component 26 public class RabbitMqHandler { 27 28 @Resource 29 private RedisClient redisClient; 30 31 @Resource 32 private OrderMapper orderMapper; 33 34 /** 35 * 日志打印处理handler 36 * 37 * @param message 待处理的消息体 38 */ 39 @RabbitListener(queues = RabbitConstants.QUEUE_LOG_PRINT) 40 public void queueLogPrintHandler(String message) { 41 log.info("接收到操作日志记录消息:[{}]", message); 42 } 43 44 /** 45 * 主题模式处理handler 46 * 47 * @param message 待处理的消息体 48 */ 49 @RabbitListener(queues = RabbitConstants.TOPIC_ROUTING_KEY) 50 public void queueTopicHandler(String message) { 51 log.info("主题模式处理器,接收消息:[{}]", message); 52 53 //todo 逻辑处理 54 55 56 57 } 58 59 }
5. 发送消息测试
1 import com.devin.order.OrderGrabbingApplication; 2 import com.devin.order.config.RabbitConstants; 3 import lombok.extern.slf4j.Slf4j; 4 import org.junit.Test; 5 import org.junit.runner.RunWith; 6 import org.springframework.amqp.rabbit.core.RabbitTemplate; 7 import org.springframework.boot.test.context.SpringBootTest; 8 import org.springframework.test.context.junit4.SpringRunner; 9 10 import javax.annotation.Resource; 11 12 /** 13 * @author Devin Zhang 14 * @className MqSendTest 15 * @description TODO 16 * @date 2020/4/28 16:49 17 */ 18 @RunWith(SpringRunner.class) 19 @SpringBootTest(classes = {OrderGrabbingApplication.class})// 指定启动类 20 @Slf4j 21 public class MqSendTest { 22 23 @Resource 24 private RabbitTemplate rabbitTemplate; 25 26 27 @Test 28 public void mqSend(){ 29 String message = "topic message"; 30 rabbitTemplate.convertAndSend(RabbitConstants.TOPIC_MODE_QUEUE, "topic.queue", message); 31 log.info("消息发送成功:[{}]", message); 32 } 33 }