Spring boot框架下的RocketMQ消息中间件
1. RocketMQ 基础概念
1.1 核心概念
以下是 RocketMQ 核心概念在 Spring Boot 的 Java 后端代码中的实际使用方式:
Producer(生产者)
定义:Producer 是负责发送消息到 RocketMQ 的组件。它可以将消息发送到指定的 Topic。
实际代码: 使用 RocketMQTemplate
提供的 API 发送消息。
@Service
public class DemoProducer {@Autowiredprivate RocketMQTemplate rocketMQTemplate;public void sendMessage(String topic, String message) {rocketMQTemplate.convertAndSend(topic, message);System.out.println("Message sent to topic: " + topic);}
}
Consumer(消费者)
定义:Consumer 是负责接收和处理从 RocketMQ 中接收到的消息的组件。
实际代码: 使用 @RocketMQMessageListener
注解标注的类来实现消费者功能。
@Service
@RocketMQMessageListener(topic = "demo-topic", consumerGroup = "demo-consumer-group")
public class DemoConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Received message: " + message);}
}
Topic(主题)
定义:Topic 是消息分类的基本单元,Producer 将消息发送到 Topic,Consumer 从 Topic 中接收消息。
实际代码: Topic 是通过代码中指定的字符串定义的,例如 demo-topic
。
- Producer 中指定 Topic:
rocketMQTemplate.convertAndSend("demo-topic", "Hello RocketMQ!");
- Consumer 中监听 Topic:
@RocketMQMessageListener(topic = "demo-topic", consumerGroup = "demo-consumer-group")
Message(消息)
定义:消息是 Producer 发送到 Topic 的载体,包含消息体和属性。
实际代码示例:
- 发送简单文本消息:
rocketMQTemplate.convertAndSend("demo-topic", "Hello RocketMQ!");
- 发送带属性的消息:
Message message = MessageBuilder.withPayload("Hello with properties").setHeader("key", "value").build(); rocketMQTemplate.syncSend("demo-topic", message);
1.2 消息模型
点对点(Queue)模型
定义:
-
每条消息只能被一个消费者(Consumer)消费。
-
消息会被存储在一个队列(Queue)中,消费者从队列中拉取消息。
-
适合任务分发、负载均衡等场景。
特点:
-
消息独占性:一条消息只能被一个消费者消费。
-
负载均衡:如果有多个消费者属于同一个消费者组(Consumer Group),消息会均匀分配给组内的消费者。
-
消息顺序性:在 RocketMQ 中,队列(Queue)是 Topic 的底层实现,每个 Queue 内的消息是有序的。
实现:
-
在 RocketMQ 中,Queue 是 Topic 的底层实现,开发者无需直接配置 Queue,只需关注 Topic 和 Consumer Group。
-
多个消费者属于同一个 Consumer Group 时,消息会按照负载均衡策略分配给组内的消费者。
发布订阅(Topic)模型
定义:
-
消息会被广播给所有订阅了该 Topic 的消费者。
-
每个消费者都会收到相同的消息。
-
适合广播通知、事件分发等场景。
特点:
-
消息广播:一条消息会被发送给所有订阅了该 Topic 的消费者。
-
消费者独立性:每个消费者独立消费消息,彼此之间没有影响。
-
无负载均衡:所有消费者都会收到相同的消息,而不是分配不同的消息。
实现:
-
在 RocketMQ 中,可以通过设置
MessageModel.BROADCASTING
来实现广播消费。 -
每个消费者都会收到 Topic 中的所有消息。
示例:在 Spring Boot 中实现广播消费
@RocketMQMessageListener(topic = "broadcast-topic",consumerGroup = "broadcast-group",messageModel = MessageModel.BROADCASTING
)
public class BroadcastConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Broadcast received: " + message);}
}
两者的核心区别
特性 | 点对点(Queue)模型 | 发布订阅(Topic)模型 |
---|---|---|
消息消费方式 | 一条消息只能被一个消费者消费 | 一条消息会被所有消费者消费 |
负载均衡 | 支持,消息会均匀分配给组内的消费者 | 不支持,所有消费者收到相同消息 |
适用场景 | 任务分发、订单处理等需要负载均衡的场景 | 广播通知、事件分发等需要广播的场景 |
消费者组的作用 | 组内消费者共享消息,实现负载均衡 | 组内消费者各自独立消费所有消息 |
消息顺序性 | 单个 Queue 内的消息是有序的 | 无顺序性,所有消费者收到相同消息 |
2. 环境准备
2.1 安装与运行 RocketMQ
1. 下载 RocketMQ
-
访问 RocketMQ 的官方 GitHub 仓库:Apache RocketMQ GitHub
-
下载最新版本的 RocketMQ 二进制包(例如:
rocketmq-all-x.x.x-bin-release.zip
)。 -
解压下载的文件
2. 启动 NameServer
-
NameServer 是 RocketMQ 的注册中心,负责管理 Broker 的路由信息。
-
启动 NameServer:
sh bin/mqnamesrv &
-
检查 NameServer 是否启动成功:查看日志文件
logs/rocketmqlogs/namesrv.log
,确认是否有以下内容:The Name Server boot success...
3. 启动 Broker
-
Broker 是 RocketMQ 的消息存储和转发服务器。
-
启动 Broker,并指定 NameServer 地址:
sh bin/mqbroker -n localhost:9876 autoCreateTopicEnable=true &
-
-n localhost:9876
:指定 NameServer 的地址。 -
autoCreateTopicEnable=true
:允许自动创建 Topic。
-
-
检查 Broker 是否启动成功:
-
查看日志文件
logs/rocketmqlogs/broker.log
,确认是否有以下内容:The broker boot success...
-
4. 验证 RocketMQ 运行状态
-
使用 RocketMQ 提供的工具命令检查服务状态:
sh bin/mqadmin clusterList -n localhost:9876
- 如果看到 Broker 和 NameServer 的信息,说明 RocketMQ 已成功启动。
2.2 RocketMQ Dashboard
RocketMQ Dashboard 是一个可视化管理工具,用于监控和管理 RocketMQ 的 Topic、Producer、Consumer 等信息。
1. 下载 RocketMQ Dashboard
-
访问 RocketMQ Dashboard 的官方 GitHub 仓库:RocketMQ Dashboard GitHub
-
下载最新版本的 Dashboard 二进制包(例如:
rocketmq-dashboard-x.x.x.jar
)。
2. 部署 RocketMQ Dashboard
-
使用以下命令启动 Dashboard:
java -jar rocketmq-dashboard-x.x.x.jar
-
默认情况下,Dashboard 会监听
8080
端口。
3. 访问 RocketMQ Dashboard
-
打开浏览器,访问
http://localhost:8080
。 -
在 Dashboard 页面中,配置 NameServer 地址(例如:
localhost:9876
),然后点击连接。
4. 监控和管理 RocketMQ
-
Topic 管理:查看所有 Topic 的详细信息,包括消息堆积情况、生产者、消费者等。
-
Producer 管理:查看生产者的运行状态和消息发送情况。
-
Consumer 管理:查看消费者的运行状态和消息消费情况。
-
消息查询:支持按 Message ID、Topic、Key 等条件查询消息。
-
集群状态:查看 NameServer 和 Broker 的运行状态。
3. Spring Boot 集成 RocketMQ 的依赖配置
3.1 添加依赖
在 pom.xml
文件中添加 Spring Boot 提供的 RocketMQ 集成 Starter 依赖:
<dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.2.1</version> <!-- 确保版本为你需要的最新稳定版 -->
</dependency>
3.2 配置文件
在 application.properties
或 application.yml
中配置 RocketMQ 的相关属性。
# 指定 RocketMQ NameServer 地址
rocketmq.name-server=127.0.0.1:9876# 配置生产者组名称
rocketmq.producer.group=demo_producer_group# 配置消费者组名称
rocketmq.consumer.group=demo_consumer_group
配置项说明
配置项 | 说明 |
---|---|
rocketmq.name-server | RocketMQ NameServer 的地址,格式为 IP:Port ,例如 127.0.0.1:9876 。 支持集群地址,多个地址用分号分隔,例如:127.0.0.1:9876;127.0.0.2:9876。 |
rocketmq.producer.group | 生产者组的名称,用于标识一组生产者。 |
rocketmq.consumer.group | 消费者组的名称,用于标识一组消费者。 |
rocketmq.access-key | 如果使用阿里云 RocketMQ,需要配置 Access Key。 |
rocketmq.secret-key | 如果使用阿里云 RocketMQ,需要配置 Secret Key。 |
rocketmq.send-message-timeout | 生产者发送消息的超时时间,默认值为 3000 (单位:毫秒)。 |
rocketmq.consumer.consume-thread-nums | 消费者消费消息的线程数,默认值为 |
rocketmq.consumer.maxReconsumeTimes | 自定义重试次数,消息消费失败会自动重试,默认最大重试次数为 16 次(包括第一次消费) |
4. Spring Boot 集成 RocketMQ 的消息生产与消费
RocketMQTemplate 是否需要定义为 Bean?
-
不需要手动定义:在 Spring Boot 项目中,
RocketMQTemplate
已经由rocketmq-spring-boot-starter
自动配置为 Bean,因此可以直接通过@Autowired
注入使用。 -
自动配置原理:
-
rocketmq-spring-boot-starter
会在启动时自动创建RocketMQTemplate
的实例。 -
只要在
application.properties
或application.yml
中正确配置了 RocketMQ 的相关参数(如rocketmq.name-server
),Spring Boot 就会自动完成初始化。
-
发送非 String 类型的消息
-
支持任意类型:
RocketMQTemplate
支持发送任意类型的消息,包括 POJO(普通 Java 对象)。 -
实现方式:
-
RocketMQ 会自动将消息序列化为 JSON 格式(默认使用 Jackson)。
-
消费者接收时,RocketMQ 会自动将 JSON 反序列化为对应的 Java 对象。
-
示例代码
发送 POJO 消息:
public class User {private String name;private int age;// 省略 getter 和 setter
}// 生产者
public void sendUserMessage(String topic, User user) {rocketMQTemplate.convertAndSend(topic, user);System.out.println("Sent user message: " + user);
}
消费 POJO 消息:
@Service
@RocketMQMessageListener(topic = "user_topic",consumerGroup = "user_consumer_group"
)
public class UserConsumer implements RocketMQListener<User> {@Overridepublic void onMessage(User user) {System.out.println("Received user message: " + user.getName() + ", age: " + user.getAge());}
}
4.1 消息生产(Producer)
一般会定义一个消息生产者类,然后其他类调用这个类包装好的消息发送方法。
发送普通消息
使用场景:发送简单的文本或对象消息。
实现方式:使用 RocketMQTemplate.convertAndSend(topic, message)
方法发送消息。
示例代码:
@Autowired
private RocketMQTemplate rocketMQTemplate;public void sendSimpleMessage(String topic, String message) {rocketMQTemplate.convertAndSend(topic, message);System.out.println("Sent simple message: " + message);
}
发送带 Tag 的消息
使用场景:通过 Tag 对消息进行分类,消费者可以根据 Tag 过滤消息。
实现方式:在 Topic 后添加 :Tag
。消息目的地的格式为:topic:tag
。
示例代码:
public void sendMessageWithTag(String topic, String tag, String message) {String destination = topic + ":" + tag; // 格式:topic:tagrocketMQTemplate.convertAndSend(destination, message);System.out.println("Sent message with tag: " + message);
}
发送同步消息
使用场景:需要确保消息成功发送到 Broker 的场景。
实现方式:使用 RocketMQTemplate.syncSend(destination, message)
方法。
示例代码:
public void sendSyncMessage(String topic, String message) {SendResult sendResult = rocketMQTemplate.syncSend(topic, message);System.out.println("Sync message sent, result: " + sendResult);
}
发送异步消息
使用场景:不需要立即确认消息是否发送成功,通过回调处理发送结果。
实现方式:使用 RocketMQTemplate.asyncSend(destination, message, sendCallback)
方法。
示例代码:
public void sendAsyncMessage(String topic, String message) {rocketMQTemplate.asyncSend(topic, message, new SendCallback() {@Overridepublic void onSuccess(SendResult sendResult) {System.out.println("Async message sent successfully: " + sendResult);}@Overridepublic void onException(Throwable throwable) {System.err.println("Async message send failed: " + throwable.getMessage());}});
}
发送单向消息
使用场景:适用于不需要确认的日志、监控等场景。
实现方式:
使用 RocketMQTemplate.sendOneWay(destination, message)
方法。
示例代码:
public void sendOneWayMessage(String topic, String message) {rocketMQTemplate.sendOneWay(topic, message);System.out.println("One-way message sent: " + message);
}
4.2 消息消费(Consumer)
基础消费逻辑
实现方式:
-
实现
RocketMQListener
接口:-
消费者类必须实现
RocketMQListener<T>
接口,并指定泛型类型(如String
或自定义 POJO)。
-
-
重写
onMessage
方法:-
在
onMessage
方法中编写消息处理逻辑。
-
-
使用
@RocketMQMessageListener
注解:-
通过注解指定监听的 Topic 和 Consumer Group。
-
示例代码:
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;@Service
@RocketMQMessageListener(topic = "demo_topic", // 监听的 TopicconsumerGroup = "demo_consumer_group" // 消费者组名称
)
public class DemoConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Received message: " + message);}
}
消费消息的确认机制
自动确认:
RocketMQ 默认会自动确认消息(ACK),消费者成功消费消息后,Broker 会认为消息已处理。
手动确认:
如果需要手动确认消息,可以使用 RocketMQListener<MessageExt>
并调用 ack
方法。
消费失败的处理
重试机制:
-
如果消费者消费消息失败,RocketMQ 会尝试重新投递消息。
-
默认重试次数为 16 次,重试间隔逐渐增加。
死信队列:
-
如果消息重试多次后仍然失败,会被投递到死信队列(DLQ,Dead Letter Queue)。
-
死信队列的命名规则为:
%DLQ% + Consumer Group
。
-
自动创建:
-
RocketMQ 会自动为每个 Consumer Group 创建一个死信队列,无需手动配置。
-
例如,如果 Consumer Group 为
demo_consumer_group
,则死信队列的topic为%DLQ%demo_consumer_group
。
-
-
手动消费死信队列:
-
可以创建一个消费者,专门消费死信队列中的消息。
-
@Service
@RocketMQMessageListener(topic = "%DLQ%demo_consumer_group", // 死信队列名称consumerGroup = "dlq_consumer_group" // 死信队列的消费者组
)
public class DLQConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Received DLQ message: " + message);// 处理死信消息,例如记录日志或人工干预}
}
消费带 Tag 的消息
实现方式:
在 @RocketMQMessageListener
中指定 selectorExpression
来过滤 Tag。
示例代码:
@Service
@RocketMQMessageListener(topic = "demo_topic",consumerGroup = "demo_consumer_group",selectorExpression = "tagA || tagB" // 过滤 Tag
)
public class TagConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Received tagged message: " + message);}
}
顺序消费
-
RocketMQ 默认是并发消费,不保证消息的顺序性。
-
顺序消费是指消息按照发送顺序被消费,适用于对消息顺序有严格要求的场景。
-
实现顺序消费需要:
-
生产者发送消息时指定相同的消息组。
-
消费者设置
consumeMode = ConsumeMode.ORDERLY
。
-
-
顺序消费的实现依赖于队列的顺序性和消费者的单线程消费。
示例代码:
@Service
@RocketMQMessageListener(topic = "demo_topic",consumerGroup = "demo_consumer_group",consumeMode = ConsumeMode.ORDERLY // 顺序消费
)
public class OrderlyConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Received orderly message: " + message);}
}
5. Spring Boot 集成 RocketMQ 的高级功能
5.1 延时消息
延时消息是指消息发送后,不会立即被消费者消费,而是在指定的延迟时间后才会被投递。RocketMQ 提供了 18 个固定的延迟级别,每个级别对应不同的延迟时间。
延迟级别与时间对应关系
延迟级别 | 延迟时间 |
---|---|
1 | 1 秒 |
2 | 5 秒 |
3 | 10 秒 |
4 | 30 秒 |
5 | 1 分钟 |
6 | 2 分钟 |
7 | 3 分钟 |
8 | 4 分钟 |
9 | 5 分钟 |
10 | 6 分钟 |
11 | 7 分钟 |
12 | 8 分钟 |
13 | 9 分钟 |
14 | 10 分钟 |
15 | 20 分钟 |
16 | 30 分钟 |
17 | 1 小时 |
18 | 2 小时 |
使用场景
-
订单超时未支付取消。
-
定时任务触发。
-
延迟通知。
实现步骤
-
构建消息:使用
MessageBuilder
构建消息,并设置MessageConst.PROPERTY_DELAY_TIME_LEVEL
属性与等级值。 -
发送消息:使用
RocketMQTemplate.syncSend
发送消息。
示例代码
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.apache.rocketmq.common.message.MessageConst;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;@Service
public class DelayedMessageProducer {@Autowiredprivate RocketMQTemplate rocketMQTemplate;/*** 发送延迟消息** @param topic 主题* @param message 消息内容* @param delayLevel 延迟级别(1-18)*/public void sendDelayedMessage(String topic, String message, int delayLevel) {// 构建消息,设置延迟级别Message<String> msg = MessageBuilder.withPayload(message).setHeader(MessageConst.PROPERTY_DELAY_TIME_LEVEL, String.valueOf(delayLevel)).build();// 发送延迟消息rocketMQTemplate.syncSend(topic, msg);System.out.println("Sent delayed message: " + message + ", delay level: " + delayLevel);}
}
调用消息生产者发送消息
delayedMessageProducer.sendDelayedMessage("my-topic", "Delayed Message", 3); // 延迟 10 秒
5.2 事务消息
事务消息用于实现分布式事务,确保业务操作和消息发送的一致性。RocketMQ 的事务消息分为两个阶段:
-
发送半消息:消息发送到 Broker,但暂时对消费者不可见。
-
提交或回滚:根据本地事务的执行结果,提交或回滚消息。
使用场景
-
分布式事务场景,例如订单创建和库存扣减。
-
需要保证业务操作和消息发送一致性的场景。
实现步骤
-
定义事务监听器:实现
RocketMQLocalTransactionListener
接口,定义本地事务逻辑和回查逻辑。 -
使用注解@RocketMQTransactionListener:通过
txProducerGroup
属性指定事务组的名称。事务组的名称必须与发送事务消息时指定的txProducerGroup
一致。txProducerGroup
是事务组的唯一标识,用于关联生产者和事务监听器。 -
发送事务消息:使用
rocketMQTemplate.sendMessageInTransaction
方法发送事务消息。
示例代码
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;@Component
@RocketMQTransactionListener(txProducerGroup = "my-transaction-group")
public class MyTransactionListener implements RocketMQLocalTransactionListener {/*** 执行本地事务** @param msg 消息* @param arg 附加参数* @return 事务状态*/@Overridepublic RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {try {// 执行本地事务System.out.println("Executing local transaction: " + msg.getPayload());// 模拟业务操作成功return RocketMQLocalTransactionState.COMMIT;} catch (Exception e) {// 本地事务执行失败,回滚消息return RocketMQLocalTransactionState.ROLLBACK;}}/*** 回查本地事务状态** @param msg 消息* @return 事务状态*/@Overridepublic RocketMQLocalTransactionState checkLocalTransaction(Message msg) {// 回查本地事务状态System.out.println("Checking local transaction: " + msg.getPayload());return RocketMQLocalTransactionState.COMMIT;}
}
checkLocalTransaction
是 RocketMQLocalTransactionListener
接口中的一个方法,用于 回查本地事务的状态。它的作用是:
事务状态回查:
-
如果生产者发送事务消息后,未及时返回本地事务的执行结果,RocketMQ 会调用
checkLocalTransaction
方法回查事务状态。
返回事务状态:根据回查结果,返回 RocketMQLocalTransactionState
枚举值:
-
COMMIT
:提交事务,消息对消费者可见。 -
ROLLBACK
:回滚事务,消息被丢弃。 -
UNKNOWN
:事务状态未知,RocketMQ 会继续回查。
定义消息生产者发送事务消息
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;@Service
public class TransactionMessageProducer {@Autowiredprivate RocketMQTemplate rocketMQTemplate;/*** 发送事务消息** @param topic 主题* @param message 消息内容*/public void sendTransactionMessage(String topic, String message) {// 构建消息Message<String> msg = MessageBuilder.withPayload(message).build();// 发送事务消息rocketMQTemplate.sendMessageInTransaction("my-transaction-group", topic, msg, null);System.out.println("Sent transaction message: " + message);}
}
-
withPayload(message)
:设置消息的有效负载(Payload),即消息的内容。 -
message
可以是任意类型的对象,RocketMQ 会自动将其序列化为字节数组。
调用消息生产者发送消息
transactionMessageProducer.sendTransactionMessage("my-topic", "Transaction Message");
5.3 消息过滤
RocketMQ 支持通过 Tag 或 SQL92 表达式 过滤消息,消费者可以只接收符合条件的消息。
使用 Tag 过滤
-
Tag 是消息的标签,用于对消息进行分类。
-
消费者可以订阅指定 Tag 的消息。
示例代码
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;@Service
@RocketMQMessageListener(topic = "my-topic",consumerGroup = "my-consumer-group",selectorExpression = "tagA || tagB" // 过滤 Tag
)
public class TagFilterConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Received filtered message: " + message);}
}
生产者发送带 Tag 的消息
public void sendMessageWithTag(String topic, String tag, String message) {String destination = topic + ":" + tag; // 格式:topic:tagrocketMQTemplate.syncSend(destination, message);System.out.println("Sent message with tag: " + message);
}
使用 SQL92 表达式过滤
-
SQL92 表达式 可以根据消息的属性进行更复杂的过滤。
-
需要在 Broker 配置中启用 SQL92 过滤功能。
示例代码
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.annotation.SelectorType;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;@Service
@RocketMQMessageListener(topic = "my-topic",consumerGroup = "my-consumer-group",selectorType = SelectorType.SQL92, // 使用 SQL92 过滤selectorExpression = "age > 18" // 过滤条件
)
public class SqlFilterConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Received SQL filtered message: " + message);}
}
生产者发送消息时设置属性
public void sendMessageWithProperties(String topic, String message) {Message<String> msg = MessageBuilder.withPayload(message).setHeader("age", 20) // 设置消息属性.build();rocketMQTemplate.syncSend(topic, msg);System.out.println("Sent message with properties: " + message);
}
相关文章:
Spring boot框架下的RocketMQ消息中间件
1. RocketMQ 基础概念 1.1 核心概念 以下是 RocketMQ 核心概念在 Spring Boot 的 Java 后端代码中的实际使用方式: Producer(生产者) 定义:Producer 是负责发送消息到 RocketMQ 的组件。它可以将消息发送到指定的 Topic。 实…...
http转化为https生成自签名证书
背景 项目开发阶段前后交互采用http协议,演示环境采用htttps协议 ,此处为个人demo案例 组件 后端:springBoot 前端:vue web 服务:tomcat 部署环境:linux 生成自签名证书 创建目录 存储证书位置 # mkdir -p…...
关于2025年智能化招聘管理系统平台发展趋势
2025年,招聘管理领域正站在变革的十字路口,全新的技术浪潮与不断变化的职场生态相互碰撞,促使招聘管理系统成为重塑企业人才战略的关键力量。智能化招聘管理系统平台在这一背景下迅速崛起,其发展趋势不仅影响企业的招聘效率与质量…...
CentOS 9 Stream 上安装 Node.js 18.20.5
要在 CentOS 9 Stream 上安装 Node.js 18.20.5,可以按照以下步骤操作: 1. 安装依赖 首先,确保你已经更新了系统并安装了必要的依赖包。 sudo dnf update -y sudo dnf install -y gcc-c make2. 安装 Node.js 18.20.5 Node.js 官方提供了一…...
NSIS 创建一键安装程序
nsis 安装redis 、mysql 、jdk navicat、 notepad、 使用NSIS 创建一键安装程序 分为两步 下载 NSIS编写 一键安装代码 1.16脚本 ; 请求管理员权限运行安装程序 RequestExecutionLevel admin; 该脚本使用 HM VNISEdit 脚本编辑器向导产生; 安装程序初始定义常量 !define PRO…...
NanoKVM简单开箱测评和拆解,让普通电脑实现BMC/IPMI远程管理功能
Sipeed推出了NanoKVM,简直是没有BMC的台式机和工作站的福音。有了这个就可以轻松实现以往服务器才有的远程管理功能。 NanoKVM 简介 Lichee NanoKVM 是基于 LicheeRV Nano 的 IP-KVM 产品,继承了 LicheeRV Nano 的极致体积 和 强大功能。 NanoKVM 包含…...
【混合开发】CefSharp+Vue桌面应用程序开发
为什么选择CefSharpVue做桌面应用程序 CefSharp 基于 Chromium Embedded Framework (CEF) ,它可以将 Chromium 浏览器的功能嵌入到 .NET 应用程序中。通过 CefSharp,开发者可以在桌面应用程序中集成 Web 技术,包括 HTML、JavaScript、CSS 等…...
2024最新版JavaScript逆向爬虫教程-------基础篇之Chrome开发者工具学习
目录 一、打开Chrome DevTools的三种方式二、Elements元素面板三、Console控制台面板四、Sources面板五、Network面板六、Application面板七、逆向调试技巧 7.1 善用搜索7.2 查看请求调用堆栈7.3 XHR 请求断点7.4 Console 插桩7.5 堆内存函数调用7.6 复制Console面板输出 工…...
下定决心不去读研了。。。
大家好,我是苍何。 之前发表过一篇文章,表达了自己读研的困惑和纠结,得到了大家很多的建议,也引起了很多人的共鸣,在留言区分享了自己的故事,看着这些故事,我觉得都够苍何写一部小说了。 可惜苍…...
Java21 正则表达式
在 Java 21 中,正则表达式主要通过 java.util.regex 包提供支持,其核心组件包括 Pattern、Matcher 和 String 类中自带的方法(如 replaceAll 和 matches)。以下是关于正则表达式在 Java 21 中的详细介绍及一些新的特性或用法。 核…...
Docker安装PostGreSQL docker安装PostGreSQL 完整详细教程
Docker安装PostGreSQL docker安装PostGreSQL 完整详细教程 Docker常用命令大全Docker 运行命令生成Docker 上安装 PostGreSQL 14.15 的步骤:1、拉取 PostGreSQL 14.15 镜像2、创建并运行容器3、测试连接4、设置所有IP都可以运行连接进入容器内 修改配置文件关闭容器…...
leetcode:205. 同构字符串(python3解法)
难度:简单 给定两个字符串 s 和 t ,判断它们是否是同构的。 如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。 每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字…...
【Javascript Day9】对象定义、数组中对象元素排序、对象在内存中存储方法、对象构建联系
目录 . 取值运算符 > 用于对象属性或方法的调用操作 [] 取值运算符 > 可用于数组下标或者对象属性的取值操作 数组对象的排序 对象在内存中存储方式 对象的三种定义方式 1. 字面量对象 2. 基于Object构造对象 3. 自定义对象构造器创建对象 对象的构建练习 . 取值…...
运维作业一
1、shell 脚本写出检测 /tmp/size.log 文件如果存在显示它的内容,不存在则创建一个文件将创建时间写入。 2、写一个 shel1 脚本,实现批量添加 20个用户,用户名为user01-20,密码为user 后面跟5个随机字符。 首先,获得随机字符,需下载pwgen&am…...
数仓建模(三)建模三步走:需求分析、模型设计与数据加载
本文包含: 数据仓库的背景与重要性数据仓库建模的核心目标本文结构概览:需求分析、模型设计与数据加载 目录 第一部分:需求分析 1.1 需求分析的定义与目标 1.2 需求分析的步骤 1.2.1 业务需求收集 1.2.2 技术需求分析 1.2.3 成果输出…...
C语言的网络编程
C语言的网络编程 引言 随着互联网的快速发展,网络编程已经成为计算机科学与技术领域中不可或缺的一部分。C语言作为一种底层语言,以其高效、快速和灵活的特性,广泛应用于网络编程中。本文将深入探讨C语言在网络编程中的应用,包括…...
EE213 Lab3 virtuoso NAND NOR INV XOR HA designlayout(min size layout method)
目录 0 前言 1 设计目标 2 减小面积的layout画法 3 NAND 4 NOR 5 INV 6 XOR 7 HA 0 前言 记录一下来到skd上的强度比较大的一门课,数字集成电路2的lab设计还是蛮好的,该帖非详细教程只是单纯的写一些思虑并用作笔记,新手小白欢迎交…...
Qt——QTableWidget 限制单元格输入范围的方法(正则表达式输入校验法、自定义代理类MyItemDelegrate)
【系列专栏】:博主结合工作实践输出的,解决实际问题的专栏,朋友们看过来! 《项目案例分享》 《极客DIY开源分享》 《嵌入式通用开发实战》 《C++语言开发基础总结》 《从0到1学习嵌入式Linux开发》...
mono3d汇总
lidar坐标系 lidar坐标系可以简单归纳为标准lidar坐标系和nucense lidar坐标系,参考链接。这个坐标系和车辆的ego坐标系是一致的。 标准lidar坐标系 opendet3d,mmdetection3d和kitt都i使用了该坐标系 up z^ x front| /| /left y <------ 0kitti采…...
机器学习第一道菜(一):线性回归的理论模型
机器学习第一道菜(一):线性回归的理论模型 一、问题:千金买笑1.1 散点图1.2 机器学习能搞啥 二、模型的建立2.1 线性回归2.2 回归模型 前面讲了机器学习的“四大绝技”,今天,开始研究第一绝技“回归”&…...
Unity的Transform类
1.position 游戏对象的世界坐标以(0, 0, 0)为原点 2.localPosition 本地坐标,相对父物体坐标 3.eulerAngles 相对世界的欧拉角 4.localEulerAngles 本地欧拉角 5.rotation 相对世界四元数 6.localRotation 本地四元…...
指针的进阶
指针的主题,我们在初级阶段的《指针》章节已经接触过了,我们知道了指针的概念: 1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。 2. 指针的大小是固定的4/8个字节(32位平台/64位平台࿰…...
每日学习30分轻松掌握CursorAI:Cursor插件系统与扩展功能
Cursor插件系统与扩展功能 一、课程概述 今天我们将学习Cursor AI的插件系统,了解如何通过插件扩展和增强IDE功能。由于Cursor AI基于VS Code开发,我们可以利用丰富的VS Code插件生态系统。 1.1 学习目标 了解插件系统原理掌握插件安装管理使用常用开…...
【WEB】网络传输中的信息安全 - 加密、签名、数字证书与HTTPS
文章目录 1. 概述2. 网络传输安全2.1.什么是中间人攻击2.2. 加密和签名2.2.1.加密算法2.2.2.摘要2.2.3.签名 2.3.数字证书2.3.1.证书的使用2.3.2.根证书2.3.3.证书链 2.4.HTTPS 1. 概述 本篇主要是讲解讲一些安全相关的基本知识(如加密、签名、证书等)&…...
Dexie.js内存管理技巧:在大型数据集操作中避免浏览器崩溃
Dexie.js 内存管理技巧:避免浏览器崩溃 在使用 Dexie.js 操作 大型数据集 时,如果不注意内存管理,可能会导致浏览器内存溢出(OOM,Out of Memory)或崩溃。因此,以下 内存管理技巧 可用于优化性能…...
vscode项目依赖问题
必读 一定要将前端下拉的项目备份一下,很容易运行导致依赖报错,重新下载 命令 使用幽灵分解器安装 pnpm install 替代 npm install 设置淘宝NPM镜像源 yarn config set registry https://registry.npmmirror.com 查看目前依赖包的版本 npm list ant-d…...
LLMs之RAG:《EdgeRAG: Online-Indexed RAG for Edge Devices》翻译与解读
LLMs之RAG:《EdgeRAG: Online-Indexed RAG for Edge Devices》翻译与解读 导读:这篇论文针对在资源受限的边缘设备上部署检索增强生成 (RAG) 系统的挑战,提出了一种名为 EdgeRAG 的高效方法。EdgeRAG 通过巧妙地结合预计算、在线生成和缓存策…...
宇泰串口卡驱动在Ubuntu22.04编译、安装汇总
从官网下载驱动官网地址 上传到Ubuntu, 目录结构如下: 驱动源代码: 驱动代码是基于开源项目编译来的 编译路径不能有中文路径,否则可能有类似错误 源码是基于Linux2.3内核编译,我当前是6.8.0-51,数据结构有升级,需要调…...
python管理工具:conda部署+使用
python管理工具:conda部署使用 一、安装部署 1、 下载 - 官网下载: https://repo.anaconda.com/archive/index.html - wget方式: wget -c https://repo.anaconda.com/archive/Anaconda3-2023.03-1-Linux-x86_64.sh2、 安装 在conda文件的…...
(三)html2canvas将HTML 转为图片并实现下载
将 HTML 转为图片并实现下载,通常可以使用一个叫做 html2canvas 的 JavaScript 库。html2canvas 能够将 HTML 元素及其样式渲染成一个画布 (Canvas),然后将该画布转换为图片格式(如 PNG 或 JPEG),最终提供下载功能。 …...
安装Docker流程
1.卸载旧版 首先如果系统中已经存在旧的Docker,则先卸载: yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine 2.配置Docker的yum库 首先要安装一个…...
flutter 使用google_mlkit_image_labeling做图片识别
在AI横行的如今,相信大家或多或少都做过跟AI接轨的需求了吧?今天我说的是关于图片识别的需求,flutter的专属图片识别插件google_mlkit_image_labeling。 google_mlkit_image_labeling它是Google旗下的Google Cloud Vision API中分支出来的一部…...
宝塔php7.4安装报错,无法安装,php8以上可以安装,以下的不行,gd库什么的都正常
宝塔的依赖问题导致的问题,最后手动挂载后才解决。。。废了三天三夜终于搞好了。。。。无语~ 建议:不要一直升级宝塔版本,升级前备份或者开服务商的实例镜像,方便恢复,不然,可就GG了࿵…...
python中的RPA->playwright自动化录制脚本实战案例笔记
playwright录制功能使用绕过登录操作 1、首先安装playwright pip install playwright2、 安装支持的浏览器 playwright install # 安装支持的浏览器:cr, chromium, ff, firefox, wk 和 webkit3、接着在自己的项目下运行录制命令: playwright codegen…...
Python在DevOps中的应用:自动化CI/CD管道的实现
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在现代软件开发中,DevOps理念的引入极大地提升了开发与运维的协作效率,而持续集成(…...
Centos 离线安装杀毒软件
离线部署实现: 1、去官网下载对应的软件包,centos就下载 .rpm软件包。https://www.clamav.net/downloads2、将下载的软件包上传到服务器后使用rpm命令进行安装,软件包里面已经将相关依赖这些打包好了,直接安装就行。 rpm -ivh --…...
TiDB使用过程中需要注意的坑点:避免踩雷
TiDB使用过程中需要注意的坑点:避免踩雷 TiDB作为一个分布式数据库,虽然在许多场景下表现出色,但在使用过程中也有一些“坑”需要开发者特别注意。尤其是在生产环境中,踩雷可能会导致性能问题,甚至系统宕机。今天&…...
Mysql--实战篇--大数据量表的分页优化(自增长主键,子查询主键主查询全部,查询条件加索引,覆盖索引等)
当Mysql数据表存储大量数据时(百万级别数据),分页查询的性能问题是一个常见的挑战。特别是当使用LIMIT和OFFSET时,随着OFFSET的增加,查询性能会显著下降。原因在于MySQL需要扫描并跳过前面的行,这会导致I/O…...
Datawhale组队学习笔记task1——leetcode面试题
文章目录 写在前面刷题流程刷题技巧 Day1题目1、0003.无重复字符的最长子串解答:2.00004 寻找两个正序数组的中位数解答:3.0005.最长回文子串解答4.0008.字符串转换整数解答: Day2题目1.0151.反转字符串中的单词解答2.0043.字符串相乘解答3.0…...
【快速入门 LVGL】-- 1、STM32 工程移植 LVGL
目录 一、LVGL 简述 二、复制一个STM32工程 三、下载 LVGL 四、裁剪 源文件 五、工程添加 LVGL 文件 六、注册 显示 七、注册 触摸屏 八、LVGL 心跳、任务刷新 九、开跑 LVGL 十、控件的事件添加、响应处理 十 一、几个好玩小事情 十 二、显示中文 ~~ 约定 ~~ 在…...
Mac使用-快速开始总结(持续更新)
目录 Mac使用-快速开始总结常用快捷键 Mac使用-快速开始总结 第一次使用mac,发现很多细节上和windows不一样,以下是自己遇到的常用总结,帮助自己快速熟悉mac的使用~ 常用快捷键 复制、粘贴 快捷键? 复制:…...
Kubernetes (K8s) 入门指南
Kubernetes (K8s) 入门指南 什么是Kubernetes? Kubernetes,通常简称为 K8s(因为从 “K” 到 “s” 之间有八个字符),是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。它最初由谷歌设…...
归纳webpack
常用配置项 const HtmlWebpackPlugin require(html-webpack-plugin); // 通常用于生成HTML const MiniCssExtractPlugin require(mini-css-extract-plugin);// 用于分离CSS const cssMinimizerWebpackPlugin require("css-minimizer-webpack-plugin"); // 用于压…...
Web APP 阶段性综述
Web APP 阶段性综述 当前,Web APP 主要应用于电脑端,常被用于部署数据分析、机器学习及深度学习等高算力需求的任务。在医学与生物信息学领域,Web APP 扮演着重要角色。在生物信息学领域,诸多工具以 Web APP 的形式呈现ÿ…...
SpringBoot之OriginTrackedPropertiesLoader类源码学习
源码解析 /*** 作用是从给定的资源(如文件或输入流)中加载 .properties 文件,* 并将属性键值对转换为带有来源信息(origin)的 OriginTrackedValue 对象。*/ public class OriginTrackedPropertiesLoader {private fin…...
Flask学习入门笔记
Flask学习入门笔记 前言1. 安装Flask2. 创建一个简单的Flask应用3. 路由与视图函数3.1 基本路由3.2 动态路由3.3 HTTP方法 4. 请求与响应4.1 获取请求数据4.2 返回响应 5. 模板渲染5.1 基本模板渲染5.2 模板继承 6. 静态文件6.1 静态文件的目录结构6.2 在模板中引用静态文件6.2…...
List 接口的实现类
在 Java 中,List 是一个非常常用的接口,提供了有序、可重复的元素集合。List 接口有多个实现类,每个实现类都有其特定的特性和适用场景。以下是 Java 中主要实现了 List 接口的类及其详细介绍。 1. 常见的 List 实现类 1.1 ArrayList 简介&…...
SpringCloud-基于Docker和Docker-Compose的项目部署
一、初始化环境 1. 卸载旧版本 首先,卸载可能已存在的旧版本 Docker。如果您不确定是否安装过,可以直接执行以下命令: sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logro…...
【人工智能】Python中的自动化机器学习(AutoML):如何使用TPOT优化模型选择
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着机器学习在各行业的广泛应用,模型选择和优化成为了数据科学家面临的主要挑战之一。自动化机器学习&am…...
Kafka 超级简述
Kafka 就是一个 分布式的消息系统,它帮助不同的系统和应用之间传递信息。可以把它想象成一个超级高效的 “邮局”: 生产者(Producer) 就是把信息(消息)送到这个 “邮局” 的人。消费者(Consume…...