1.增加pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2.编写配置类
@Configuration
public class RabbitMQConfiguration {
//队列名称
public final static String orderQueue = "order_queue";
//交换机名称
public final static String orderExchange = "order_exchange";
// routingKey队列路由键
public final static String routingKeyOrder = "routing_key_order";
//死信消息队列名称
public final static String dealQueueOrder = "deal_queue_order";
//死信交换机名称
public final static String dealExchangeOrder = "deal_exchange_order";
//死信 routingKey
public final static String deadRoutingKeyOrder = "dead_routing_key_order";
//死信队列 交换机标识符
public static final String DEAD_LETTER_QUEUE_KEY = "x-dead-letter-exchange";
//死信队列交换机绑定键标识符
public static final String DEAD_LETTER_ROUTING_KEY = "x-dead-letter-routing-key";
@Autowired
private CachingConnectionFactory connectionFactory;
@Bean
public Queue orderQueue() {
// 将普通队列绑定到死信队列交换机上
Map<String, Object> args = new HashMap<>(2);
//args.put("x-message-ttl", 5 * 1000);//直接设置 Queue 延迟时间 但如果直接给队列设置过期时间,这种做法不是很灵活
//这里采用发送消息动态设置延迟时间,这样我们可以灵活控制
args.put(DEAD_LETTER_QUEUE_KEY, dealExchangeOrder);
args.put(DEAD_LETTER_ROUTING_KEY, deadRoutingKeyOrder);
return new Queue(RabbitMQConfiguration.orderQueue, true, false, false, args);
}
//声明一个direct类型的交换机
@Bean
DirectExchange orderExchange() {
return new DirectExchange(RabbitMQConfiguration.orderExchange);
}
//绑定Queue队列到交换机,并且指定routingKey
@Bean
Binding bindingDirectExchangeDemo5() {
return BindingBuilder.bind(orderQueue()).to(orderExchange()).with(routingKeyOrder);
}
//创建配置死信队列
@Bean
public Queue deadQueueOrder() {
Queue queue = new Queue(dealQueueOrder, true);
return queue;
}
//创建死信交换机
@Bean
public DirectExchange deadExchangeOrder() {
return new DirectExchange(dealExchangeOrder);
}
//死信队列与死信交换机绑定
@Bean
public Binding bindingDeadExchange() {
return BindingBuilder.bind(deadQueueOrder()).to(deadExchangeOrder()).with(deadRoutingKeyOrder);
}
}
3.编写监听器
@Component
public class MqFailureListener {
@Autowired
private RatingBasicInfoService basicInfoService;
@RabbitListener(
queues = RabbitMQConfiguration.dealQueueOrder
)
public void process(Integer id, Message message, @Headers Map<String, Object> headers, Channel channel) throws IOException {
System.out.println("消息:用户id--------" + id);
RatingBasicInfo ratingBasicInfo = basicInfoService.getById(id);
String payPhoto = ratingBasicInfo.getPayPhoto();
if (StringUtils.isEmpty(payPhoto)) {
System.out.println("用户:" + ratingBasicInfo.getName() + ";未按时上传缴费截图");
//delivery tag可以从消息头里边get出来
Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
//手动应答,消费者成功消费完消息之后通知mq,从队列移除消息,需要配置文件指明。第二个参数为是否批量处理
channel.basicAck(deliveryTag, false);
//移出队列,false只确保一个消息被消费并一处队列
//channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
}
}
4.测试接口
@RestController
@RequestMapping("/test")
@Api(tags = "mq测试")
public class TestController {
@Autowired
private AmqpTemplate rabbitTemplate;
@Autowired
private RatingBasicInfoService basicInfoService;
@GetMapping("/submit")
@ApiOperation("提交信息")
public ResponseEntity submit() {
RatingBasicInfo ratingBasicInfo = new RatingBasicInfo();
ratingBasicInfo.setName("xx");
ratingBasicInfo.setOpenId("123");
basicInfoService.save(ratingBasicInfo);
System.out.println("创建成功......");
// 放入死信队列
//Rabbit延时队列,处理订单自动取消
this.rabbitTemplate.convertAndSend(
RabbitMQConfiguration.orderExchange,
RabbitMQConfiguration.routingKeyOrder,
ratingBasicInfo.getId(), message -> {
message.getMessageProperties().setExpiration(1000 * 30 + "");
return message;
});
System.out.println("发送消息......");
return ResultUtil.success();
}
}