Spring Boot封装RocketMQ事务消息发送
下面我将把RocketMQ事务消息发送功能封装为Spring Boot组件,方便在项目中调用。
1. 添加依赖
首先确保pom.xml中有RocketMQ客户端依赖:
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client-java</artifactId>
<version>5.0.8</version>
</dependency>2. 配置类
import org.apache.rocketmq.client.apis.ClientServiceProvider;
import org.apache.rocketmq.client.apis.producer.Producer;
import org.apache.rocketmq.client.apis.producer.TransactionChecker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RocketMQConfig {
private static final Logger log = LoggerFactory.getLogger(RocketMQConfig.class);
@Value("${rocketmq.transaction.topic:yourTransactionTopic}")
private String transactionTopic;
# 或者使用自定义的 9878 端口
@Value("${rocketmq.endpoints:localhost:8081}")
private String endpoints;
@Bean
public ClientServiceProvider clientServiceProvider() {
return ClientServiceProvider.loadService();
}
@Bean
public TransactionChecker transactionChecker() {
return messageView -> {
log.info("Receive transactional message check, message={}", messageView);
// 这里可以根据业务逻辑决定是提交还是回滚
// 可以从messageView中获取业务数据进行检查
return TransactionResolution.COMMIT;
};
}
@Bean(destroyMethod = "close")
public Producer transactionalProducer(ClientServiceProvider provider, TransactionChecker checker) {
try {
return provider.newProducerBuilder()
.setTopics(transactionTopic)
.setTransactionChecker(checker)
.build();
} catch (Exception e) {
log.error("Failed to create transactional producer", e);
throw new RuntimeException("Failed to create transactional producer", e);
}
}
}3. 服务类封装
import org.apache.rocketmq.client.apis.ClientServiceProvider;
import org.apache.rocketmq.client.apis.message.Message;
import org.apache.rocketmq.client.apis.producer.Producer;
import org.apache.rocketmq.client.apis.producer.Transaction;
import org.apache.rocketmq.client.apis.producer.TransactionResolution;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.nio.charset.StandardCharsets;
import java.util.Map;
@Service
public class RocketMQTransactionalService {
private static final Logger log = LoggerFactory.getLogger(RocketMQTransactionalService.class);
private final ClientServiceProvider provider;
private final Producer producer;
private final String transactionTopic;
@Autowired
public RocketMQTransactionalService(ClientServiceProvider provider,
Producer producer,
@Value("${rocketmq.transaction.topic:yourTransactionTopic}") String transactionTopic) {
this.provider = provider;
this.producer = producer;
this.transactionTopic = transactionTopic;
}
/**
* 发送事务消息
* @param body 消息内容
* @param tag 消息标签
* @param keys 消息keys
* @param properties 消息属性
* @return 事务对象,用于后续提交或回滚
*/
public Transaction sendTransactionalMessage(String body, String tag, String keys, Map<String, String> properties) {
try {
Message.Builder builder = provider.newMessageBuilder()
.setTopic(transactionTopic)
.setTag(tag)
.setKeys(keys)
.setBody(body.getBytes(StandardCharsets.UTF_8));
if (properties != null) {
properties.forEach(builder::addProperty);
}
Message message = builder.build();
Transaction transaction = producer.beginTransaction();
producer.send(message, transaction);
log.info("Send transaction message successfully, keys={}", keys);
return transaction;
} catch (Exception e) {
log.error("Failed to send transactional message", e);
throw new RuntimeException("Failed to send transactional message", e);
}
}
/**
* 提交事务
* @param transaction 事务对象
*/
public void commitTransaction(Transaction transaction) {
try {
transaction.commit();
log.info("Transaction committed successfully");
} catch (Exception e) {
log.error("Failed to commit transaction", e);
throw new RuntimeException("Failed to commit transaction", e);
}
}
/**
* 回滚事务
* @param transaction 事务对象
*/
public void rollbackTransaction(Transaction transaction) {
try {
transaction.rollback();
log.info("Transaction rolled back successfully");
} catch (Exception e) {
log.error("Failed to rollback transaction", e);
throw new RuntimeException("Failed to rollback transaction", e);
}
}
}4. 使用示例
import org.apache.rocketmq.client.apis.producer.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class OrderService {
@Autowired
private RocketMQTransactionalService rocketMQTransactionalService;
public void createOrder(Order order) {
// 1. 准备消息内容
String messageBody = "Order created: " + order.getId();
String tag = "ORDER_CREATED";
String keys = "order-" + order.getId();
// 可以添加自定义属性
Map<String, String> properties = new HashMap<>();
properties.put("orderId", order.getId());
properties.put("userId", order.getUserId());
// 2. 发送事务消息
Transaction transaction = null;
try {
transaction = rocketMQTransactionalService.sendTransactionalMessage(
messageBody, tag, keys, properties);
// 3. 执行本地事务
boolean localTransactionSuccess = processLocalTransaction(order);
// 4. 根据本地事务结果提交或回滚
if (localTransactionSuccess) {
rocketMQTransactionalService.commitTransaction(transaction);
} else {
rocketMQTransactionalService.rollbackTransaction(transaction);
}
} catch (Exception e) {
if (transaction != null) {
rocketMQTransactionalService.rollbackTransaction(transaction);
}
throw e;
}
}
private boolean processLocalTransaction(Order order) {
// 这里执行本地事务逻辑,如数据库操作等
// 返回true表示成功,false表示失败
return true;
}
}5. 事务检查器实现
如果需要更复杂的事务检查逻辑,可以自定义实现:
import org.apache.rocketmq.client.apis.message.MessageView;
import org.apache.rocketmq.client.apis.producer.TransactionChecker;
import org.apache.rocketmq.client.apis.producer.TransactionResolution;
import org.springframework.stereotype.Component;
@Component
public class CustomTransactionChecker implements TransactionChecker {
@Override
public TransactionResolution check(MessageView messageView) {
// 从消息中获取业务数据
String orderId = messageView.getProperties().get("orderId");
// 检查本地事务状态
boolean isSuccess = checkLocalTransactionStatus(orderId);
return isSuccess ? TransactionResolution.COMMIT : TransactionResolution.ROLLBACK;
}
private boolean checkLocalTransactionStatus(String orderId) {
// 实现检查本地事务状态的逻辑
// 例如查询数据库确认订单状态
return true;
}
}然后在配置类中修改:
@Bean
public TransactionChecker transactionChecker(CustomTransactionChecker customChecker) {
return customChecker;
}6. 配置参数
在application.yml中添加配置:
rocketmq:
endpoints: localhost:8081
transaction:
topic: yourTransactionTopic总结
这样封装后,在Spring Boot项目中就可以方便地使用RocketMQ事务消息了:
- 注入
RocketMQTransactionalService - 调用
sendTransactionalMessage发送消息并获取事务对象 - 执行本地事务
- 根据本地事务结果调用
commitTransaction或rollbackTransaction
















