深入浅出MQTT协议:从物联网基础到实战应用全解析
深入浅出MQTT协议:从物联网基础到实战应用全解析
作为一名在物联网领域摸爬滚打多年的老程序员,今天来和大家聊聊物联网通信中最核心的技术之一——MQTT协议。无论是Java后端开发还是嵌入式硬件开发,掌握MQTT都能让你在物联网项目中如鱼得水。本文将从基础概念讲起,带大家系统理解MQTT的工作原理,并通过实战案例掌握MQTT的应用技巧。
一、物联网与MQTT:开启万物互联的钥匙
1.1 物联网的本质与应用场景
物联网(Internet of Things, IoT)的核心在于"物物相连",通过各类传感器设备(如温度传感器、湿度传感器、GPS模块等),将物理世界的实体对象接入网络,实现数据交换与智能控制。这种连接不是简单的网络互通,而是包含了信息采集-传输-处理-反馈的完整闭环。
举个生活中的例子:智能农业大棚系统通过部署在田间的传感器实时采集土壤湿度、空气温度等数据,这些数据通过MQTT协议传输到云端服务器,服务器根据预设规则分析数据后,自动控制灌溉系统和通风设备,这就是典型的物联网应用场景。
目前物联网已广泛应用于:
- 智慧城市(智能交通信号灯控制)
- 智慧医疗(远程心电监测设备)
- 工业4.0(工厂设备状态实时监控)
- 智能家居(语音控制灯光系统)
- 环境监测(水质污染预警系统)
1.2 为什么MQTT成为物联网首选协议
在物联网场景中,设备通常具有低功耗、网络不稳定、计算资源有限等特点,传统的HTTP协议难以满足需求。MQTT(Message Queuing Telemetry Transport)凭借以下核心优势脱颖而出:
轻量级设计
- 固定报头仅2字节,最小数据包仅4字节
- 协议开销小,适合窄带网络和低功耗设备
- 对比:HTTP请求头通常几十到几百字节
发布订阅模式
- 解耦发布者与订阅者,实现异步通信
- 支持一对多、多对多通信模式
- 设备无需知道接收方具体位置,只需关注主题
可靠传输机制
- 三级QoS(服务质量)保障:
- QoS0:最多一次交付(适合传感器数据)
- QoS1:至少一次交付(状态更新)
- QoS2:恰好一次交付(支付数据)
- 遗嘱消息(Last Will and Testament):设备异常离线时自动发送通知
海量连接支持
- 单台服务器可支持百万级设备同时在线
- 某共享单车平台使用MQTT承载千万辆单车的实时定位数据
多平台兼容性
- 支持C、Java、Python、JavaScript等多语言客户端
- 适配嵌入式系统(ESP32、Arduino)到云端服务器全场景
二、从C/S到发布订阅:MQTT核心通信模式解析
2.1 传统客户端-服务器模式的局限
在传统C/S模式中:
客户端 <------直接连接------> 服务器
这种模式存在明显缺陷:
- 客户端与服务器必须实时在线
- 客户端需知道服务器具体IP和端口
- 大量设备直接连接服务器会造成端口资源耗尽
- 设备离线时消息无法保存
以智能家居为例,如果每个家电都直接连接云端服务器,当服务器重启时,所有设备都需要重新建立连接,期间的控制指令会丢失。
2.2 发布订阅模式的革命性突破
MQTT采用的发布订阅模式引入了Broker(代理服务器)作为中间枢纽:
发布者 ----发布消息----> Broker ----转发消息----> 订阅者(主题topic) (按主题匹配)
这种模式实现了双重解耦:
空间解耦
- 发布者无需知道订阅者的位置和数量
- 订阅者无需知道发布者的存在
- 示例:智能电表只需要向"energy/data"主题发布用电数据,而电力公司的数据分析系统和用户的手机APP都可以订阅该主题获取数据
时间解耦
- 发布者和订阅者无需同时在线
- Broker会存储消息直到订阅者上线(根据QoS和保留消息设置)
- 示例:用户下班回家前,通过手机APP订阅"home/light/status"主题,而智能灯泡在用户离线时仍然会向该主题发布状态消息,用户上线后即可获取历史数据
2.3 MQTT协议报文结构详解
MQTT协议通过二进制报文传输数据,核心报文类型包括:
- CONNECT(连接请求) - 客户端连接到Broker时发送
固定报头:1字节(类型1)+ 剩余长度
可变报头:协议名称("MQTT")+ 协议级别 + 连接标志
负载:客户端ID + 用户名密码(可选)
- PUBLISH(发布消息) - 发布者发送消息到Broker
固定报头:3字节(类型3)+ 主题长度 + 主题名
可变报头:QoS等级 + 消息ID(QoS≥1时)
负载:消息内容(二进制/文本)
- SUBSCRIBE(订阅请求) - 客户端订阅主题
固定报头:8字节(类型8)+ 主题数量
负载:主题列表 + 每个主题的QoS等级
- PINGREQ(心跳请求) - 保持连接活性
固定报头:2字节(类型12)
这些报文通过紧凑的二进制格式设计,极大降低了网络传输开销,非常适合物联网设备使用。
三、MQTT课程体系与实战路线图
3.1 课程四大模块深度解析
模块一:基础概念与核心原理
- 物联网与MQTT关系:从传感器数据采集到云端处理的完整链路
- 协议架构:Broker、发布者、订阅者的角色分工
- 入门案例:通过Java客户端实现简单的"灯控"场景
// MQTT客户端基础代码示例 MqttClient client = new MqttClient("tcp://broker.emqx.io:1883", "clientId"); // 设置连接选项 MqttConnectOptions options = new MqttConnectOptions(); options.setAutomaticReconnect(true); // 设置自动重连功能 client.connect(options); // 连接到MQTT服务器 client.subscribe("home/light/control", 1); // 订阅灯控主题,QoS级别为1 client.publish("home/light/status", "ON".getBytes(), 1, false); // 发布灯的状态消息
模块二:核心机制与高级特性
- QoS详解:三种服务质量等级的应用场景与实现原理
QoS等级 应用场景 实现方式 0 环境监测数据 一次性发送,不确认 1 设备状态更新 消息带ID,接收方确认 2 支付指令 四次握手确认机制 - 主题设计:层次化主题结构设计最佳实践
// 合理的主题设计示例 company/device/area1/room2/temp_sensor // 按公司-设备-区域-房间分层 smart/home/bedroom/light/switch // 智能家居主题规范
- 会话与持久化:离线消息保存与恢复机制
模块三:MQTT Broker实战
- 可视化管理工具:Dashboard使用指南
- 安全配置:
- 用户名密码认证
- 客户端证书双向认证
- 主题权限控制(ACL)
- 高级功能:
- 黑名单管理(禁止恶意设备连接)
- 连接抖动处理(网络不稳定时的重连策略)
- 数据桥接(MQTT与Kafka/Redis的数据互通)
# MQTT Broker安装与启动命令
apt-get install emqx # Debian系安装
emqx start # 启动Broker
emqx_ctl status # 查看状态
模块四:多平台客户端编程
- Web前端集成:使用mqtt.js实现Web端设备监控
// Vue中使用MQTT示例
import mqtt from 'mqtt'
// 连接到MQTT Broker
const client = mqtt.connect('ws://broker.emqx.io:8083/mqtt')
// 连接成功后订阅主题
client.on('connect', () => {client.subscribe('home/sensors/#') // 订阅所有传感器主题
})
// 接收消息并更新页面数据
client.on('message', (topic, payload) => {this.sensorData[topic] = payload.toString() // 更新页面数据
})
- Java后端开发:基于Eclipse Paho实现服务端逻辑
- 智能灯泡实战:
- 硬件:ESP32开发板 + LED灯
- 固件:使用Arduino IDE烧录MQTT客户端程序
- 后端:Java程序接收控制指令并转发到硬件
- 前端:Vue页面实现灯光开关控制
3.2 学习路线建议
阶段 | 学习内容 | 耗时 | 实践目标 |
---|---|---|---|
基础 | 协议概念+发布订阅模式 | 1天 | 完成简单的"发布-订阅"测试 |
进阶 | QoS+主题设计+MQTT Broker | 3天 | 搭建本地Broker并实现权限控制 |
实战 | 多平台客户端开发 | 5天 | 完成智能灯泡控制系统 |
优化 | 性能调优+安全加固 | 2天 | 实现百万级连接测试 |
四、拓展知识:MQTT与其他物联网协议的对比
在物联网领域,除了MQTT还有哪些主流协议?它们各自的应用场景是什么?
4.1 MQTT vs CoAP
特性 | MQTT | CoAP |
---|---|---|
传输层 | TCP | UDP |
设计理念 | 发布订阅 | 客户端-服务器 |
适合场景 | 长连接设备(如智能家居) | 短连接低功耗设备(如传感器网络) |
典型应用 | 智能家电 | 农业传感器节点 |
4.2 MQTT vs AMQP
特性 | MQTT | AMQP |
---|---|---|
设计目标 | 物联网设备 | 企业消息系统 |
协议复杂度 | 简单轻量 | 复杂完整 |
带宽需求 | 低 | 高 |
典型应用 | 传感器数据采集 | 金融交易系统 |
4.3 协议选择建议
- 如果你开发的是电池供电、网络不稳定的设备(如水表、气表),选择MQTT
- 如果是超低功耗、短距离通信的传感器网络,考虑CoAP
- 企业级消息系统或需要复杂路由策略的场景,AMQP更合适
五、MQTT实践之MQTT 5.0新特性
MQTT 5.0相比3.1.1版本增加了许多强大的功能,包括:
5.1 会话过期与消息过期
// MQTT 5.0设置会话过期示例
MqttConnectionOptions options = new MqttConnectionOptions();
// 设置会话过期时间为1小时(单位:秒)
options.setSessionExpiryInterval(3600L);// 设置消息过期时间
MqttProperties props = new MqttProperties();
// 消息10分钟后过期(单位:秒)
props.setMessageExpiryInterval(600L);
client.publish("sensor/temp", message, props);
通过设置过期时间,我们可以避免过时数据的处理,并更好地管理长期离线设备的会话状态。
5.2 服务质量扩展
MQTT 5.0扩展了服务质量特性,提供了:
- 共享订阅:多个订阅者可以负载均衡地接收消息
- 流量控制:通过设置接收最大值控制消息流量
// 共享订阅示例
client.subscribe("$share/group1/sensor/data", 1);
5.3 用户属性与原因码
MQTT 5.0允许在消息中添加用户自定义属性,同时引入了详细的原因码:
// 添加用户属性
MqttProperties props = new MqttProperties();
// 添加自定义属性
props.addUserProperty("location", "livingroom");
props.addUserProperty("device_id", "temp001");
client.publish("home/temperature", message, props);
六、动手实践:10分钟搭建你的第一个MQTT环境
6.1 准备工作
- 硬件:普通PC或云服务器(推荐1核2G配置)
- 软件:
- Windows/macOS/Linux操作系统
- Docker(可选,用于快速部署)
- 任意文本编辑器
6.2 使用Docker部署MQTT Broker
# 拉取MQTT镜像(最新稳定版)
docker pull emqx/emqx:latest# 启动Broker容器(映射1883端口用于MQTT连接,18083端口用于Web管理)
docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 18083:18083 emqx/emqx:latest# 验证启动状态
docker ps | grep emqx
6.3 安装MQTT客户端工具
# 使用npm安装MQTT命令行工具(需要先安装Node.js)
npm install -g mqtt# 或者使用MOSQUITTO客户端(适用于Linux/macOS)
apt-get install mosquitto-clients # Debian系
brew install mosquitto # macOS
6.4 实现简单的发布订阅测试
步骤1:启动订阅者
# 订阅"test/topic"主题,QoS等级1
mosquitto_sub -h localhost -p 1883 -t "test/topic" -q 1
步骤2:启动发布者
# 向"test/topic"主题发布消息"Hello MQTT!",QoS等级1
mosquitto_pub -h localhost -p 1883 -t "test/topic" -m "Hello MQTT!" -q 1
步骤3:查看订阅者接收结果
Hello MQTT! # 订阅者终端应显示此消息
通过这个简单测试,你已经完成了MQTT最核心的发布订阅流程,接下来就可以按照课程体系深入学习更多高级功能了。
七、MQTT安全实践:构建可靠的物联网通信系统
物联网设备通常部署在各种环境中,安全防护至关重要。MQTT提供了多层次的安全机制:
7.1 传输层安全
// 启用TLS加密连接示例
MqttClient client = new MqttClient("ssl://broker.emqx.io:8883", clientId);
MqttConnectOptions options = new MqttConnectOptions();// 设置证书
SSLSocketFactory socketFactory = getSocketFactory("ca.crt", // CA证书"client.crt", // 客户端证书"client.key", // 客户端私钥"password" // 私钥密码
);
options.setSocketFactory(socketFactory);
client.connect(options);
7.2 认证与授权
# 在EMQ X中创建用户并设置密码
./emqx_ctl users create myuser mypassword# 配置访问控制列表(ACL)示例
{allow, {user, "sensor1"}, publish, ["sensors/temp"]}.
{allow, {user, "dashboard"}, subscribe, ["sensors/#"]}.
{deny, all, all, ["admin/#"]}.
7.3 数据加密最佳实践
敏感数据可在应用层进行加密,确保端到端安全:
// 使用AES加密消息内容
String originalMessage = "温度:23.5℃,湿度:45%";
String encryptedMessage = AESUtil.encrypt(originalMessage, secretKey);
client.publish("secure/sensors", encryptedMessage.getBytes(), 1, false);// 接收方解密
client.setCallback(new MqttCallback() {public void messageArrived(String topic, MqttMessage message) {// 解密消息内容String encryptedData = new String(message.getPayload());String decryptedData = AESUtil.decrypt(encryptedData, secretKey);System.out.println("解密后数据: " + decryptedData);}
});
八、MQTT性能优化:百万设备并发连接实战
8.1 MQTT Broker集群搭建
# 修改第一个节点配置
node.name = emqx@192.168.1.100
cluster.discovery = static
cluster.static.seeds = emqx@192.168.1.100,emqx@192.168.1.101# 启动集群后检查状态
./emqx_ctl cluster status
8.2 客户端性能优化
// 客户端连接池示例
public class MqttClientPool {private static final int POOL_SIZE = 10;private List<MqttClient> clientPool = new ArrayList<>();public MqttClientPool() throws MqttException {// 初始化连接池for (int i = 0; i < POOL_SIZE; i++) {MqttClient client = new MqttClient("tcp://broker.emqx.io:1883", "client-" + UUID.randomUUID().toString());MqttConnectOptions options = new MqttConnectOptions();options.setAutomaticReconnect(true);options.setCleanSession(true);client.connect(options);clientPool.add(client);}}// 从池中获取客户端public MqttClient getClient() {// 简单轮询策略int index = (int) (System.currentTimeMillis() % POOL_SIZE);return clientPool.get(index);}
}
8.3 压力测试与监控
# 使用MQTT Benchmark工具进行压力测试
mqtt-benchmark --broker tcp://localhost:1883 --count 1000 --size 256 --qos 1 --clients 1000 --username admin --password public# 监控Broker性能
curl http://localhost:18083/api/v4/stats | jq
结语
MQTT作为物联网的"神经网络",正在支撑着越来越多的智能应用。掌握这门技术,不仅能拓展你的技术边界,更能让你在智能家居、工业互联网等热门领域占据先机。后续我将继续分享更多MQTT实战技巧,包括高可用集群搭建、数据持久化方案、与AI算法结合的智能分析等进阶内容,欢迎关注我的博客获取最新内容。
学习物联网技术就像搭建积木,每掌握一个协议、一个工具,就能拼出更复杂的系统。让我们一起从MQTT开始,构建属于自己的智能世界!
参考资料
- MQTT 3.1.1规范文档
- EMQ X官方文档
- Eclipse Paho客户端库
相关文章:
深入浅出MQTT协议:从物联网基础到实战应用全解析
深入浅出MQTT协议:从物联网基础到实战应用全解析 作为一名在物联网领域摸爬滚打多年的老程序员,今天来和大家聊聊物联网通信中最核心的技术之一——MQTT协议。无论是Java后端开发还是嵌入式硬件开发,掌握MQTT都能让你在物联网项目中如鱼得水…...

解析楼宇自控系统:分布式结构的核心特点与优势展现
在建筑智能化发展的进程中,楼宇自控系统作为实现建筑高效运行与管理的关键,其系统结构的选择至关重要。传统的集中式楼宇自控系统在面对日益复杂的建筑环境和多样化的管理需求时,逐渐暴露出诸多弊端,如可靠性低、扩展性差、响应速…...

C#数字图像处理(三)
文章目录 前言1.图像平移1.1 图像平移定义1.2 图像平移编程实例 2.图像镜像2.1 图像镜像定义2.2 图像镜像编程实例 3.图像缩放3.1 图像缩放定义3.2 灰度插值法3.3 图像缩放编程实例 4.图像旋转4.1 图像旋转定义4.2 图像旋转编程实例 前言 在某种意义上来说,图像的几…...
STM32 智能小车项目 L298N 电机驱动模块
今天开始着手做智能小车的项目了 在智能小车或机器人项目中,我们经常会听到一个词叫 “H 桥电机驱动”,尤其是常见的 L298N 模块,就是基于“双 H 桥”原理设计的。那么,“H 桥”到底是什么?为什么要用“双 H 桥”来驱动…...

SQL Transactions(事务)、隔离机制
目录 Why Transactions? Example: Bad Interaction Transactions ACID Transactions COMMIT ROLLBACK How the Transaction Log Works How Data Is Stored Example: Interacting Processes Interleaving of Statements Example: Strange Interleaving Fixing the…...
【动画】unity中实现骨骼蒙皮动画
我是一名资深的游戏客户端,没事的时候我就想手搓轮子 本文目标 搓一个骨骼动画的核心实现,促进理解骨骼动画本质 骨骼动画简介 官方解释上网搜或者问豆包 快速理解 想知道骨骼动画怎么个事要先知道模型是怎么个事 简单来说:模型 顶点数…...
VSCODE的终端无法执行npm命令
问题原因:PowerShell 默认可能限制脚本执行。 解决方法: 在 PowerShell 中运行以下命令,查看当前策略: Get-ExecutionPolicy 如果结果是 Restricted,改为 RemoteSigned: Set-ExecutionPolicy RemoteSigne…...
Langchian - 自定义提示词模板 提取结构化的数据
场景:从自然语言中提取固定结构信息返回 例如:根据一段文字,提取文字中人的具体特征 马路上走来一个1米7的女生,她一头乌黑的长发披在肩上随风飘动,在她旁边的是她的男朋友,叫:刘山;比她高10厘米 如果想要提取上面这句话中人的身高及头发的颜色,并以固定的格式返回,…...

【机器学习基础】机器学习入门核心:Jaccard相似度 (Jaccard Index) 和 Pearson相似度 (Pearson Correlation)
机器学习入门核心:Jaccard相似度 (Jaccard Index) 和 Pearson相似度 (Pearson Correlation) 一、算法逻辑Jaccard相似度 (Jaccard Index)**Pearson相似度 (Pearson Correlation)** 二、算法原理与数学推导1. Jaccard相…...

QT之头像剪裁效果实现
文章目录 源码地址,环境:QT5.15,MinGW32位效果演示导入图片设置剪裁区域创建剪裁小窗口重写剪裁小窗口的鼠标事件mousePressEventmouseMoveEventmouseReleaseEvent 小窗口移动触发父窗口的重绘事件剪裁效果实现 源码地址,环境&…...
apptrace 视角下移动端深度链接技术与优势
官网链接:AppTrace - 专业的移动应用推广追踪平台 App 拉起,本质上是移动端深度链接技术的具象化呈现。在这一领域,apptrace 凭借前沿技术与创新理念,实现从 H5 网页到 App 的无缝跳转,精准定位 App 内指定页面&#…...
微前端之micro-app数据通信
在这之前如果还没接触过微前端,可以找一些视频、资料先去了解一下,就不在这里赘述了。 现在常见的微前端框架包括: single-spa micro-app qiankun EMP 无界 目前了解到的基本上是这些哈,大家感兴趣可以自行去了解一下,看下它们之间的区别。 因为我目前使用的是mic…...

【GPT入门】第40课 vllm与ollama特性对比,与模型部署
【GPT入门】第40课 vllm与ollama特性对比,与模型部署 1.两种部署1.1 vllm与ollama特性对比2. vllm部署2.1 服务器准备2.1 下载模型2.2 提供模型服务 1.两种部署 1.1 vllm与ollama特性对比 2. vllm部署 2.1 服务器准备 在autodl 等大模型服务器提供商,…...

unity开发棋牌游戏
使用unity开发的棋牌游戏,目前包含麻将、斗地主、比鸡、牛牛四种玩法游戏。 相关技术 客户端:unity 热更新:xlua 服务器:c Web服务器:ruoyi 游戏视频 unity开发棋牌游戏 游戏截图...

Nat Commun项目文章 ▏小麦CUTTag助力解析转录因子TaTCP6调控小麦氮磷高效利用机制
今年2月份发表在《Nature Communications》(IF14.4)的“TaTCP6 is required for efficientand balanced utilization of nitrate and phosphorus in wheat”揭示了TaTCP6在小麦氮磷利用中的关键调控作用,为优化肥料利用和提高作物产量提供了理…...
Qt OpenGL 相机实现
在Qt中使用OpenGL实现相机功能主要涉及视图矩阵(view matrix)的操作,包括相机位置、观察方向和上向量等概念。下面我将介绍如何在Qt中实现一个基本的3D相机。 基本概念 OpenGL相机本质上是通过视图矩阵(view matrix)来实现的,它定义了从世界空间到观察…...
云原生时代 Kafka 深度实践:03进阶特性与最佳实践
3.1 数据可靠性与一致性 Producer 端可靠性策略 Kafka 通过acks参数控制消息确认机制,不同设置适用于不同场景: acks0:Producer 发送消息后不等待 Broker 确认,立即返回。这种模式吞吐量最高,但可能丢失消息&#x…...
基于关联表字段映射的批量数据更新 SQL 实现方案(AIGC)
UPDATE po_upfiles u JOIN po_micro m ON u.from_id = m.ent_id_old SET u.from_id = m.ent_id; 我的提问 批量更新po_upfiles数据中from_id=ent_id_old的数据中from_id为ent_id,语句怎么写“问题重新按照适合AI的逻辑进行提问,如何修改 精确版...
Hadoop复习(二)
部署Hadoop 考试不考部署,就复习选择和大题 问题 1 单项选择 2 / 2 分 下面哪个是MapReduce的核心配置文件 core-site.xml hdfs-site.xml yarn-site.xml mapred-site.xml 问题 2 单项选择 2 / 2 分 下面哪个是HDFS的核心配置文件 core-site.xml hdf…...

C 语言开发中常见的开发环境
目录 1.Dev-C 2.Visual Studio Code 3.虚拟机 Linux 环境 4.嵌入式 MCU 专用开发环境 1.Dev-C 使用集成的 C/C 开发环境(适合基础学习),下载链接Dev-C下载 - 官方正版 - 极客应用 2.Visual Studio Code 结合 C/C 扩展 GCC/MinGW 编译器,…...

vscode命令行debug
vscode命令行debug 一般命令行debug会在远程连服务器的时候用上,命令行debug的本质是在执行时暴露一个监听端口,通过进入这个端口,像本地调试一样进行。 这里提供两种方式: 直接在命令行中添加debugpy,适用于python…...

Matlab作图之 subplot
1. subplot(m, n, p) 将当前图形划分为m*n的网格,在 p 指定的位置创建坐标轴 matlab 按照行号对子图的位置进行编号 第一个子图是第一行第一列,第二个子图是第二行第二列......... 如果指定 p 位置存在坐标轴, 此命令会将已存在的坐标轴设…...
Springboot 项目一启动就获取HttpSession
在 Spring Boot 项目中,HttpSession 是有状态的,通常只有在用户发起 HTTP 请求并建立会话后才会创建。因此,在项目启动时(即应用刚启动还未处理任何请求)是无法获取到 HttpSession 的。 方法一:使用 HttpS…...
PostgreSQL的扩展 insert_username
PostgreSQL的扩展 insert_username insert_username 是 PostgreSQL 的一个实用扩展,用于自动记录数据行的创建者和最后修改者信息。这个扩展特别适合需要审计跟踪的应用场景。 一 扩展安装与启用 1.1 安装扩展 -- 使用超级用户安装 CREATE EXTENSION insert_use…...

【机器学习基础】机器学习入门核心算法:层次聚类算法(AGNES算法和 DIANA算法)
机器学习入门核心算法:层次聚类算法(AGNES算法和 DIANA算法) 一、算法逻辑二、算法原理与数学推导1. 距离度量2. 簇间距离计算(连接标准)3. 算法伪代码(凝聚式) 三、模型评估1. 内部评估指标2. …...

Google Play的最新安全变更可能会让一些高级用户无法使用App
喜欢Root或刷机的Android用户要注意了,Google最近全面启用了新版Play Integrity API,可能会导致部分用户面临无法使用某些App的窘境。Play Integrity API是Google提供给开发者的工具,用于验证App是否在“未修改”的设备上运行。 许多重要应用…...
深度学习篇---人脸识别中的face-recognition库和深度学习
深度学习方法和使用 Python 的face_recognition库进行人脸识别在技术原理、实现方式和应用场景上有显著区别,以下从多个维度对比分析: 一、技术原理 1. 深度学习方法 核心逻辑:基于神经网络(如卷积神经网络 CNN)构建…...
(11)java+ selenium->元素定位之By_tag_name
1.简介 继续WebDriver关于元素定位,这篇介绍By ClassName。tagName是DOM结构的一部分,其中页面上的每个元素都是通过输入标签,按钮标签或锚定标签等标签定义的。每个标签都具有多个属性,例如ID,名称,值类等。就其他定位符而言在Selenium中,我们使用了标签的这些属性值来…...

React---day5
4、React的组件化 组件的分类: 根据组件的定义方式,可以分为:函数组件(Functional Component )和类组件(Class Component);根据组件内部是否有状态需要维护,可以分成:无状态组件(Stateless Component )和…...

Java开发之定时器学习
面试 一、线程池实现定时器 核心代码: public static void main(String[] args) {ScheduledExecutorService scheduledExecutorService Executors.newScheduledThreadPool(5);Runnable runnable () -> System.out.println("当前线程"Thread.current…...