!163 将spring-cloud-stream改为普通的mq依赖用法

* update: sky日志
* update: RocketMQ的集成方式
* feat:1. rabbit: 普通消息、延迟队列
2.X
Xbhog 9 months ago committed by 疯狂的狮子Li
parent 16ca219267
commit 0dac5a544f

@ -45,6 +45,7 @@
<mapstruct-plus.version>1.3.6</mapstruct-plus.version>
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
<justauth.version>1.16.6</justauth.version>
<rocketmq-version>2.3.0</rocketmq-version>
<!-- 离线IP地址定位库 -->
<ip2region.version>2.7.0</ip2region.version>
<!-- 临时修复 fastjson 漏洞 -->
@ -384,6 +385,13 @@
<version>${mapstruct-plus.version}</version>
</dependency>
<!--消息队列-->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>${rocketmq-version}</version>
</dependency>
</dependencies>
</dependencyManagement>

@ -10,7 +10,7 @@
<modules>
<module>ruoyi-demo</module>
<module>ruoyi-stream-mq</module>
<module>ruoyi-test-mq</module>
</modules>
<artifactId>ruoyi-example</artifactId>

@ -1,60 +0,0 @@
package org.dromara.stream.controller;
import org.dromara.common.core.domain.R;
import org.dromara.stream.mq.producer.DelayProducer;
import org.dromara.stream.mq.producer.LogStreamProducer;
import org.dromara.stream.mq.producer.TestStreamProducer;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* mq
*/
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/test-mq")
public class TestMqController {
private final DelayProducer delayProducer;
private final TestStreamProducer testStreamProducer;
private final LogStreamProducer logStreamProducer;
/**
* Rabbitmq
*
* @param msg
* @param delay
*/
@GetMapping("/sendRabbitmq")
public R<Void> sendRabbitmq(String msg, Long delay) {
delayProducer.sendMsg(msg, delay);
return R.ok();
}
/**
* Rocketmq
*
* @param msg
*/
@GetMapping("/sendRocketmq")
public R<Void> sendRocketmq(String msg) {
testStreamProducer.streamTestMsg(msg);
return R.ok();
}
/**
* Kafka
*
* @param msg
*/
@GetMapping("/sendKafka")
public R<Void> sendKafka(String msg) {
logStreamProducer.streamLogMsg(msg);
return R.ok();
}
}

@ -1,20 +0,0 @@
package org.dromara.stream.mq;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* @author Lion Li
*/
@Data
@Accessors(chain = true)
public class TestMessaging {
/**
* id
*/
private String msgId;
/**
*
*/
private String msgText;
}

@ -1,22 +0,0 @@
package org.dromara.stream.mq.consumer;
import org.dromara.stream.mq.TestMessaging;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.util.function.Consumer;
@Slf4j
@Component
public class DelayConsumer {
@Bean
Consumer<TestMessaging> delay() {
log.info("初始化订阅");
return obj -> {
log.info("消息接收成功:" + obj);
};
}
}

@ -1,22 +0,0 @@
package org.dromara.stream.mq.consumer;
import org.dromara.stream.mq.TestMessaging;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.util.function.Consumer;
@Slf4j
@Component
public class LogStreamConsumer {
@Bean
Consumer<TestMessaging> log() {
log.info("初始化订阅");
return msg -> {
log.info("通过stream消费到消息 => {}", msg.toString());
};
}
}

@ -1,22 +0,0 @@
package org.dromara.stream.mq.consumer;
import org.dromara.stream.mq.TestMessaging;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.util.function.Consumer;
@Slf4j
@Component
public class TestStreamConsumer {
@Bean
Consumer<TestMessaging> demo() {
log.info("初始化订阅");
return msg -> {
log.info("通过stream消费到消息 => {}", msg.toString());
};
}
}

@ -1,27 +0,0 @@
package org.dromara.stream.mq.producer;
import org.dromara.stream.mq.TestMessaging;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
public class DelayProducer {
@Autowired
private StreamBridge streamBridge;
public void sendMsg(String msg, Long delay) {
// 构建消息对象
TestMessaging testMessaging = new TestMessaging()
.setMsgId(UUID.randomUUID().toString())
.setMsgText(msg);
Message<TestMessaging> message = MessageBuilder.withPayload(testMessaging)
.setHeader("x-delay", delay).build();
streamBridge.send("delay-out-0", message);
}
}

