(1)生产者代码
@Slf4j
@RestController
@RequestMapping("/test")
public class MqProducerController {
@Autowired
private RocketMQTemplate rocketMQTemplate;
@RequestMapping("/syncSendOrderMessage")
public String syncSendOrderMessage() {
Order order = new Order();
order.setOrderId(1);
order.setOrderNo(1);
order.setProductId(1);
order.setUserId(1);
order.setOrderNum(5);
order.setOrderAmt(new BigDecimal("100.0"));
order.setOrderStatus("下单");
order.setPayStatus("未支付");
order.setCreateUser("elite");
order.setCreateTime(LocalDateTime.now());
SendResult sendResult = rocketMQTemplate.syncSend("sync-order-topic", order.toString(), 6000);
return sendResult.toString();
}
@RequestMapping("/asyncSendOrderMessage")
public String asyncSendOrderMessage() {
Order order = new Order();
order.setOrderId(1);
order.setOrderNo(1);
order.setProductId(1);
order.setUserId(1);
order.setOrderNum(5);
order.setOrderAmt(new BigDecimal("100.0"));
order.setOrderStatus("下单");
order.setPayStatus("未支付");
order.setCreateUser("elite");
order.setCreateTime(LocalDateTime.now());
rocketMQTemplate.asyncSend("async-order-topic",order.toString(),new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
log.info("send successful,{}",sendResult.toString());
}
@Override
public void onException(Throwable throwable) {
log.info("send fail; {}", throwable.getMessage());
}
});
return order.toString();
}
@RequestMapping("/convertAndSendOrderMessage")
public String convertAndSendOrderMessage() {
Order order = new Order();
order.setOrderId(1);
order.setOrderNo(1);
order.setProductId(1);
order.setUserId(1);
order.setOrderNum(5);
order.setOrderAmt(new BigDecimal("100.0"));
order.setOrderStatus("下单");
order.setPayStatus("未支付");
order.setCreateUser("elite");
order.setCreateTime(LocalDateTime.now());
rocketMQTemplate.convertAndSend("convertAndSend-order-topic",order.toString());
return order.toString();
}
}
(2)消费者代码
@Component
@RocketMQMessageListener(topic = "sync-order-topic",selectorExpression = "*",
consumerGroup = "sync-consumer-group",
consumeMode = ConsumeMode.ORDERLY,
messageModel = MessageModel.CLUSTERING)
public class SyncConsumer implements RocketMQListener<String> {
@Override
public void onMessage(String message) {
System.out.println("sync-order-topic:"+message);
}
}
@Component
@RocketMQMessageListener(topic = "async-order-topic",selectorExpression = "*",
consumerGroup = "async-consumer-group",
consumeMode = ConsumeMode.ORDERLY,
messageModel = MessageModel.CLUSTERING)
public class AsyncConsumer implements RocketMQListener<String> {
@Override
public void onMessage(String message) {
System.out.println("async-order-topic:"+message);
}
}
@Component
@RocketMQMessageListener(topic = "convertAndSend-order-topic",selectorExpression = "*",
consumerGroup = "convertAndSend-consumer-group",
consumeMode = ConsumeMode.ORDERLY,
messageModel = MessageModel.CLUSTERING)
public class ConvertAndSendConsumer implements RocketMQListener<String> {
@Override
public void onMessage(String message) {
System.out.println("convertAndSend-order-topic:"+message);
}
}
(3)事务代码
/*
* 【生产者】模拟用户发起订单
*/
@Slf4j
@Service
public class TransactionProducerService {
@Autowired
private RocketMQTemplate rocketMQTemplate;
public TransactionSendResult sendHalfMsg(String msg){
// 生成事务ID
String transactionId = UUID.randomUUID().toString().replace("-","");
log.info("【发送半消息】transactionId={}", transactionId);
String transKeys = "transKey";
// 发送事务消息
TransactionSendResult sendResult = rocketMQTemplate.sendMessageInTransaction(
"trans-order-topic",
MessageBuilder.withPayload(msg)
.setHeader(RocketMQHeaders.TRANSACTION_ID, transactionId)
.setHeader(RocketMQHeaders.KEYS,transKeys) // 相比于使用"KEYS",使用封装常量更不易出错
.build(),
msg
);
log.info("【发送半消息】sendResult={}",msg);
return sendResult;
}
}
/*
* 【事务监听器(本地事务)】
*/
@Slf4j
@RocketMQTransactionListener()
public class ICBCTransactionListener implements RocketMQLocalTransactionListener {
int count = 0;
//信息发送后执行一次半消息的确认,本地数据库的处理也是在这里
@Override
public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
System.out.println("executeLocalTransaction:"+count);
count = count+1;
MessageHeaders messageHeaders = msg.getHeaders();
String transactionId = (String) messageHeaders.get(RocketMQHeaders.TRANSACTION_ID);
log.info("预提交消息成功:{}",msg);
log.info("【执行本地事务】消息体参数:transactionId={}", transactionId);
try {
StringBuilder money = new StringBuilder();
byte[] bytes = ((byte[])msg.getPayload());
for (int i = 0; i < bytes.length; i++) {
money.append(bytes[i] - '0');
}
log.info("【执行本地事务成功】工行账户扣除" + money +"元!");
return RocketMQLocalTransactionState.UNKNOWN;
} catch (Exception e) {
return RocketMQLocalTransactionState.ROLLBACK;
}
}
//executeLocalTransaction方法执行返回RocketMQLocalTransactionState.UNKNOWN,
// rocketmq会再次来这里确认消息是否可以被消费还是销毁
@Override
public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
MessageHeaders headers = msg.getHeaders();
String transactionId = headers.get(RocketMQHeaders.TRANSACTION_ID, String.class);
log.info("执行消息回查:{}",msg);
log.info("【回查本地事务】transactionId={}",transactionId);
// 执行代码查询是否本地事务执行成功
if(...){
return RocketMQLocalTransactionState.COMMIT;
}else {
return RocketMQLocalTransactionState.ROLLBACK;
}
}
}
/*
* 【消费者】
*/
@Slf4j
@Component
@RocketMQMessageListener(topic = "trans-order-topic",selectorExpression = "*",
consumerGroup = "trans-consumer-group",
consumeMode = ConsumeMode.ORDERLY,
messageModel = MessageModel.CLUSTERING)
public class CCBTransactionConsumer implements RocketMQListener<String> {
@Override
public void onMessage(String message) {
// 幂等性判断
// 1、使用唯一字段进行判断,如订单号
// 2、新建一张带有唯一性字段的表,辅助判断
// 执行具体业务
// if(...) { //执行失败
// log.error("【执行失败】转账失败!");
// } else //执行成功
log.info("【执行成功】转账成功!建行账户增加" + message + "元!");
// }
}
}