amqp依赖包,可快速方便的在 SpringBoot 中使用 RabbitMQ
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>
config
@Configuration public class RabbitMQConfig { /** * 消息转换器 默认jdk转换器 * @return */ @Bean public MessageConverter jsonMessageConverter(){ return new Jackson2JsonMessageConverter(); } }
@Component @Slf4j public class RabbitTemplateConfig implements RabbitTemplate.ConfirmCallback ,RabbitTemplate.ReturnsCallback{ @Autowired private RabbitTemplate rabbitTemplate; @PostConstruct public void init() { rabbitTemplate.setConfirmCallback(this); rabbitTemplate.setReturnsCallback(this); } /** * 确认消息是否投递到交换机 * */ @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { if (ack) { log.info("消息成功投递到交换机..."); } else { log.error("消息未成功投递到交换机..."+cause); } } /** * 消息成功投递到交换机,向队列投递失败时调用 * @param returned the returned message and metadata. */ @Override public void returnedMessage(ReturnedMessage returned) { log.error("消息未成功投递到队列..."); //获取到发送失败的消息内容信息 System.out.println(new String(returned.getMessage().getBody())); //TODO 将未发送成功的消息保存下来,比如记录到数据库,后续已定时任务的方式 或 人工处理 } }
商品微服务:生产者
yml
rabbitmq: host: 111.111.111.111 port: 5672 virtual-host: / username: rabbitmq password: 123456 # 生产者确认 publisher-confirm-type: correlated #开启消息确认异步回调 publisher-returns: true #开启消息发送失败回调 template: # 定义消息路由失败时的策略。true,则调用ReturnCallback;false:则直接丢弃消息 mandatory: true
代码
// 商品上架 同步数据到搜索引擎库 if(product.getStatus().equals(ProductStatus.ON.getStatus())) { rabbitTemplate.convertAndSend( RabbitMQConstant.EXCHANGE_PRODUCT, RabbitMQConstant.ROUTING_KEY_PRODUCT_SAVE, product); } //如果是下架状态的商品信息从ES库删除 if(product.getStatus().equals(ProductStatus.OFF.getStatus())){ rabbitTemplate .convertAndSend(RabbitMQConstant.EXCHANGE_PRODUCT,RabbitMQConstant.ROUTING_KEY_PRODUCT_DEL ,product.getId()); }
es微服务:消费者
pom
elasticsearch: uris: - http://111.111.111.111:9200 # 搜索引擎服务地址 rabbitmq: host: 111.111.111.111 port: 5672 virtual-host: / username: rabbitmq password: 123456 # 消费者确认 listener: simple: acknowledge-mode: manual #手动确认
写监听类,在方法上加
@RabbitListener(bindings = @QueueBinding( value = @Queue("direct.queue01"), exchange = @Exchange(name = "amq.direct",type = ExchangeTypes.DIRECT), key = {"product.save"} ))
此方式是定向
// 处理删除商品的业务 public void directListener01(String message, Channel channel, Message msg) throws IOException { //手动分会给队列一个ack信号 try { System.out.println("消费者01收到direct.queue01消息:" + message); int i=100/0;
//期间调用文档更新方法 productDocService.saveOrUpdate(doc);
//返回ack channel.basicAck(msg.getMessageProperties().getDeliveryTag(),false); } catch (Exception e) { // TODO 添加额外的处理逻辑 //b:是否允许多条处理 b1:是否重新回到队列 // 返回 nack,从队列删除该消息 channel.basicNack(msg.getMessageProperties().getDeliveryTag(), false, false); //通过其他途径记录和后续处理该消息 }