目录
0. 引言
上一节针对spring或其他框架集成rocketmq实现消息发送进行了讲解,而作为当前更加流行的springboot框架,实现rocketmq的集成则更加简单,本节我们就重点针对springboot集成rocketmq,实现异步、同步、单向、顺序、延迟、事务消息发送进行讲解,文末附上源码。
1. springboot集成
1、引入maven依赖
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
2、配置文件application.yml中添加配置项
rocketmq:
name-server: localhost:9876
producer:
group: group_test # 生产者分组,事务消息会使用
send-message-timeout: 3000 # 消息发送超时时长,默认3s
retry-times-when-send-failed: 3 # 同步发送消息失败重试次数,默认2
retry-times-when-send-async-failed: 3 # 异步发送消息失败重试次数,默认2
3、在controller或者service中,直接引入RocketMQTemplate
即可使用
@Resource
private RocketMQTemplate rocketMQTemplate;
2. 消息发送
各种消息的相关概念和特点描述本篇不再累述,如果不清楚的小伙伴可以查看上一篇文章:
2.1 消息同步发送
查看RocketMQTemplate
支持的同步发送方法参数如下,其中参数含义为:
destination: 目标地址,由topic和tag组成,如topicA:tag1
payload:消息主体,即要发送的消息内容
timeout:发送超时时间
示例代码:
@GetMapping(value = "/syncSend")
public void syncSend() {
String message = "同步消息";
SendResult sendResult = rocketMQTemplate.syncSend("topic_test:tag_test", message);
System.out.println("发送结果:"+sendResult);
}
除了使用RocketMQTemplate
类中的方法,还可以使用其父类AbstractMessageSendingTemplate
中的发送方法来实现同步发送
代码示例
@GetMapping("send2")
public String send(){
Message<String> msg = MessageBuilder.withPayload("Hello,RocketMQ Normal_msg").build();
rocketMQTemplate.send("topic_test",msg);
return "success";
}
@RequestMapping(value = "/send3")
public void send3() {
// 发送普通字符串消息
rocketMQTemplate.convertAndSend("topic_test", "Hello Word");
}
2.2 消息异步发送
支持的参数如下,其中SendCallback
就是要定义的回调类
示例代码:
@GetMapping(value = "/aSyncSend")
public void aSyncSend() {
String message = "异步消息";
// 定义回调函数
SendCallback callback = new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
System.out.println("发送成功");
}
@Override
public void onException(Throwable throwable) {
System.out.println("发送失败");
}
};
rocketMQTemplate.asyncSend("topic_test", message, callback);
}
2.3 消息单向发送
单向消息的发送相对简单,可以选择直接传入数据内容,或者构建一个message对象传入
示例代码
@GetMapping(value = "/sendOneWay")
public void sendOneWay() {
rocketMQTemplate.sendOneWay("topic_test", "发送单向消息");
}
2.4 顺序消息发送
顺序消息发送前,要先将topic设置为顺序topic, 并设置namesrv的orderMessageEnable 和 returnOrderTopicConfigToBroker为true, 如何设置请查看上一篇《集成java客户端实现各类消息发送》
顺序发送,使用带Orderly
字样方法即可,支持同步、异步、单向顺序发送
同步顺序发送:
异步顺序发送
单向顺序发送
可以看到springboot集成的顺序消息与之前讲解的java client的区别是不用再定义MessageQueueSelector
了,而是直接传入hashKey
即可,这个hashKey就是区分键,比如订单号、用户ID等的hashcode值。其默认的MessageQueueSelector就是SelectMessageQueueByHash
当然如果不想使用默认的队列选择器,可以通过setMessageQueueSelector
方法自定义
示例代码:
@GetMapping(value = "/sendOrder")
public void sendOrder() {
for (int i = 0; i < 10; i++) {
// 模拟奇数、偶数分别为一组
rocketMQTemplate.syncSendOrderly("topic_order", "发送单向消息", (i%2)+"");
}
}
2.5 批量消息发送
批量消息的发送,主要关注方法参数中的入参为集合Collection的形式
代码示例
@GetMapping(value = "/sendBatch")
public void sendBatch() {
List<org.apache.rocketmq.common.message.Message> messages = new ArrayList<>();
messages.add(new org.apache.rocketmq.common.message.Message("topic_test", "Tag", "消息1".getBytes()));
messages.add(new org.apache.rocketmq.common.message.Message("topic_test", "Tag", "消息2".getBytes()));
messages.add(new org.apache.rocketmq.common.message.Message("topic_test", "Tag", "消息3".getBytes()));
// 模拟奇数、偶数分别为一组
SendResult sendResult = rocketMQTemplate.syncSend("topic_test", messages);
System.out.println("发送结果:"+sendResult);
}
2.6 延迟消息发送
延迟消息的发送主要关注delayLevel
参数
该参数支持18个等级
代码示例
@GetMapping(value = "/sendDelay")
public void sendDelay() {
Message<String> msg = MessageBuilder.withPayload("延迟消息").build();
SendResult sendResult = rocketMQTemplate.syncSend("topic_test", msg, 3, 2);
System.out.println("发送结果:"+sendResult);
}
2.7 事务消息发送
事务消息通过sendMessageInTransaction
方法实现
发送代码与java client的形式类似
@GetMapping(value = "/sendTransaction")
public void sendTransaction() {
Message<String> msg = MessageBuilder.withPayload("延迟消息").build();
SendResult sendResult = rocketMQTemplate.sendMessageInTransaction("topic_test", msg, null);
System.out.println("发送结果:"+sendResult);
}
关键在于TransactionListener
的定义,接口改成了RocketMQLocalTransactionListener
,并且需要申明@RocketMQTransactionListener
注解
RocketMQLocalTransactionState状态各个值的定义,executeLocalTransaction和checkLocalTransaction方法的含义均可参考上篇文章
@RocketMQTransactionListener
public class RocketMQLocalTransactionListenerImpl implements RocketMQLocalTransactionListener {
@Override
public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {
// TODO 执行本地事务(书写你自己的本地事务逻辑)
try{
String body = message.getPayload().toString();
int i = Integer.parseInt(body);
// 模拟偶数执行成功,奇数执行失败
if(i % 2 == 0){
System.out.println("本地事务执行成功:"+body);
// 执行成功
return RocketMQLocalTransactionState.COMMIT;
}else{
System.out.println("本地事务执行失败:"+body);
// 执行失败
return RocketMQLocalTransactionState.ROLLBACK;
}
}catch (Exception e){
e.printStackTrace();
// 执行失败
return RocketMQLocalTransactionState.ROLLBACK;
}
}
@Override
public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
// TODO 去缓存或者数据库查询当前消息的实际状态
// 模拟查询到状态为1
Integer status = 1;
// 不同实际状态对应的消息状态
if (null != status) {
switch (status) {
case 1:
return RocketMQLocalTransactionState.COMMIT;
case 2:
return RocketMQLocalTransactionState.ROLLBACK;
default:
return RocketMQLocalTransactionState.COMMIT;
}
}
return RocketMQLocalTransactionState.COMMIT;
}
}
3. 总结
至此我们就将java集成rocektmq实现消息发送的内容讲解完成了,但有发送还应该有接收消费,所以紧接着,我们继续来学习如何实现消息消费。