news 2026/7/10 22:24:44

RabbitMQ消息中间件极速入门与实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
RabbitMQ消息中间件极速入门与实战

第一章:RabbitMQ起步

1-1 课程导航

课程导航

  • RabbitMQ简介及AMQP协议
  • RabbitMQ安装与使用
  • RabbitMQ核心概念
  • 与SpringBoot整合
  • 保障100%的消息可靠性投递方案落地实现

1-2 RabbitMQ简介

初识RabbitMQ

  • RabbitMQ是一个开源的消息代理和队列服务器
  • 用来通过普通协议在完全不同的应用之间共享数据
  • RabbitMQ是使用Erlang语言来编写的
  • 并且RabbitMQ是基于AMQP协议的

RabbitMQ简介

  • 目前很多互联网大厂都在使用RabbitMQ
  • RabbitMQ底层采用Erlang语言进行编写
  • 开源、性能优秀,稳定性保障
  • 与SpringAMQP完美的整合、API丰富
  • 集群模式丰富,表达式配置,HA模式,镜像队列模型
  • 保证数据不丢失的前提做到高可靠性、可用性
  • AMQP全称:Advanced Message Queuing Protocol
  • AMQP翻译:高级消息队列协议

AMQP协议模型

1-3 RabbitMQ安装

学习笔记

0.安装准备 官网地址:http://www.rabbitmq.com/ 安装Linux必要依赖包<Linux7> 下载RabbitMQ安装包 进行安装,修改相关配置文件 vim /etc/hostname vim /etc/hosts 1.安装Erlang wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb sudo dpkg -i erlang-solutions_1.0_all.deb sudo apt-get install erlang erlang-nox 2.安装RabbitMQ echo 'deb http://www.rabbitmq.com/debian/ testing main' | sudo tee /etc/apt/sources.list.d/rabbitmq.list wget -O- https://www.rabbitmq.com/rabbitmq-release-signing-key.asc | sudo apt-key add - sudo apt-get install rabbitmq-server 3.安装RabbitMQ web管理插件 sudo rabbitmq-plugins enable rabbitmq_management sudo systemctl restart rabbitmq-server 访问:http://localhost:15672 默认用户名密码:guest/guest 4.修改RabbitMQ配置 vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.5.7/ebin/rabbit.app 比如修改密码、配置等等;例如:loopback_users中的<<"guest">>,只保留guest 服务启动:rabbitmq-server start & 服务停止:rabbitmqctl app_stop

1-4 RabbitMQ概念

RabbitMQ的整体架构

RabbitMQ核心概念

  • Server:又称Broker,接受客户端的连接,实现AMQP实体服务
  • Connection:连接,应用程序与Broker的网络连接
  • Channel:网络信道

    几乎所有的操作都在Channel中进行
    Channel是进行消息读写的通道
    客户端可建立多个Channel
    每个Channel代表一个会话任务
  • Message:消息

    服务器和应用程序之间传送的数据,由Properties和Body组成
    Properties可以对消息进行修饰,比如消息的优先级、延迟等高级特性
    Body则就是消息体内容
  • Virtual host:虚拟机

    用于进行逻辑隔离,最上层的消息路由
    一个Virtual host里面可以有若干个Exchange和Queue
    同一个Virtual host里面不能有相同名称的Exchange或Queue
  • Exchange:交换机,接收消息,根据路由键转发消息到绑定的队列
  • Binding:Exchange和Queue之间的虚拟连接,binding中可以包含routing key
  • Routing key:一个路由规则,虚拟机可用它来确定如何路由一个特定消息
  • Queue:也称为Message Queue,消息队列,保存消息并将它们转发给消费者

RabbitMQ消息的流转过程

第二章:RabbitMQ使用

2-1 发送消息

SpringBoot与RabbitMQ集成

  • 引入相关依赖
  • 对application.properties进行配置

