mq自用文章

mq使用
maven
xml 配置
<!-- mq-->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.1.1</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</exclusion>
</exclusions>
</dependency>
# mq 参数
rocketmq:
name-server: 127.0.0.1:9876
producer:
group:
/**
* @Author
* @Date Created in 2022/06/07
* @Describe:
*/
import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.apache.rocketmq.spring.support.RocketMQUtil;
import org.springframework.messaging.Message;
import org.springframework.messaging.converter.StringMessageConverter;
import java.util.concurrent.ConcurrentHashMap;
/**
* @description: 事务消息监听器
* 关于 @RocketMQTransactionListener 这个注解,有点奇怪。 2.0.4 版本中,是需要指定 txProducerGroup 指向一个消息发送者组。不同的组可以有不同的事务消息逻辑。
* 但是到了 2.1.1 版本,只能指定 rocketMQTemplateBeanMame ,也就是说如果你有多个发送者组需要有不同的事务消息逻辑,那就需要定义多个 RocketMQTemplate
* 而且这个版本中,虽然重现了我们在原生 API 中的事务消息逻辑,但是测试过程中还是发现一些奇怪的特性,用的时候要注意点。
**/
//@RocketMQTransactionListener(txProducerGroup = "springBootGroup2")
@RocketMQTransactionListener(rocketMQTemplateBeanName = "rocketMQTemplate")
public class MyTransactionImpl implements RocketMQLocalTransactionListener {
private ConcurrentHashMap<Object, Message> localTrans = new ConcurrentHashMap<>();
@Override
public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
Object transId = msg.getHeaders().get(RocketMQHeaders.PREFIX + RocketMQHeaders.TRANSACTION_ID);
String destination = arg.toString();
localTrans.put(transId, msg);
// 这个 msg 的实现类是 GenericMessage ,里面实现了 toString 方法
// Header 中自定义的 RocketMQHeaders.TAGS 属性,到这里就没了。但是 RocketMQHeaders.TRANSACTION_ID 这个属性就还在。
// message Header 里面会默认保存 RocketMQHeaders 里的属性,但是都会加上一个 RocketMQHeaders.PREFIX 前缀
System.out.println("executeLocalTransaction msg = " + msg);
// 转成 RocketMQ Message 对象
org.apache.rocketmq.common.message.Message message = RocketMQUtil.convertToRocketMessage(new StringMessageConverter(), "UTF-8"
String tags = message.getTags();
if (StringUtils.contains(tags, "TagA")) {
return RocketMQLocalTransactionState.COMMIT;
} else if (StringUtils.contains(tags, "TagB")) {
return RocketMQLocalTransactionState.ROLLBACK;
} else {
return RocketMQLocalTransactionState.UNKNOWN;
}
}
// 延迟检查的时间间隔要有点奇怪。
@Override
public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
String transId = msg.getHeaders().get(RocketMQHeaders.PREFIX + RocketMQHeaders.TRANSACTION_ID).toString();
Message originalMessage = localTrans.get(transId);
// 这里能够获取到自定义的 transaction_id 属性
System.out.println("checkLocalTransaction msg = " + originalMessage);
// 获取标签时,自定义的 RocketMQHeaders.TAGS 拿不到,但是框架会封装成一个带 RocketMQHeaders.PREFIX 的属性
// String tags = msg.getHeaders().get(RocketMQHeaders.TAGS).toString();
String tags = msg.getHeaders().get(RocketMQHeaders.PREFIX + RocketMQHeaders.TAGS).toString();
if (StringUtils.contains(tags, "TagC")) {
return RocketMQLocalTransactionState.COMMIT;
} else if (StringUtils.contains(tags, "TagD")) {
return RocketMQLocalTransactionState.ROLLBACK;
} else {
return RocketMQLocalTransactionState.UNKNOWN;
}
}
}
import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
生产者
/**
* @Author
* @Date Created in 2022/06/07
* @Describe:
*/
// -------
@ExtRocketMQTemplateConfiguration()
public class ExtRocketMQTemplate extends RocketMQTemplate {
}
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
/**
* @Author
* @Date Created in 2022/06/07
* @Describe:
*/
@Component
public class SpringBootProducer {
@Autowired
private RocketMQTemplate rocketMQTemplate;
// 发送消息的实例
public void sendMessage(String topic, String msg) {
rocketMQTemplate.convertAndSend(topic, msg);
}
// 发送事务消息的实例
public void sendMessageInTransaction(String topic, String msg) throws InterruptedException {
String[] tags = {"TagA", "TagB", "TagC", "TagD", "TagE"};
for (int i = 0; i < 10; i++) {
Message<String> message = MessageBuilder.withPayload(msg).build();
String destination = topic + ":" + tags[i % tags.length];
TransactionSendResult sendResult =
rocketMQTemplate.sendMessageInTransaction(destination, message, destination);
System.out.printf("%s%n", sendResult);
Thread.sleep(10);
}
}
}
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.dataease.controller.sys.request.SysRoleCreateRequest;
import io.dataease.controller.sys.request.SysUserCreateRequest;
import org.apache.rocketmq.spring.annotation.ConsumeMode;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author
* @Date Created in 2022/06/07
* @Describe:
*/
@Component
@RestController
@RocketMQMessageListener(consumerGroup = "springBootGroup", topic = "TestTopi2", consumeMode = ConsumeMode.ORDERLY)
public class SpringBootConsumer implements RocketMQListener {
@Override
public void onMessage(Object message) {
// 业务逻辑
}
}
自己创建消费者(原)可不用,现未经过测试,原来可用
@GetMapping("/getMqData")
public String getMqOfGz() throws MQClientException {
// 消费者的组名,这个和 kafka 是一样 , 这里需要注意的是,
String url = environment.getProperty("mq.url");
String group = environment.getProperty("mq.group");
String title = environment.getProperty("mq.title");
Integer num = parMqGroupService.selectParMqGroupByLastId()+1;
parMqGroupService.insertParMqGroup(new ParMqGroup());
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(group+num);
// 指定 NameServer 地址,多个地址以 ; 隔开
consumer.setNamesrvAddr(url);
// 设置 Consumer 第一次启动是从队列头部开始消费还是队列尾部开始消费
// 如果非第一次启动,那么按照上次消费的位置继续消费
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
// 订阅 PushTopic Tag push 的消息
consumer.subscribe(title, "*"); //* 表示不过滤,可以通过 tag 来过滤,比如 :”tagA”
/*
* 注册消息监听回调这里有两种监听, MessageListenerConcurrently 以及 MessageListenerOrderly
* 前者是普通监听,后者是顺序监听。这块在后续单独说明
*/
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt>
msgs,
ConsumeConcurrentlyContext context) {
System.out.println(Thread.currentThread().getName()
+ " Receive New Messages: " + msgs.size());
MessageExt msg = msgs.get(0);
if (msg.getTopic().equals(title)) {
// 执行 TopicTest1 的消费逻辑
if (msg.getTags() != null) {
// 执行 TagA 的消费
System.out.println(new String(msg.getBody()));
LoginLog loginLog = new LoginLog();
loginLog.setLoginOperation(new String(msg.getBody()));
loginLogService.insertLoginLog(loginLog);
}
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;// 返回消息消费状态
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值