@ -1,24 +0,0 @@
package org.dromara.stream.mq.producer;
import org.dromara.stream.mq.TestMessaging;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
public class LogStreamProducer {
@Autowired
private StreamBridge streamBridge;
public void streamLogMsg(String msg) {
// 构建消息对象
TestMessaging testMessaging = new TestMessaging()
.setMsgId(UUID.randomUUID().toString())
.setMsgText(msg);
streamBridge.send("log-out-0", MessageBuilder.withPayload(testMessaging).build());
}
}

@ -1,24 +0,0 @@
package org.dromara.stream.mq.producer;
import org.dromara.stream.mq.TestMessaging;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
public class TestStreamProducer {
@Autowired
private StreamBridge streamBridge;
public void streamTestMsg(String msg) {
// 构建消息对象
TestMessaging testMessaging = new TestMessaging()
.setMsgId(UUID.randomUUID().toString())
.setMsgText(msg);
streamBridge.send("demo-out-0", MessageBuilder.withPayload(testMessaging).build());
}
}

@ -1,109 +0,0 @@
server:
port: 9402
# Spring
spring:
application:
# 应用名称
name: ruoyi-stream-mq
profiles:
# 环境配置
active: @profiles.active@
cloud:
stream:
function:
# 重点配置 与 binding 名与消费者对应
definition: delay;demo;log
--- # rabbitmq 配置
spring:
rabbitmq:
host: localhost
port: 5672
username: root
password: root
cloud:
stream:
rabbit:
bindings:
delay-in-0:
consumer:
delayedExchange: true
delay-out-0:
producer:
delayedExchange: true
bindings:
delay-in-0:
destination: delay.exchange.cloud
content-type: application/json
group: delay-group
binder: rabbit
delay-out-0:
destination: delay.exchange.cloud
content-type: application/json
group: delay-group
binder: rabbit
--- # rocketmq 配置
spring:
cloud:
stream:
rocketmq:
binder:
# rocketmq 地址
name-server: localhost:9876
bindings:
demo-out-0:
producer:
# 必须得写
group: default
bindings:
demo-out-0:
content-type: application/json
destination: stream-test-topic
group: test-group
binder: rocketmq
demo-in-0:
content-type: application/json
destination: stream-test-topic
group: test-group
binder: rocketmq
--- # kafka 配置
spring:
cloud:
stream:
kafka:
binder:
brokers: localhost:9092
bindings:
log-out-0:
destination: stream-log-topic
contentType: application/json
group: log_group
binder: kafka
log-in-0:
destination: stream-log-topic
contentType: application/json
group: log_group
binder: kafka
--- # nacos 配置
spring:
cloud:
nacos:
# nacos 服务地址
server-addr: @nacos.server@
username: @nacos.username@
password: @nacos.password@
discovery:
# 注册组
group: @nacos.discovery.group@
namespace: ${spring.profiles.active}
config:
# 配置组
group: @nacos.config.group@
namespace: ${spring.profiles.active}
config:
import:
- optional:nacos:application-common.yml

