使用步骤
1.在linux上安装Rabbitmq
https://blog.csdn.net/qq_45173404/article/details/116429302
2.配置xml和nacos
代码如下(示例):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
spring:
rabbitmq:
host: 139.9.51.189
port: 5672
username: root
password: zkhj@20230210
virtual-host: /
publisher-confirm-type: correlated
listener:
simple:
acknowledge-mode: manual
3. 创建rabbitmqConfig
@Slf4j
@Configuration
public class RabbitMqConfig {
RabbitTemplate rabbitTemplate;
@Primary
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
this.rabbitTemplate = rabbitTemplate;
rabbitTemplate.setMessageConverter(jsonMessageConverter());
initRabbitTemplate();
return rabbitTemplate;
}
@Bean
public MessageConverter jsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
/**
* 定制RabbitTemplate
*/
//@PostConstruct // RabbitConfig对象创建完成以后,调用这个方法
public void initRabbitTemplate() {
// 设置回调 消息抵达Broker回调
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
/**
* 只要消息抵达Broker ack就会是true
* @param correlationData 当前消息唯一关联数据(唯一id)
* @param ack 消息是否成功收到
* @param cause 失败的原因
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
log.info("[消息抵达Broker]Rabbitmq...confirm...correlationData[{}],ack[{}],cause[{}]",correlationData, ack, cause);
}
});
// 设置消息抵达队列Queue的确认回调
rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
/**
* 只要消息没有投递给指定的队列,就触发这个失败回调
* @param message 投递失败的消息的详细信息
* @param replyCode 回复的状态码
* @param replyText 回复的文本内容
* @param exchange 发送时的交换机
* @param routingKey 发送时的路由键
*/
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
log.info("[消息投递失败]Fail Message[{}],replyCode[{}]", message, replyCode);
}
});
}
}
4. 创建队列和交换机
@Component
@Configuration
public class RabbitMqConstantConfig {
/**
* 延时路由key(共用)
*/
public static final String DELAYED_ROUTE_KEY = "delay.#";
/**
* (设备)延时工单队列
*/
public static final String DELAYED_WORK_ORDER_QUEUE_NAME = "delay.wordOrder.queue";
/**
* (设备)延时工单交换机
*/
public static final String DELAYED_WORK_ORDER_EXCHANGE_NAME = "delay.wordOrder.exchange";
@Bean(DELAYED_WORK_ORDER_QUEUE_NAME)
public Queue workOrderQueue() {
return new Queue(DELAYED_WORK_ORDER_QUEUE_NAME);
}
@Bean(DELAYED_WORK_ORDER_EXCHANGE_NAME)
public CustomExchange workOrderExchange() {
Map<String, Object> args = new HashMap<>();
//声明 延迟交换机的类型为路由直连
args.put("x-delayed-type", "direct");
//声明 延迟交换机的类型为路由直连
return new CustomExchange(DELAYED_WORK_ORDER_EXCHANGE_NAME, "x-delayed-message", true, false, args);
}
@Bean
public Binding bindingWorkOrderNotify(@Qualifier(DELAYED_WORK_ORDER_QUEUE_NAME) Queue queue,
@Qualifier(DELAYED_WORK_ORDER_EXCHANGE_NAME) CustomExchange customExchange) {
return BindingBuilder.bind(queue).to(customExchange).with(DELAYED_ROUTE_KEY).noargs();
}
配置x-delayed-message属性开启延时的功能
5.创建生产者
@Slf4j
@Component
public class ProduceHandler {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 普通发送消息
* @param exchange 交换机
* @param routingKey 路由key
* @param msg 消息体
*/
public void send(String exchange, String routingKey, String msg) {
rabbitTemplate.convertAndSend(exchange,routingKey,msg,message -> {
// 设置消息全局唯一性,防止重复消费,解决幂等性
message.getMessageProperties().setMessageId(UUID.randomUUID().toString());
return message;
});
}
/**
* 发送延时消息
* @param exchange 交换机
* @param routingKey 路由key
* @param msg 消息体
* @param time 延时时间(秒)
*/
public void sendDelayMQ(String exchange, String routingKey, String msg, Integer time) {
rabbitTemplate.convertAndSend(exchange,routingKey,msg,message -> {
// 设置延迟毫秒值
message.getMessageProperties().setHeader("xdelay",String.valueOf(time * 1000));
message.getMessageProperties().setDelay(time * 1000);
// 设置消息全局唯一性,防止重复消费,解决幂等性
message.getMessageProperties().setMessageId(UUID.randomUUID().toString());
return message;
});
}
}
6. 创建消费者
@Slf4j
@Component
public class ConsumerHandler {
@Autowired
private WorkOrderService workOrderService;
/**
* 消费延时工单队列数据
* @param msg
* @param message
* @param channel
* @throws IOException
*/
@RabbitListener(queues = DELAYED_WORK_ORDER_QUEUE_NAME)
public void delayWorkOrder(String msg, Message message, Channel channel) {
log.info("接收---超时工单消息,工单ID:{}",msg);
if (StringUtils.isNotBlank(msg)){
log.info("开始处理--超时工单消息,工单ID:{}",msg);
workOrderService.delayWorkOrder(Long.valueOf(msg),message,channel);
}
}
}
总结
- 建议将生产者和消费着放入handler文件夹当中
- 仿照写完以后要去了解里面的属性的含义,根据这个去学习rabbitmq看得明白一些