需求描述
因业务需要,我需要在spring boot开发的工程中添加RabbitMq来保证与其他模块工程的异步通信。但加入了Spring boot的starter后为保证消息可靠发送等还需要做一系列的配置操作,以消息可重发,我还需要编写相应逻辑代码。一个工程中倒无所谓,但是多个项目中都需要使用到RabbitMq时大量的重复逻辑就出现了,为了解决这个问题,急需将类似操作进行整理和规范化。
需求分析
查看大量操作逻辑,主要需要的操作无非以下几个:
- 自动注册配置交换机(因我主要使用的是Topic交换机,以下逻辑以Topic交换机为准,后续将会补充其他类型的交换机)
- 使用Redis进行消息缓存
- 支持对Queue进行添加和删除
- 支持对Queue和交换机进行绑定
- 支持对Topic交换机进行消息发送
- 支持可靠消息发送,并自动处理失败消息重推
- 在spring启动时自动完成一系列配置,在使用相应方法时不进行依赖注入(Autowire)
需求实现
为满足以上需求,首先需要在现有Spring boot 工程中添加以下依赖
- spring-boot-starter-amqp
- spring-boot-starter-data-redis
- lombok(非必须)
pom文件中添加:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--lombok非必须依赖,只是方便一些getter、setter、log等操作-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
接下来需要在相应启动环境的application.yml中添加配置参数,为了保证与官方相似,我自定义了一部分参数,在后面的配置文件中使用:
spring:
rabbitmq:
host: 0.0.0.0
port: 5672
username: username
password: password
# 开启rabbitMq消息确认机制
publisher-confirms: true
publisher-returns: true
# 自定义参数 指定交换机名称
exchange-name: MESSAGE_EXCHANGE
# 自定义参数 指定交换机类型,此处类型与rabbitMq官方保持一致
exchange-type: topic
# 自定义参数 指定发送的消息在redis中暂存时的key值
message-buffer-tag: message_buffer_tag
redis:
host: 0.0.0.0
port: 8085
password: password
jedis:
pool:
max-active: 1024
max-idle: 200
max-wait: 1000
配置了以上参数后,rabbitMq和redis已基本可用,但为了打成目的,我需要在Spring启动时能够做到对相应配置进行自动化处理,因此需要编写一个公共初始化配置类来完成对交换机的创建、rabbitTemplate的可靠发送配置、redis相应配置。
为了满足需要,编写InitConfig配置类:
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
/**
* @Auth Arabira
* @Date 2019/7/4 14:52
* @Description 初始化配置类
*/
@Slf4j
@Configuration
public class InitConfig {
// 交换机名称,若不存在将会使用默认名称
@Value("${spring.rabbitmq.exchange-name:cloud-pay}")
private String settedExchangeName;
// 交换机类型,若不存在将创建topic类型交换机
@Value("${spring.rabbitmq.exchange-type:topic}")
private String exchangeType;
// 存储redis的消息标记,若不存在将使用默认标记
@Value("${spring.rabbitmq.message-buffer-tag:message-tag}")
private String messageBufferTag;
/**
* @Author arabira
* @Description 自定义redis工具类,指定初始化方法为initialize
* 因保密原因不方便公开工具类,请按需求自主编写
* @Method redisUtil
* @Param []
* @Return com.somecompany.common.RedisUtil
* @Time 2019/8/7 11:38
*/
@Bean(initMethod = "initialize")
public RedisUtil redisUtil () {
return new RedisUtil();
}
/**
* @Author arabira
* @Description rabbitAdmin类创建,此处使用@DependsOn来指定该类只有在
* connectionFactory类存在时才可以创建
* @Method rabbitAdmin
* @Param [connectionFactory]
* @Return org.springframework.amqp.rabbit.core.RabbitAdmin
* @Time 2019/8/7 11:39
*/
@Bean
@DependsOn("connectionFactory")