「这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战」
1、前言
本次我为大家介绍下,SpringBoot项目中,Rabbit MQ的开发。下面为大家分享下,对MQ的一些封装(抽取公共代码,可配置、可扩展)。
2、maven引入
在pom文件中引入amqp,这里无需指定版本(跟随SpringBoot的版本)。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
3、增加MQ配置类
将队列、交换机等放入配置文件,交由配置类,在项目启动时,创建交换机、队列。
@Configuration
public class RabbitmqConfig {
@Value("${spring.rabbitmq.username:#{null}}")
private String username;
@Value("${spring.rabbitmq.password:#{null}}")
private String password;
@Value("${spring.rabbitmq.virtual-host}")
private String virtualHost;
@Value("${spring.rabbitmq.publisher-confirms}")
private boolean publisherConfirms;
@Value("${spring.rabbitmq.host}")
private String host;
@Value("${spring.rabbitmq.port}")
private int port;
@Value("#{'${spring.rabbitmq.queuesconfig:null}'.split(',')}")
private List<String> queuesConfig;
@Value("#{'${spring.rabbitmq.directexchangesconfig:null}'.split(',')}")
private List<String> directExchangesConfig;
/**
* 创建MQ连接
*/
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
// 设置用户名
connectionFactory.setUsername(username);
// 设置密码
connectionFactory.setPassword(password);
// 虚拟主机
connectionFactory.setVirtualHost(virtualHost);
// 消息确认
connectionFactory.setPublisherConfirms(publisherConfirms);
// 地址
connectionFactory.setHost(host);
connectionFactory.setPort(port);
return connectionFactory;
}
/**
* 定义rabbitTemplate
* @return
*/
@Bean(name="rabbitTemplate")
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
return template;
}
/**
* 按配置创建所有队列
*/
@Bean
public LinkedList<Queue> builderQueues() {
LinkedList<Queue> queues = new LinkedList<Queue>();
if (null != queuesConfig && queuesConfig.size() > 0 && !"null".equals(queuesConfig.get(0))) {
for (String qConfig : queuesConfig) {
String[] msgs = qConfig.split("/");
if(4 != msgs.length) {
throw new KPromptException("未按格式配置队列,配置信息为["+ qConfig +"]");
}
String qName = msgs[0];
logger.info("正在创建队列[" + qName + "]");
queues.add(createQueue(qName, Boolean.parseBoolean(msgs[1]), Boolean.parseBoolean(msgs[2]) , Boolean.parseBoolean(msgs[3])));
}
}
return queues;
}
/**
* 按配置创建所有直接交换机
*/
@Bean
@DependsOn("builderQueues")
public LinkedList<DirectExchange> builderDirectExchanges() {
LinkedList<DirectExchange> directExchanges = new LinkedList<DirectExchange>();
if (null != directExchangesConfig && directExchangesConfig.size() > 0 && !"null".equals(directExchangesConfig.get(0))) {
for (String dEConfig : directExchangesConfig) {
String[] msgs = dEConfig.split("/");
if(3 != msgs.length) {
throw new KPromptException("未按格式配置直接交换机,配置信息为["+ dEConfig +"]");
}
String dEName = msgs[0];
logger.info("正在创建直接交换机[" + dEName + "]");
directExchanges.add(createDirectExchange(dEName, Boolean.parseBoolean(msgs[1]), Boolean.parseBoolean(msgs[2])));
}
}
return directExchanges;
}
/**
* 创建rabbitAdmin
*/
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
return new RabbitAdmin(connectionFactory);
}
/**
* 根据名称查找队列
* @param name
* @param queues
* @return
*/
public Queue getQueue(String name, LinkedList<Queue> queues) {
for (Queue q : queues) {
if (name.equals(q.getName())) {
return q;
}
}
return null;
}
/**
* 创建队列
* @param queueName
* @param queueDurable
* @param queueExclusive
* @param queueAutoDelete
* @return
*/
public Queue createQueue(String queueName, boolean queueDurable, boolean queueExclusive, boolean queueAutoDelete) {
return new Queue(queueName, queueDurable, queueExclusive, queueAutoDelete);
}
/**
* 创建直接模式交换机
* @param exchangeName
* @param directExchangeDurable
* @param directExchangeAutoDelete
* @return
*/
public DirectExchange createDirectExchange(String exchangeName, boolean directExchangeDurable, boolean directExchangeAutoDelete) {
return new DirectExchange(exchangeName, directExchangeDurable, directExchangeAutoDelete);
}
}
4、示例
向队列发送消息(生产者):
//发送到MQ
rabbitTemplate.convertAndSend(StringUtils.EMPTY,"UserBehaviorMQueue", UserBehavior);
消费者处理消息:
@RabbitHandler
@RabbitListener(queues = "UserBehaviorMQueue", containerFactory = "containerFactory")
public void userBehaviorListener(UserBehavior userBehavior) {
log.info("用户行为记录,接收到的用户行为信息为:{}", userBehavior);
try {
//do something
}catch(Exception e){
//消息处理异常、记录下来消息信息、异常信息、然后将此条消息丢掉,或记录数据库中
log.error("用户行为记录出现异常,接收到的用户行为信息为:{},异常信息为:{}", uerBehavior, e);
}
}
这里,消费者处理消息时,一定要加上try/catch,如果不加的话,出现异常,这条消息会一直不断地发送到消费者这里。好了、本期就先介绍到这里,有什么需要交流的,大家可以随时私信我。😊