一、Windows系统安装:
rabbitmq安装
前提是erlang环境
,我把两个安装包都放云盘了,安装细节就不说了 都是傻瓜式安装,注意点就是安装路径不要有中文。
链接:https://pan.xunlei.com/s/VO4dwLaZaV10xGlKkhjY5ZknA1?pwd=xx8e#
正常安装完成然后执行下面命令就可以使用了:
1、进入安装目录 cd 你的RabbitMQ安装目录\sbin
2、打开节点:rabbitmqctl start_app
3、配置管理模块:rabbitmq-plugins enable rabbitmq_management
4、关闭节点:rabbitmqctl stop
这篇文章是草稿之前忘记记录错误和解决方法,现在发出来已经忘记当时出现的错误和解决办法(报一丝)
二、使用案例(超时未支付取消订单)
依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
配置RabbitMQ:
在项目的配置类中,配置RabbitMQ的交换机、队列和绑定关系,如下:
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitMqConfig {
public static final String ORDER_EXCHANGE = "order_exchange";
public static final String DEAD_LETTER_EXCHANGE = "dead_letter_exchange";
public static final String ORDER_QUEUE = "order_queue";
public static final String DEAD_LETTER_QUEUE = "dead_letter_queue";
public static final String ROUTING_KEY = "order_routing_key";
public static final String DEAD_LETTER_ROUTING_KEY = "dead_letter_routing_key";
@Bean
public DirectExchange orderExchange() {
return new DirectExchange(ORDER_EXCHANGE);
}
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange(DEAD_LETTER_EXCHANGE);
}
@Bean
public Queue orderQueue() {
Map<String, Object> args = new HashMap<>();
args.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE);
args.put("x-dead-letter-routing-key", DEAD_LETTER_ROUTING_KEY);
args.put("x-message-ttl", 900000); // 设置消息存活时间为15分钟(毫秒)
return QueueBuilder.durable(ORDER_QUEUE).withArguments(args).build();
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder.durable(DEAD_LETTER_QUEUE).build();
}
@Bean
public Binding orderBinding(@Qualifier("orderQueue") Queue queue,
@Qualifier("orderExchange") DirectExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY);
}
@Bean
public Binding deadLetterBinding(@Qualifier("deadLetterQueue") Queue queue,
@Qualifier("deadLetterExchange") DirectExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(DEAD_LETTER_ROUTING_KEY);
}
}
创建生产者
在服务类中,创建一个生产者,用于将订单信息发送到RabbitMQ队列中:
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrderProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendOrder(Order order) {
rabbitTemplate.convertAndSend(RabbitMqConfig.ORDER_EXCHANGE, RabbitMqConfig.ROUTING_KEY, order);
}
}
消费者处理超时订单:
创建一个消费者,用于监听死信队列,并处理超时订单:
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class OrderConsumer {
@Autowired
private OrderService orderService;
@RabbitListener(queues = RabbitMqConfig.DEAD_LETTER_QUEUE)
public void handleOrderTimeout(Order order) {
// 检查订单状态是否为待支付
if (order.getStatus() == 0) {
// 更新订单状态为已取消
order.setStatus(5);
order.setCancelReason("订单超时未支付,系统自动取消");
orderService.updateOrder(order);
}
}
}
调用RabbitMQ
在订单创建后,调用OrderProducer的sendOrder方法,将订单信息发送到RabbitMQ队列中:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/order")
public class OrderController {
@Autowired
private OrderProducer orderProducer;
@Autowired
private OrderService orderService;
@PostMapping("/create")
@ResponseBody
public String createOrder(@RequestBody Order order) {
// 创建订单逻辑
orderService.createOrder(order);
// 将订单信息发送到RabbitMQ队列中
orderProducer.sendOrder(order);
return "订单创建成功";
}
}
在service中调用
如果你想在service中调用,需要考虑生成订单的代码出错然后回滚事务:
使用RabbitMQ事务机制:
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class OrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
@Transactional(rollbackFor = Exception.class)
public void createOrder(Order order) {
// 创建订单逻辑
try {
// 模拟订单创建
System.out.println("订单创建成功");
// 开启RabbitMQ事务
rabbitTemplate.execute(channel -> {
try {
channel.txSelect(); // 开启事务
rabbitTemplate.convertAndSend("order_exchange", "order_routing_key", order);
channel.txCommit(); // 提交事务
return null;
} catch (Exception e) {
channel.txRollback(); // 回滚事务
throw e;
}
});
// 模拟其他业务逻辑
System.out.println("其他业务逻辑执行成功");
} catch (Exception e) {
// 如果发生异常,回滚事务
throw new RuntimeException("订单创建失败", e);
}
}
}
@Transactional
并不能回滚取消RabbitMQ已发送的消息@Transactional
注解主要用于管理数据库事务,确保在事务边界内的数据库操作要么全部成功提交,要么在发生异常时回滚。- 因为
RabbitMQ
的消息发送和数据库操作是两种不同的资源,Spring的事务管理器无法直接管理RabbitMQ的消息发送操作。