创建名为rabbitmq-producer的maven工程pom如下

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>47-rabbitmq</artifactId> <groupId>com.myimooc</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>rabbitmq-producer</artifactId> <properties> <spring.boot.version>2.0.4.RELEASE</spring.boot.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-parent</artifactId> <version>${spring.boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--RabbitMQ依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <!--工具类依赖--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.36</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>

1.编写Order类

package com.myimooc.rabbitmq.entity; import java.io.Serializable; /** * <br> * 标题: 订单实体<br> * 描述: 订单实体<br> * 时间: 2018/09/06<br> * * @author zc */ public class Order implements Serializable{ private static final long serialVersionUID = 6771608755338249746L; private String id; private String name; /** * 存储消息发送的唯一标识 */ private String messageId; public Order() { } public Order(String id, String name, String messageId) { this.id = id; this.name = name; this.messageId = messageId; } @Override public String toString() { return "Order{" + "id='" + id + ''' + ", name='" + name + ''' + ", messageId='" + messageId + ''' + '}'; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getMessageId() { return messageId; } public void setMessageId(String messageId) { this.messageId = messageId; } }

2.编写OrderSender类

package com.myimooc.rabbitmq.producer.producer; import com.myimooc.rabbitmq.entity.Order; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.rabbit.support.CorrelationData; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * <br> * 标题: 订单消息发送者<br> * 描述: 订单消息发送者<br> * 时间: 2018/09/06<br> * * @author zc */ @Component public class OrderSender { private RabbitTemplate rabbitTemplate; @Autowired public OrderSender( RabbitTemplate rabbitTemplate) { this.rabbitTemplate = rabbitTemplate; } /** * 发送订单 * * @param order 订单 * @throws Exception 异常 */ public void send(Order order) throws Exception { CorrelationData correlationData = new CorrelationData(); correlationData.setId(order.getMessageId()); // exchange:交换机 // routingKey:路由键 // message:消息体内容 // correlationData:消息唯一ID this.rabbitTemplate.convertAndSend("order-exchange", "order.a", order, correlationData); } }

3.编写application.properties类

# RabbitMQ配置 spring.rabbitmq.addresses=192.168.0.105:5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest spring.rabbitmq.virtual-host=/ spring.rabbitmq.connection-timeout=15000 # Server配置 server.servlet.context-path=/ server.port=8080 spring.http.encoding.charset=UTF-8 spring.jackson.date-format=yyyy-MM-dd HH:mm:ss spring.jackson.time-zone=GMT+8 spring.jackson.default-property-inclusion=NON_NULL

4.编写Application类

package com.myimooc.rabbitmq.producer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * <br> * 标题: 启动类<br> * 描述: 启动类<br> * 时间: 2018/09/06<br> * * @author zc */ @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

5.编写OrderSenderTest类

package com.myimooc.rabbitmq.producer.producer; import com.myimooc.rabbitmq.entity.Order; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.UUID; /** * <br> * 标题: 订单消息发送者测试<br> * 描述: 订单消息发送者测试<br> * 时间: 2018/09/06<br> * * @author zc */ @RunWith(SpringRunner.class) @SpringBootTest public class OrderSenderTest { @Autowired private OrderSender orderSender; @Test public void testSend1() throws Exception { Order order = new Order(); order.setId("201809062009010001"); order.setName("测试订单1"); order.setMessageId(System.currentTimeMillis() + "$" + UUID.randomUUID().toString().replaceAll("-","")); this.orderSender.send(order); } }

2-2 处理消息

创建名为rabbitmq-consumer的maven工程pom如下

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>47-rabbitmq</artifactId> <groupId>com.myimooc</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>rabbitmq-consumer</artifactId> <properties> <spring.boot.version>2.0.4.RELEASE</spring.boot.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-parent</artifactId> <version>${spring.boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--RabbitMQ依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <!--工具类依赖--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.36</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>

1.编写Order类

package com.myimooc.rabbitmq.entity; import java.io.Serializable; /** * <br> * 标题: 订单实体<br> * 描述: 订单实体<br> * 时间: 2018/09/06<br> * * @author zc */ public class Order implements Serializable{ private static final long serialVersionUID = 6771608755338249746L; private String id; private String name; /** * 存储消息发送的唯一标识 */ private String messageId; public Order() { } public Order(String id, String name, String messageId) { this.id = id; this.name = name; this.messageId = messageId; } @Override public String toString() { return "Order{" + "id='" + id + ''' + ", name='" + name + ''' + ", messageId='" + messageId + ''' + '}'; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getMessageId() { return messageId; } public void setMessageId(String messageId) { this.messageId = messageId; } }

2.编写OrderReceiver类

package com.myimooc.rabbitmq.consumer.consumer; import com.rabbitmq.client.Channel; import com.myimooc.rabbitmq.entity.Order; import org.springframework.amqp.rabbit.annotation.*; import org.springframework.amqp.support.AmqpHeaders; import org.springframework.messaging.handler.annotation.Headers; import org.springframework.messaging.handler.annotation.Payload; import org.springframework.stereotype.Component; import java.util.Map; /** * <br> * 标题: 订单接收者<br> * 描述: 订单接收者<br> * 时间: 2018/09/06<br> * * @author zc */ @Component public class OrderReceiver { /** * 接收消息 * * @param order 消息体内容 * @param headers 消息头内容 * @param channel 网络信道 * @throws Exception 异常 */ @RabbitListener(bindings = @QueueBinding( value = @Queue(value = "order-queue",durable = "true"), exchange = @Exchange(name = "order-exchange",type = "topic"), key = "order.*" )) @RabbitHandler public void onOrderMessage(@Payload Order order, @Headers Map<String, Object> headers, Channel channel) throws Exception { // 消费者操作 System.out.println("收到消息:"); System.out.println("订单信息:" + order.toString()); // 手动签收消息 Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG); channel.basicAck(deliveryTag, false); } }

3.编写application.properties类

# RabbitMQ连接配置 spring.rabbitmq.addresses=192.168.0.105:5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest spring.rabbitmq.virtual-host=/ spring.rabbitmq.connection-timeout=15000 # RabbitMQ消费配置 # 基本并发:5 spring.rabbitmq.listener.simple.concurrency=5 # 最大并发:10 spring.rabbitmq.listener.simple.max-concurrency=10 # 签收模式:手动签收 spring.rabbitmq.listener.simple.acknowledge-mode=manual # 限流策略:同一时间只有1条消息发送过来消费 spring.rabbitmq.listener.simple.prefetch=1 # Server配置 server.servlet.context-path=/ server.port=8082 spring.http.encoding.charset=UTF-8 spring.jackson.date-format=yyyy-MM-dd HH:mm:ss spring.jackson.time-zone=GMT+8 spring.jackson.default-property-inclusion=NON_NULL

4.编写Application类

package com.myimooc.rabbitmq.consumer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * <br> * 标题: 启动类<br> * 描述: 启动类<br> * 时间: 2018/09/06<br> * * @author zc */ @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

第三章:可靠性投递

3-1 设计方案

保障100%消息投递成功设计方案(一)

3-2 代码详解

因篇幅限制,源码请到github地址查看,这里仅展示核心关键类

1.编写OrderSender类

package com.myimooc.rabbitmq.ha.producer; import com.myimooc.rabbitmq.entity.Order; import com.myimooc.rabbitmq.ha.constant.Constants; import com.myimooc.rabbitmq.ha.dao.mapper.BrokerMessageLogMapper; import com.myimooc.rabbitmq.ha.dao.po.BrokerMessageLogPO; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.rabbit.support.CorrelationData; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * <br> * 标题: 订单消息发送者<br> * 描述: 订单消息发送者<br> * 时间: 2018/09/06<br> * * @author zc */ @Component public class OrderSender { @Autowired private RabbitTemplate rabbitTemplate; @Autowired private BrokerMessageLogMapper brokerMessageLogMapper; /** * 回调方法:confirm确认 */ private final RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() { @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { System.out.println("correlationData:" + correlationData); String messageId = correlationData.getId(); if (ack) { // 如果confirm返回成功,则进行更新 BrokerMessageLogPO messageLogPO = new BrokerMessageLogPO(); messageLogPO.setMessageId(messageId); messageLogPO.setStatus(Constants.OrderSendStatus.SEND_SUCCESS); brokerMessageLogMapper.changeBrokerMessageLogStatus(messageLogPO); } else { // 失败则进行具体的后续操作:重试或者补偿等 System.out.println("异常处理..."); } } }; /** * 发送订单 * * @param order 订单 */ public void send(Order order) { // 设置回调方法 this.rabbitTemplate.setConfirmCallback(confirmCallback); // 消息ID CorrelationData correlationData = new CorrelationData(order.getMessageId()); // 发送消息 this.rabbitTemplate.convertAndSend("order-exchange", "order.a", order, correlationData); } }

2.编写OrderService类

package com.myimooc.rabbitmq.ha.service; import com.myimooc.rabbitmq.entity.Order; import com.myimooc.rabbitmq.ha.constant.Constants; import com.myimooc.rabbitmq.ha.dao.mapper.BrokerMessageLogMapper; import com.myimooc.rabbitmq.ha.dao.mapper.OrderMapper; import com.myimooc.rabbitmq.ha.dao.po.BrokerMessageLogPO; import com.myimooc.rabbitmq.ha.producer.OrderSender; import com.myimooc.rabbitmq.ha.util.FastJsonConvertUtils; import org.apache.commons.lang3.time.DateUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Date; /** * <br> * 标题: 订单服务<br> * 描述: 订单服务<br> * 时间: 2018/09/07<br> * * @author zc */ @Service public class OrderService { @Autowired private OrderMapper orderMapper; @Autowired private BrokerMessageLogMapper brokerMessageLogMapper; @Autowired private OrderSender orderSender; /** * 创建订单 * * @param order 订单 */ public void create(Order order) { // 当前时间 Date orderTime = new Date(); // 业务数据入库 this.orderMapper.insert(order); // 消息日志入库 BrokerMessageLogPO messageLogPO = new BrokerMessageLogPO(); messageLogPO.setMessageId(order.getMessageId()); messageLogPO.setMessage(FastJsonConvertUtils.convertObjectToJson(order)); messageLogPO.setTryCount(0); messageLogPO.setStatus(Constants.OrderSendStatus.SENDING); messageLogPO.setNextRetry(DateUtils.addMinutes(orderTime, Constants.ORDER_TIMEOUT)); this.brokerMessageLogMapper.insert(messageLogPO); // 发送消息 this.orderSender.send(order); } }

3.编写RetryMessageTask类

package com.myimooc.rabbitmq.ha.task; import com.myimooc.rabbitmq.entity.Order; import com.myimooc.rabbitmq.ha.constant.Constants; import com.myimooc.rabbitmq.ha.dao.mapper.BrokerMessageLogMapper; import com.myimooc.rabbitmq.ha.dao.po.BrokerMessageLogPO; import com.myimooc.rabbitmq.ha.producer.OrderSender; import com.myimooc.rabbitmq.ha.util.FastJsonConvertUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.List; /** * <br> * 标题: 重发消息定时任务<br> * 描述: 重发消息定时任务<br> * 时间: 2018/09/07<br> * * @author zc */ @Component public class RetryMessageTask { private Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private OrderSender orderSender; @Autowired private BrokerMessageLogMapper brokerMessageLogMapper; /** * 启动完成3秒后开始执行,每隔10秒执行一次 */ @Scheduled(initialDelay = 3000, fixedDelay = 10000) public void retrySend() { logger.debug("重发消息定时任务开始"); // 查询 status = 0 和 timeout 的消息日志 List<BrokerMessageLogPO> pos = this.brokerMessageLogMapper.listSendFailureAndTimeoutMessage(); for (BrokerMessageLogPO po : pos) { logger.debug("处理消息日志:{}",po); if (po.getTryCount() >= Constants.MAX_RETRY_COUNT) { // 更新状态为失败 BrokerMessageLogPO messageLogPO = new BrokerMessageLogPO(); messageLogPO.setMessageId(po.getMessageId()); messageLogPO.setStatus(Constants.OrderSendStatus.SEND_FAILURE); this.brokerMessageLogMapper.changeBrokerMessageLogStatus(messageLogPO); } else { // 进行重试,重试次数+1 this.brokerMessageLogMapper.updateRetryCount(po); Order reSendOrder = FastJsonConvertUtils.convertJsonToObject(po.getMessage(), Order.class); try { this.orderSender.send(reSendOrder); } catch (Exception ex) { // 异常处理 logger.error("消息发送异常:{}", ex); } } } logger.debug("重发消息定时任务结束"); } }

4.编写ApplicationTest类

package com.myimooc.rabbitmq.ha; import com.myimooc.rabbitmq.entity.Order; import com.myimooc.rabbitmq.ha.service.OrderService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.UUID; /** * <br> * 标题: 订单创建测试<br> * 描述: 订单创建测试<br> * 时间: 2018/09/07<br> * * @author zc */ @RunWith(SpringRunner.class) @SpringBootTest public class ApplicationTest { @Autowired private OrderService orderService; @Test public void testCreateOrder(){ Order order = new Order(); order.setId(String.valueOf(System.currentTimeMillis())); order.setName("测试创建订单"); order.setMessageId(System.currentTimeMillis() + "$" + UUID.randomUUID().toString().replaceAll("-","")); this.orderService.create(order); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/10 22:24:10

暖风机性能如何?参数全解读

暖风机主打大风量强力制热&#xff0c;风量≥10500m/h、制热量≥55.25KW&#xff0c;采用 PTC 加热器联动控制与顶吹送风方式&#xff0c;噪音≤60dB&#xff0c;兼顾高效采暖与安全静音&#xff0c;是大空间快速升温的优选设备。This heater features high air volume and pow…

作者头像 李华
网站建设 2026/7/10 22:24:07

elasticsearch学习笔记(三十一)——Elasticsearch doc value正排索引

在我们搜索的时候&#xff0c;要依靠倒排索引&#xff0c;但是当我们排序的时候&#xff0c;需要依靠正排索引。通过倒排索引锁定文档document之后&#xff0c;看到每个document的每个field&#xff0c;然后进行排序&#xff0c;所谓的正排索引就是doc values。对于ES而言&…

作者头像 李华
网站建设 2026/7/10 22:20:16

基于MATLAB卷积神经网络的口罩佩戴检测系统

摘要&#xff1a;随着公共卫生安全意识的不断提高&#xff0c;口罩佩戴检测在疫情防控、公共场所管理等领域具有重要的应用价值。本文设计并实现了一个基于卷积神经网络&#xff08;CNN&#xff09;的口罩佩戴检测系统。该系统采用深度学习技术&#xff0c;通过训练CNN模型自动…

作者头像 李华
网站建设 2026/7/10 22:19:52

基于MKV42F128VLH16与PAM8904的低功耗警报系统设计

1. 项目概述与核心组件选型在工业控制和智能家居领域&#xff0c;可靠的事件通知系统是保障设备安全运行的关键环节。本次项目基于MKV42F128VLH16微控制器和PAM8904音频驱动芯片构建通用警报系统&#xff0c;可适配从工厂设备异常到家庭安防报警等多种场景。MKV42F128VLH16是NX…

作者头像 李华
网站建设 2026/7/10 22:19:15

jed - 轻量级终端代码编辑器详解

1. 命令简介 jed 是一个基于 Slang 库开发的轻量级屏幕编辑器&#xff0c;主要用于编辑程序源代码。它支持语法高亮显示&#xff0c;并且能够模拟多种经典编辑器的操作模式&#xff0c;包括 Emacs、EDT、WordStar 和 Brief&#xff0c;具有高度可定制性与灵活性。jed 特别适合…

作者头像 李华