@ -1,10 +0,0 @@
Spring Boot Version: ${spring-boot.version}
Spring Application Name: ${spring.application.name}
_ _
(_) | |
_ __ _ _ ___ _ _ _ ______ ___| |_ _ __ ___ __ _ _ __ ___ ______ _ __ ___ __ _
| '__| | | |/ _ \| | | | |______/ __| __| '__/ _ \/ _` | '_ ` _ \______| '_ ` _ \ / _` |
| | | |_| | (_) | |_| | | \__ \ |_| | | __/ (_| | | | | | | | | | | | | (_| |
|_| \__,_|\___/ \__, |_| |___/\__|_| \___|\__,_|_| |_| |_| |_| |_| |_|\__, |
__/ | | |
|___/ |_|

@ -0,0 +1,102 @@
# ruoyi-test-mq
## 模块说明
该模块基于需求【[将spring-cloud-stream改为普通spring的mq依赖用法】下修改编写
原模块缺点:功能复杂学习成本高 大部分用户用不明白 功能封闭 特性无法使用 项目中基本不会有切换mq的事情发生
现模块集成基础的rabbit、rocketmq、kafka等主流的中间件功能包含
1. rabbit: 普通消息、延迟队列
2. rocket普通消息、事务消息
3. kafka普通消息
后续可实现的:
1. kafka stream流的使用
2. rocket 顺序、异步、延时等
## 项目目录
```xml
├─src
│ └─main
│ ├─java
│ │ └─org
│ │ └─dromara
│ │ └─stream
│ │ │ RuoYiTestMqApplication.java
│ │ │
│ │ ├─config
│ │ │ RabbitConfig.java 普通消息配置类
│ │ │ RabbitTtlQueueConfig.java 延迟队列配置类
│ │ │
│ │ ├─controller 测试类
│ │ │ PushMessageController.java
│ │ │
│ │ └─mq
│ │ ├─consumer
│ │ │ ├─kafkaMq
│ │ │ │ KafkaNormalConsumer.java
│ │ │ ├─rabbit
│ │ │ │ ConsumerListener.java
│ │ │ └─rocketmq
│ │ │ NormalRocketConsumer.java
│ │ │ TransactionRocketConsumer.java
│ │ ├─listener
│ │ │ TranscationRocketListener.java
│ │ └─producer
│ │ ├─kafkaMq
│ │ │ KafkaNormalProducer.java
│ │ ├─rabbitMq
│ │ │ DelayRabbitProducer.java
│ │ │ NormalRabbitProducer.java
│ │ └─rocketMq
│ │ NormalRocketProducer.java
│ │ TransactionRocketProducer.java
│ │
│ └─resources
│ application.yml IP:Host根据实际情况替换
│ logback-plus.xml
```
## 使用方式
rocketmq
**注意需要进入到rockerMQ文件路径中执行**
创建普通消息的topic
```sh
sh mqadmin updateTopic -n <nameserver_address> -t <topic_name> -c <cluster_name> -a +message.type=NORMAL
```
```shell
bin/mqadmin updatetopic -n localhost:9876 -t TestTopic -c DefaultCluster
```
创建事务消息的topic
```sh
sh mqadmin updateTopic -n <nameserver_address> -t <topic_name> -c <cluster_name> -a +message.type=TRANSACTION
```
```shell
bin/mqadmin updatetopic -n localhost:9876 -t transaction_topic -c DefaultCluster -a +message.type=TRANSACTION
```
kafka:
```shell
kafka-topics.sh --create --topic <topic_name> --bootstrap-server <broker_list> --partitions <num_partitions> --replication-factor <replication_factor>
```
```shell
kafka-topics.sh --create --topic my_topic --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1
```
## 验证方式
可通过`PushMessageController`实现`Restful`进行测试;

@ -9,10 +9,10 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-stream-mq</artifactId>
<artifactId>ruoyi-test-mq</artifactId>
<description>
ruoyi-stream-mq SpringCloud-Stream-MQ 案例项目
ruoyi-test-mq 案例项目
</description>
<dependencies>
@ -21,22 +21,20 @@
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-nacos</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-kafka</artifactId>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-sentinel</artifactId>

@ -5,15 +5,14 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
/**
* SpringCloud-Stream-MQ
*
* SpringBoot-MQ
* @author Lion Li
*/
@SpringBootApplication
public class RuoYiStreamMqApplication {
public class RuoYiTestMqApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(RuoYiStreamMqApplication.class);
SpringApplication application = new SpringApplication(RuoYiTestMqApplication.class);
application.setApplicationStartup(new BufferingApplicationStartup(2048));
application.run(args);
System.out.println("(♥◠‿◠)ノ゙ MQ案例模块启动成功 ლ(´ڡ`ლ)゙ ");

@ -0,0 +1,54 @@
package org.dromara.stream.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author xbhog
*/
@Configuration
public class RabbitConfig {
public static final String EXCHANGE_NAME = "demo-exchange";
public static final String QUEUE_NAME = "demo-queue";
public static final String ROUTING_KEY = "demo.routing.key";
/**
*
* ExchangeBuilder
* Direct ExchangeRouting Key()
* Fanout Exchange广
* Topic Exchange#*
* Header Exchangeheaders
* durable false true
**/
@Bean
public TopicExchange exchange() {
return new TopicExchange(EXCHANGE_NAME);
}
/**
*
* durable
* deliveryMode 1 2
**/
@Bean
public Queue queue() {
return new Queue(QUEUE_NAME, false);
}
/**
*
* bing
* to
* with Key rabbit.
* noargs
* rabbit
**/
@Bean
public Binding binding(Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY);
}
}

@ -0,0 +1,69 @@
package org.dromara.stream.config;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* RabbitTTL
* @author xbhog
*/
@Configuration
public class RabbitTtlQueueConfig {
// 延迟队列名称
public static final String DELAY_QUEUE_NAME = "delay-queue";
// 延迟交换机名称
public static final String DELAY_EXCHANGE_NAME = "delay-exchange";
// 延迟路由键名称
public static final String DELAY_ROUTING_KEY = "delay.routing.key";
// 死信交换机名称
public static final String DEAD_LETTER_EXCHANGE = "dlx-exchange";
// 死信队列名称
public static final String DEAD_LETTER_QUEUE = "dlx-queue";
// 死信路由键名称
public static final String DEAD_LETTER_ROUTING_KEY = "dlx.routing.key";
// 延迟消息的默认 TTL毫秒
@Value("${rabbitmq.delay.ttl:5000}")
private long messageTTL;
// 声明延迟队列
@Bean
public Queue delayQueue() {
return QueueBuilder.durable(DELAY_QUEUE_NAME)
.withArgument("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE)
.withArgument("x-dead-letter-routing-key", DEAD_LETTER_ROUTING_KEY)
.withArgument("x-message-ttl", messageTTL)
.build();
}
// 声明延迟交换机
@Bean
public TopicExchange delayExchange() {
return new TopicExchange(DELAY_EXCHANGE_NAME);
}
// 将延迟队列绑定到延迟交换机
@Bean
public Binding delayBinding(Queue delayQueue, TopicExchange delayExchange) {
return BindingBuilder.bind(delayQueue).to(delayExchange).with(DELAY_ROUTING_KEY);
}
// 声明死信队列
@Bean
public Queue deadLetterQueue() {
return new Queue(DEAD_LETTER_QUEUE);
}
// 声明死信交换机
@Bean
public TopicExchange deadLetterExchange() {
return new TopicExchange(DEAD_LETTER_EXCHANGE);
}
// 将死信队列绑定到死信交换机
@Bean
public Binding deadLetterBinding(Queue deadLetterQueue, TopicExchange deadLetterExchange) {
return BindingBuilder.bind(deadLetterQueue).to(deadLetterExchange).with(DEAD_LETTER_ROUTING_KEY);
}
}

@ -0,0 +1,72 @@
package org.dromara.stream.controller;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.stream.mq.producer.kafkaMq.KafkaNormalProducer;
import org.dromara.stream.mq.producer.rabbitMq.DelayRabbitProducer;
import org.dromara.stream.mq.producer.rabbitMq.NormalRabbitProducer;
import org.dromara.stream.mq.producer.rocketMq.NormalRocketProducer;
import org.dromara.stream.mq.producer.rocketMq.TransactionRocketProducer;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author xbhog
*/
@Slf4j
@RestController
@RequestMapping("push/message")
public class PushMessageController {
@Resource
private NormalRabbitProducer normalRabbitProducer;
@Resource
private DelayRabbitProducer delayRabbitProducer;
@Resource
private NormalRocketProducer normalRocketProducer;
@Resource
private TransactionRocketProducer transactionRocketProducer;
@Resource
private KafkaNormalProducer normalKafkaProducer;
/**
* rabbit
*/
@GetMapping("/rabbitMsg/sendNormal")
public void sendMq() {
normalRabbitProducer.sendMq("hello normal RabbitMsg");
}
/**
* rabbit
*/
@GetMapping("/rabbitMsg/sendDelay")
public void sendMessage() {
delayRabbitProducer.sendDelayMessage("Hello ttl RabbitMsg");
}
/**
* rockerMQ
* Topicgroup
*/
@GetMapping("/rocketMq/send")
public void sendRockerMq(){
normalRocketProducer.sendMessage();
}
@GetMapping("/rocketMq/transactionMsg")
public void sendRockerMqTransactionMsg(){
transactionRocketProducer.sendTransactionMessage();
}
/**
* kafkaSpringboot
*/
@GetMapping("/kafkaMsg/send")
public void sendKafkaMsg(){
normalKafkaProducer.sendKafkaMsg();
}
}

@ -0,0 +1,24 @@
package org.dromara.stream.mq.consumer.kafkaMq;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
/**
* @author xbhog
* @date 2024/05/19 18:04
**/
@Slf4j
@Component
public class KafkaNormalConsumer {
//默认获取最后一条消息
@KafkaListener(topics = "test-topic",groupId = "demo")
public void timiKafka(ConsumerRecord record){
Object key = record.key();
Object value = record.value();
log.info("【消费者】received the message key {}value{}",key,value);
}
}

@ -0,0 +1,36 @@
package org.dromara.stream.mq.consumer.rabbit;
import lombok.extern.slf4j.Slf4j;
import org.dromara.stream.config.RabbitConfig;
import org.dromara.stream.config.RabbitTtlQueueConfig;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* @author xbhog
* @date 2024518
*/
@Slf4j
@Component
public class ConsumerListener {
/**
* RabbitConfig
*
**/
@RabbitListener(queues = RabbitConfig.QUEUE_NAME)
public void listenQueue(Message message) {
log.info("【消费者】Start consuming data{}",new String(message.getBody()));
}
/**
*
* TTl
*
*/
@RabbitListener(queues = RabbitTtlQueueConfig.DEAD_LETTER_QUEUE)
public void receiveMessage(String message){
log.info("【消费者】Received delayed message{}",message);
}
}

@ -0,0 +1,20 @@
package org.dromara.stream.mq.consumer.rocketmq;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Component;
/**
* @author xbhog
* @date 2024/06/01 16:53
**/
@Slf4j
@Component
@RocketMQMessageListener(topic = "TestTopic", consumerGroup = "springboot-mq-consumer-1")
public class NormalRocketConsumer implements RocketMQListener<String> {
@Override
public void onMessage(String message) {
log.info("【消费者】接收消息:{}" ,message);
}
}

@ -0,0 +1,21 @@
package org.dromara.stream.mq.consumer.rocketmq;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Component;
/**
* @author xbhog
* @date 2024/06/01 16:54
**/
@Slf4j
@Component
@RocketMQMessageListener(consumerGroup = "transaction-group", topic = "transaction_topic")
public class TransactionRocketConsumer implements RocketMQListener<String> {
@Override
public void onMessage(String message) {
log.info("【消费者】===>接收事务消息:{}",message);
}
}

@ -0,0 +1,42 @@
package org.dromara.stream.mq.listener;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;
/**
* @author xbhog
* @date 2024/06/01 17:05
**/
@Slf4j
@Component
@RocketMQTransactionListener
public class TranscationRocketListener implements RocketMQLocalTransactionListener {
@Override
public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {
log.info("执行本地事务");
String tag = String.valueOf(message.getHeaders().get("rocketmq_TAGS"));
if ("TAG-1".equals(tag)) {
//这里只讲TAGA消息提交状态为可执行
log.info("【监听器】这里是校验TAG-1;提交状态:COMMIT");
return RocketMQLocalTransactionState.COMMIT;
} else if ("TAG-2".equals(tag)) {
log.info("【监听器】这里是校验TAG-2;提交状态:ROLLBACK");
return RocketMQLocalTransactionState.ROLLBACK;
} else if ("TAG-3".equals(tag)) {
log.info("【监听器】这里是校验TAG-3;提交状态:UNKNOWN");
return RocketMQLocalTransactionState.UNKNOWN;
}
log.info("=========【监听器】提交状态:UNKNOWN");
return RocketMQLocalTransactionState.UNKNOWN;
}
@Override
public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
log.info("【监听器】检查本地交易===>{}", message);
return RocketMQLocalTransactionState.COMMIT;
}
}

@ -0,0 +1,24 @@
package org.dromara.stream.mq.producer.kafkaMq;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.CompletableFuture;
/**
* @author xbhog
* @date 2024/05/19 18:02
**/
@Slf4j
@Component
public class KafkaNormalProducer {
@Resource
private KafkaTemplate kafkaTemplate;
public void sendKafkaMsg(){
CompletableFuture send = kafkaTemplate.send("test-topic","hello", "kafkaTest");
send.join();
}
}

@ -0,0 +1,25 @@
package org.dromara.stream.mq.producer.rabbitMq;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.stream.config.RabbitTtlQueueConfig;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @author xbhog
* @date 2024/05/25 17:15
**/
@Slf4j
@Component
public class DelayRabbitProducer {
@Resource
private RabbitTemplate rabbitTemplate;
@GetMapping("/sendDelay")
public void sendDelayMessage(String message) {
rabbitTemplate.convertAndSend(RabbitTtlQueueConfig.DELAY_EXCHANGE_NAME, RabbitTtlQueueConfig.DELAY_ROUTING_KEY, message);
log.info("【生产者】Delayed message send: " + message);
}
}

@ -0,0 +1,24 @@
package org.dromara.stream.mq.producer.rabbitMq;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.stream.config.RabbitConfig;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
/**
* @author xbhog
*/
@Slf4j
@Component
public class NormalRabbitProducer {
@Resource
RabbitTemplate rabbitTemplate;
public void sendMq(String message) {
rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_NAME, RabbitConfig.ROUTING_KEY, message);
log.info("【生产者】Message send: " + message);
}
}

@ -0,0 +1,25 @@
package org.dromara.stream.mq.producer.rocketMq;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
/**
* @author xbhog
* @date 2024/06/01 16:49
**/
@Slf4j
@Component
public class NormalRocketProducer {
@Resource
private RocketMQTemplate rocketMQTemplate;
public void sendMessage(){
SendResult sendResult = rocketMQTemplate.syncSend("TestTopic", MessageBuilder.withPayload("hello world test").build());
log.info("发送普通同步消息-msgsyncSendMessage===>{}", sendResult);
}
}

@ -0,0 +1,41 @@
package org.dromara.stream.mq.producer.rocketMq;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
/**
* @author xbhog
* @date 2024/06/01 16:54
**/
@Slf4j
@Component
public class TransactionRocketProducer {
@Resource
private RocketMQTemplate rocketMQTemplate;
public void sendTransactionMessage(){
List<String> tags = Arrays.asList("TAG-1", "TAG-2", "TAG-3");
for (int i = 0; i < 3; i++) {
Message<String> message = MessageBuilder.withPayload("===>事务消息-" + i).build();
//destination formats: `topicName:tags` message message Message arg ext arg
TransactionSendResult res = rocketMQTemplate.sendMessageInTransaction("transaction_topic:" + tags.get(i), message, i + 1);
if (res.getLocalTransactionState().equals(LocalTransactionState.COMMIT_MESSAGE) && res.getSendStatus().equals(SendStatus.SEND_OK)) {
log.info("【生产者】事物消息发送成功;成功结果:{}",res);
}else{
log.info("【生产者】事务发送失败:失败原因:{}",res);
}
}
}
}

@ -0,0 +1,44 @@
server:
port: 9402
# Spring
spring:
application:
# 应用名称
name: ruoyi-test-mq
profiles:
# 环境配置
active: @profiles.active@
#MQ配置
rabbitmq:
host: 192.168.1.13
port: 5672
username: mq
password: mq
publisher-returns: true
publisher-confirm-type: correlated
kafka:
bootstrap-servers: 192.168.1.13:9092
producer:
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
rocketmq:
name-server: 192.168.1.13:9876
producer:
group: dist-test # 生产者组
--- # nacos 配置
spring:
cloud:
nacos:
# nacos 服务地址
server-addr: @nacos.server@
discovery:
# 注册组
group: @nacos.discovery.group@
namespace: ${spring.profiles.active}
config:
# 配置组
group: @nacos.config.group@
namespace: ${spring.profiles.active}
config:
import:
- optional:nacos:application-common.yml

@ -19,7 +19,8 @@
<!-- 开启 skywalking 日志收集 -->
<include resource="logback-skylog.xml" />
<!--系统操作日志-->
<!--系统操作日志-->
<root level="info">
<appender-ref ref="console" />
</root>
Loading…
Cancel
Save