springboot 整合rabbitmq 动态生成交换机、队列
1.引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2.创建实体类
@Data
public class RabbitModuleInfoDTO {
private String routingKey;
private Queue queue;
private Exchange exchange;
@Data
public static class Exchange {
private RabbitExchangeTypeEnum type = RabbitExchangeTypeEnum.DIRECT;
private String name;
private boolean durable = true;
private boolean autoDelete = false;
private Map<String, Object> arguments;
}
@Data
public static class Queue {
private String name;
private boolean durable = true;
private boolean exclusive = false;
private boolean autoDelete = false;
private String deadLetterExchange;
private String deadLetterRoutingKey;
private Map<String, Object> arguments;
}
}
3.rabbitmq队列初始化
@Slf4j
public class RabbitModuleInitializer implements SmartInitializingSingleton {
private AmqpAdmin amqpAdmin;
private List<RabbitModuleInfoDTO> modules;
public RabbitModuleInitializer(AmqpAdmin amqpAdmin, List<RabbitModuleInfoDTO> modules) {
this.amqpAdmin = amqpAdmin;
this.modules = modules;
}
@Override
public void afterSingletonsInstantiated() {
log.info("RabbitMQ 根据配置动态创建和绑定队列、交换机");
declareRabbitModule();
}
private void declareRabbitModule() {
if (CollectionUtil.isEmpty(modules)) {
return;
}
for (RabbitModuleInfoDTO rabbitModuleInfo : modules) {
configParamValidate(rabbitModuleInfo);
Queue queue = convertQueue(rabbitModuleInfo.getQueue());
Exchange exchange = convertExchange(rabbitModuleInfo.getExchange());
String routingKey = rabbitModuleInfo.getRoutingKey();
String queueName = rabbitModuleInfo.getQueue().getName();
String exchangeName = rabbitModuleInfo.getExchange().getName();
Binding binding = new Binding(queueName, Binding.DestinationType.QUEUE, exchangeName, routingKey, null);
amqpAdmin.declareQueue(queue);
amqpAdmin.declareExchange(exchange);
amqpAdmin.declareBinding(binding);
}
}
public void configParamValidate(RabbitModuleInfoDTO rabbitModuleInfo) {
String routingKey = rabbitModuleInfo.getRoutingKey();
Assert.isTrue(StrUtil.isNotBlank(routingKey), "RoutingKey 未配置");
Assert.isTrue(rabbitModuleInfo.getExchange() != null, "routingKey:{}未配置exchange", routingKey);
Assert.isTrue(StrUtil.isNotBlank(rabbitModuleInfo.getExchange().getName()), "routingKey:{}未配置exchange的name属性", routingKey);
Assert.isTrue(rabbitModuleInfo.getQueue() != null, "routingKey:{}未配置queue", routingKey);
Assert.isTrue(StrUtil.isNotBlank(rabbitModuleInfo.getQueue().getName()), "routingKey:{}未配置exchange的name属性", routingKey);
}
public Queue convertQueue(RabbitModuleInfoDTO.Queue queue) {
Map<String, Object> arguments = queue.getArguments();
if (arguments != null && arguments.containsKey("x-message-ttl")) {
arguments.put("x-message-ttl", Convert.toLong(arguments.get("x-message-ttl")));
}
if (arguments != null && arguments.containsKey("x-max-priority")) {
arguments.put("x-max-priority", Convert.toLong(arguments.get("x-max-priority")));
}
String deadLetterExchange = queue.getDeadLetterExchange();
String deadLetterRoutingKey = queue.getDeadLetterRoutingKey();
if (StrUtil.isNotBlank(deadLetterExchange) && StrUtil.isNotBlank(deadLetterRoutingKey)) {
if (arguments == null) {
arguments = new HashMap<>(Constants.RABBIT_MQ_INITIAL_CAPACITY);
}
arguments.put("x-dead-letter-exchange", deadLetterExchange);
arguments.put("x-dead-letter-routing-key", deadLetterRoutingKey);
}
return new Queue(queue.getName(), queue.isDurable(), queue.isExclusive(), queue.isAutoDelete(), arguments);
}
public Exchange convertExchange(RabbitModuleInfoDTO.Exchange exchangeInfo) {
AbstractExchange exchange = null;
RabbitExchangeTypeEnum exchangeType = exchangeInfo.getType();
String exchangeName = exchangeInfo.getName();
boolean isDurable = exchangeInfo.isDurable();
boolean isAutoDelete = exchangeInfo.isAutoDelete();
Map<String, Object> arguments = exchangeInfo.getArguments();
switch (exchangeType) {
case DIRECT:// 直连交换机
exchange = new DirectExchange(exchangeName, isDurable, isAutoDelete, arguments);
break;
case TOPIC:
exchange = new TopicExchange(exchangeName, isDurable, isAutoDelete, arguments);
break;
case FANOUT:
exchange = new FanoutExchange(exchangeName, isDurable, isAutoDelete, arguments);
break;
case HEADERS:
exchange = new HeadersExchange(exchangeName, isDurable, isAutoDelete, arguments);
break;
}
return exchange;
}
}
4.rabbitmq配置
@Configuration
@ConfigurationProperties(prefix = "common.tools.rabbitmq")
@Data
public class RabbitConfig {
private List<RabbitModuleInfoDTO> modules;
@Bean
public MessageConverter jackson2MessageConverter() {
return new Jackson2JsonMessageConverter();
}
@Bean
@ConditionalOnMissingBean
public RabbitModuleInitializer rabbitModuleInitializer(AmqpAdmin amqpAdmin) {
return new RabbitModuleInitializer(amqpAdmin, modules);
}
}
5.yml配置
common:
tools:
rabbitmq:
modules:
- routing-key: log.inbound.operation.queue.key
queue:
name: log.inbound.operation.queue
exchange:
name: log.exchange
type: direct
spring:
rabbitmq:
host: 192.168.16.128
port: 5672
username: guest
password: guest
6.生产者
@Component
@RequiredArgsConstructor
@Slf4j
public class TestPublisher {
private final RabbitTemplate rabbitTemplate;
public void send(TestMessageDTO testMessageDTO){
rabbitTemplate.convertAndSend("log.exchange", "log.inbound.operation.queue.key", testMessageDTO);
}
}
7.消费者
@Component
public class TestConsumer {
@RabbitListener(queues = "log.inbound.operation.queue")
public void handleInventoryOperation(TestMessageDTO testMessageDTO) {
System.out.println(testMessageDTO);
}
}
8.消息日志显示
![在这里插入图片描述](https://img-blog.csdnimg.cn/a4448299d4e540f8ad10e132f6eb773a.png)