RabbitMQ配置从数据库获取,并可动态创建虚拟机和队列并绑定

首先建三张表并对应三个实体文件:rabbitmq_connect,rabbitmq_exchange, rabbitmq_queue;另外rabbitmq_producer_message_record(记录表可选)

#rabbitmq连接信息
CREATE TABLE `rabbitmq_connect` (
  `id` bigint NOT NULL,
  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '连接名',
  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '描述',
  `username` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户名',
  `password` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '密码',
  `host` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主机',
  `port` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '端口',
  `virtualHost` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '虚拟主机',
  `is_delete` tinyint(1) NOT NULL COMMENT '是否删除: 0 否 1 是',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='rabbtimq 连接配置信息';

#rabbitmq交换机信息
CREATE TABLE `rabbitmq_exchange` (
  `id` bigint NOT NULL,
  `connect_id` bigint NOT NULL COMMENT '连接配置id',
  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '交换机名称',
  `remark` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '交换机备注',
  `type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '交换机类型 CUSTOM(自定义交换机) DIRECT(直连) TOPIC(通配符)HEADERS(消息头) 5 FANOUT(广播)',
  `customType` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '自定义交换机名称',
  `arguments` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '自定义交换机参数',
  `is_delete` tinyint(1) NOT NULL COMMENT '是否删除 0 否 1 是',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='rabbitmq 交换机信息';

#rabbitmq队列信息
CREATE TABLE `rabbitmq_queue` (
  `id` bigint NOT NULL,
  `exchang_id` bigint NOT NULL COMMENT '交换机id',
  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '队列名称',
  `remark` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '描述',
  `routing_key` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '队列路由键',
  `durable` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否为持久队列(该队列将在服务器重启后保留下来):0 否 1 是 (默认是)',
  `exclusive` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否为排它队列:0 否 1 是 (默认否)',
  `auto_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '如果队列为空是否删除(如果服务器在不使用队列时是否删除队列):0 否 1 是 (默认否)',
  `where_all` tinyint(1) NOT NULL DEFAULT '1' COMMENT '头队列是否全部匹配:0 否 1 是 (默认是)',
  `args` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '参数',
  `headers` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '消息头',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `is_delete` tinyint(1) NOT NULL COMMENT '是否删除 0 否 1 是',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='rabbitmq 队列表';

#rabbitmq生产记录
CREATE TABLE `rabbitmq_producer_message_record` (
  `id` bigint NOT NULL,
  `msg_id` int DEFAULT NULL COMMENT '消息id',
  `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '内容',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `producer_id` bigint DEFAULT NULL COMMENT '生产者id',
  `status` tinyint(1) DEFAULT NULL COMMENT '状态:-1 未接收 0 丢失 1 成功',
  PRIMARY KEY (`id`),
  KEY `record_id_status_index` (`id`,`status`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='rabbitmq生产者消息记录表';

工程中引入包:


   org.springframework.boot
   spring-boot-starter-amqp

实体类:

/**
* 描述:rabbtimq 连接配置信息模型
* @author Administrator
* @date 2021/11/04
*/
@Data
@ToString(callSuper = true)
@TableName("rabbitmq_connect")
public class RabbitmqConnect implements Serializable {
        /****/
        @TableId("id")
        private Long id;
    
        /***连接名*/
        @TableField("name")
         private String name;
    
        /***描述*/
        @TableField("remark")
         private String remark;
    
        /***用户名*/
        @TableField("username")
         private String username;
    
        /***密码*/
        @TableField("password")
         private String password;
    
        /***主机*/
        @TableField("host")
         private String host;
    
        /***端口*/
        @TableField("port")
         private String port;
    
        /***虚拟主机*/
        @TableField("virtualHost")
         private String virtualHost;
    
        /***是否删除: 0 否 1 是*/
        @TableField("is_delete")
        private Boolean isDelete;
    
        /***创建时间*/
        @TableField("create_time")
        @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8")
        private Date createTime;

        /** 交换机集合 */
        @TableField(exist = false)
        private List rabbitmqExchanges = Lists.newArrayList();

}


/**
* 描述:rabbitmq 交换机信息模型
* @author Administrator
* @date 2021/11/04
*/
@Data
@ToString(callSuper = true)
@TableName("rabbitmq_exchange")
public class RabbitmqExchange implements Serializable {
        /****/
        @TableId("id")
        private Long id;
    
        /***连接配置id*/
        @TableField("connect_id")
        private Long connectId;
    
        /***交换机名称*/
        @TableField("name")
         private String name;
    
        /***交换机备注*/
        @TableField("remark")
         private String remark;
    
        /***交换机类型 CUSTOM(自定义交换机) DIRECT(直连) TOPIC(通配符)HEADERS(消息头) 5 FANOUT(广播)*/
        @TableField("type")
         private RabbitmqExchangeTypeEnum type;
    
        /***自定义交换机名称*/
        @TableField("customType")
         private String customType;
    
        /***自定义交换机参数*/
        @TableField("arguments")
         private String arguments;
    
        /***是否删除 0 否 1 是*/
        @TableField("is_delete")
        private Boolean isDelete;
    
        /***创建时间*/
        @TableField("create_time")
        @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8")
        private Date createTime;

        /***队列集合*/
        @TableField(exist = false)
        private List rabbitmqQueues = Lists.newArrayList();
}

/**
* 描述:rabbitmq 队列表模型
* @author Administrator
* @date 2021/11/04
*/
@Data
@ToString(callSuper = true)
@TableName("rabbitmq_queue")
public class RabbitmqQueue implements Serializable {
        /****/
        @TableId("id")
        private Long id;
    
        /***交换机id*/
        @TableField("exchang_id")
        private Long exchangId;
    
        /***队列名称*/
        @TableField("name")
         private String name;
    
        /***描述*/
        @TableField("remark")
         private String remark;
    
        /***队列路由键*/
        @TableField("routing_key")
         private String routingKey;
    
        /***是否为持久队列(该队列将在服务器重启后保留下来):0 否 1 是 (默认是)*/
        @TableField("durable")
        private Boolean durable;
    
        /***是否为排它队列:0 否 1 是 (默认否)*/
        @TableField("exclusive")
        private Boolean exclusive;
    
        /***如果队列为空是否删除(如果服务器在不使用队列时是否删除队列):0 否 1 是 (默认否)*/
        @TableField("auto_delete")
        private Boolean autoDelete;
    
        /***头队列是否全部匹配:0 否 1 是 (默认是)*/
        @TableField("where_all")
        private Boolean whereAll;
    
        /***参数*/
        @TableField("args")
         private String args;
    
        /***消息头*/
        @TableField("headers")
         private String headers;
    
        /***创建时间*/
        @TableField("create_time")
        @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8")
        private Date createTime;
    
        /***是否删除 0 否 1 是*/
        @TableField("is_delete")
        private Boolean isDelete;
}


/**
* 描述:rabbitmq生产者消息记录表模型
* @author Administrator
* @date 2021/11/10
*/
@Data
@ToString(callSuper = true)
@TableName("rabbitmq_producer_message_record")
public class RabbitmqProducerMessageRecord implements Serializable {
        /****/
        @TableId("id")
        private Long id;
    
        /***消息id*/
        @TableField("msg_id")
        private Integer msgId;
    
        /***内容*/
        @TableField("content")
         private String content;
    
        /***创建时间*/
        @TableField("create_time")
        @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8")
        private Date createTime;
    
        /***生产者id*/
        @TableField("producer_id")
        private Long producerId;
    
        /***状态:0 丢失 1 成功*/
        @TableField("status")
        private Integer status;
}

导包:

        
            org.springframework.boot
            spring-boot-starter-amqp
        

配置类:

/**
 * @author Administrator
 * @date 2021/11/04
 */
@Configuration
@RequiredArgsConstructor
@Slf4j
public class MultiRabbitMqConfig {

    private final DefaultListableBeanFactory defaultListableBeanFactory;

    // private final AutowireCapableBeanFactory autowireCapableBeanFactory;

    private List rabbitmqConnectList = Lists.newArrayList();

    @Autowired
    private RabbitmqConnectMapper rabbitmqConnectMapper;

    @Autowired
    private RabbitmqExchangeMapper rabbitmqExchangeMapper;

    @Autowired
    private RabbitmqQueueMapper rabbitmqQueueMapper;

    @Autowired
    private RabbitmqProducerMessageRecordMapper rabbitmqProducerMessageRecordMapper;

    @PostConstruct
    public void init() {
        initData();
        initRabbitmq();
    }

    //将需要的各种Bean注入到spring容器中, 便于管理使用
    public void initRabbitmq() {
        // 注册 rabbitAdmin rabbitTemplate
        rabbitmqConnectList.forEach(c -> {
            AbstractBeanDefinition beanDefinition =
                BeanDefinitionBuilder.genericBeanDefinition(CachingConnectionFactory.class)
                    .addPropertyValue("cacheMode", CachingConnectionFactory.CacheMode.CHANNEL)
                    .addPropertyValue("host", c.getHost())
                    .addPropertyValue("port", c.getPort())
                    .addPropertyValue("username", c.getUsername())
                    .addPropertyValue("password", c.getPassword())
                    .addPropertyValue("virtualHost", c.getVirtualHost()).getBeanDefinition();

            String connectionFactoryName = RabbitmqContant.CONNECTION_FACTORY + c.getName();
            defaultListableBeanFactory.registerBeanDefinition(connectionFactoryName, beanDefinition);
            CachingConnectionFactory connectionFactory =
                defaultListableBeanFactory.getBean(connectionFactoryName, CachingConnectionFactory.class);
            connectionFactory.setPublisherReturns(true);
            connectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);

            // 注册 rabbitAdmin
            String rabbitAdminName = RabbitmqContant.RABBIT_ADMIN + c.getName();
            AbstractBeanDefinition rabbitAdminBeanDefinition =
                BeanDefinitionBuilder.genericBeanDefinition(RabbitAdmin.class).addConstructorArgValue(connectionFactory)
                    .addPropertyValue("autoStartup", true).getBeanDefinition();
            defaultListableBeanFactory.registerBeanDefinition(rabbitAdminName, rabbitAdminBeanDefinition);

            RabbitAdmin rabbitAdmin = defaultListableBeanFactory.getBean(rabbitAdminName, RabbitAdmin.class);
            log.info("register rabbitAdmin:[{}]", rabbitAdmin);

            // 注册 rabbitTemplate
            RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);

            rabbitTemplate.setMandatory(true);
            rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
                log.info("消息发送成功:correlationData({}),ack({}),cause({})", correlationData, ack, cause);
                rabbitmqProducerMessageRecordMapper.updateStatus(Long.valueOf(correlationData.getId()), 0);
            });

            // rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
            // log.info("消息丢失:exchange({}),route({}),replyCode({}),replyText({}),message:{}", exchange, routingKey,
            // replyCode, replyText, message);
            // });

            String rabbitTemplateName = RabbitmqContant.RABBIT_TEMPLATE + c.getName();
            defaultListableBeanFactory.registerSingleton(rabbitTemplateName, rabbitTemplate);
            log.info("register rabbitTemplate:[{}]", rabbitTemplate);

//            //如果从配置中创建需要加上这段
//            // 创建交换机
//            c.getRabbitmqExchanges().forEach(e -> {
//                // 声明交换机
//                Exchange exchange = null;
//                switch (e.getType()) {
//                    case DIRECT:
//                        exchange = new DirectExchange(e.getName());
//                        break;
//                    case TOPIC:
//                        exchange = new TopicExchange(e.getName());
//                        break;
//                    case HEADERS:
//                        exchange = new HeadersExchange(e.getName());
//                        break;
//                    case FANOUT:
//                        exchange = new FanoutExchange(e.getName());
//                        break;
//                    case CUSTOM:
//                        exchange = new CustomExchange(e.getName(), e.getCustomType(), true, false,
//                            JSON.parseObject(e.getArguments()));
//                        break;
//                    default:
//                        break;
//                }
//
//                rabbitAdmin.declareExchange(exchange);
//
//                log.debug("create exchange [{}] success!", e.getName());
//
//                // 创建并绑定队列
//                e.getRabbitmqQueues().forEach(q -> {
//                    Queue queue = new Queue(q.getName(), q.getDurable(), q.getExclusive(), q.getAutoDelete(),
//                        JSON.parseObject(q.getArgs()));
//
//                    log.debug("queue [{}] binding exchange [{}] success!", q.getName(), e.getName());
//
//                    rabbitAdmin.declareQueue(queue);
//                });
//            });
        });
    }

    public void initData() {
        List rabbitmqConnects =
            rabbitmqConnectMapper.selectList(new QueryWrapper().eq("is_delete", 0));
        List rabbitmqExchanges =
            rabbitmqExchangeMapper.selectList(new QueryWrapper().eq("is_delete", 0));
        List rabbitmqQueues =
            rabbitmqQueueMapper.selectList(new QueryWrapper().eq("is_delete", 0));

        Map> e_q_map =
            rabbitmqQueues.stream().collect(Collectors.groupingBy(q -> q.getExchangId()));
        rabbitmqExchanges.stream().forEach(e -> {
            if (e_q_map.containsKey(e.getId())) {
                e.getRabbitmqQueues().addAll(e_q_map.get(e.getId()));
            }
        });
        Map> c_e_map =
            rabbitmqExchanges.stream().collect(Collectors.groupingBy(q -> q.getConnectId()));
        rabbitmqConnects.stream().forEach(c -> {
            if (c_e_map.containsKey(c.getId())) {
                c.getRabbitmqExchanges().addAll(c_e_map.get(c.getId()));
            }
        });
        rabbitmqConnectList = rabbitmqConnects;
    }

    public  T getBean(String name, Class clz) throws BeansException {
        T result = (T)defaultListableBeanFactory.getBean(name, clz);
        return result;
    }

    public List getRegisterRabbitmq() {
        return rabbitmqConnectList;
    }

}

public class RabbitmqContant {

    public final static String CONNECTION_FACTORY = "CONNECTION_FACTORY_";

    public final static String RABBIT_ADMIN = "RABBIT_ADMIN_";

    public final static String RABBIT_TEMPLATE = "RABBIT_TEMPLATE_";

    public final static String DASH = "_";

}

使用逻辑:

/**
 * 描述:rabbtimq 业务使用模块
 * 
 * @author Administrator
 * @date 2021/11/04
 */
@Api(value = "/rabbitmqUse", tags = "rabbtimq 业务使用模块")
@RestController
@RequestMapping("/rabbitmqUse")
@Slf4j
public class RabbitmqUseController {

    @Autowired
    private MultiRabbitMqConfig multiRabbitMqConfig;

    @Autowired
    private RabbitmqProducerMessageRecordService rabbiemqProducerMessageRecordService;

    /**
     * 查询所有
     */
    @ApiOperation("rabbtimq 传送数据到队列")
    @ApiParam("send")
    @PostMapping("/send")
    public BaseResponse send(@RequestBody RabbitmqUseRequest request) {
        List registerRabbitmq = multiRabbitMqConfig.getRegisterRabbitmq();

        RabbitmqProducerMessageRecord record = new RabbitmqProducerMessageRecord();
        long id = IdWorker.getId();
        record.setId(id);
        record.setCreateTime(new Date());
        record.setContent(request.getData());
        record.setStatus(-1);

        try {
            for (RabbitmqConnect c : registerRabbitmq) {
                for (RabbitmqExchange e : c.getRabbitmqExchanges()) {
                    for (RabbitmqQueue q : e.getRabbitmqQueues()) {
                        if (q.getId().equals(request.getQueueId())) {

                            String msgId = String.valueOf(id);

                            record.setProducerId(q.getId());

                            RabbitTemplate rabbitTemplate = multiRabbitMqConfig
                                .getBean(RabbitmqContant.RABBIT_TEMPLATE + c.getName(), RabbitTemplate.class);
//                            rabbitTemplate.convertAndSend(e.getName(), q.getRoutingKey(), request.getData());

                            Message message = MessageBuilder.withBody(request.getData().getBytes()).setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN).setCorrelationId(msgId).build();

                            CorrelationData correlationData = new CorrelationData(msgId);

                            rabbitTemplate.send(e.getName(), q.getRoutingKey(), message, correlationData);

                            record.setStatus(0);

                            return ResponseUtils.success();
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            rabbiemqProducerMessageRecordService.save(record);
        }

        log.info("消息发送失败:{}","队列不存在");
        return ResponseUtils.errorMsg("消息发送失败,队列不存在");
    }

最后启动类加上注解:

@SpringBootApplication(exclude = {RabbitAutoConfiguration.class})

声明:本文借鉴和引用

SpringBoot整合多个RabbitMQ_huan的学习记录-CSDN博客

你可能感兴趣的:(解决方案,rabbitmq,数据库,java,消息队列,spring)