高效Android MQTT封装工具:简化物联网开发,提升性能与稳定性
在Android开发中,封装MQTT工具可以帮助简化与MQTT服务器的通信。MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布/订阅消息传输协议,常用于物联网(IoT)设备之间的通信。
以下是一个简单的MQTT封装工具示例,使用Eclipse Paho库来实现MQTT客户端功能。
- 添加依赖
首先,在build.gradle文件中添加Paho MQTT库的依赖:
dependencies {implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
}
- 权限配置
在AndroidManifest.xml中添加必要的权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- 服务配置
在AndroidManifest.xml中注册Paho的MqttService:
<service android:name="org.eclipse.paho.android.service.MqttService" />
4.MQTT封装工具类支持:
自定义客户端ID:支持用户自定义客户端ID。
遗言消息:支持设置遗言消息,用于客户端异常断开时通知其他客户端。
线程池管理:使用线程池处理MQTT操作,避免阻塞主线程。
灵活的回调机制:支持为每个操作单独设置回调。
连接重试机制:增加连接失败后的重试机制,提升连接稳定性。
日志级别:支持动态调整日志级别,便于调试和生产环境切换。
支持多服务器连接:允许同时连接多个MQTT服务器。
消息缓存策略:增加消息缓存的最大数量和时间限制,避免内存泄漏。
更灵活的重试机制:支持自定义重试次数和重试间隔。
连接状态管理:增加更详细的连接状态(如连接中、已连接、断开中等)。
支持QoS级别配置:允许动态配置发布和订阅的QoS级别。
MQTT工具类
import android.content.Context;
import android.util.Log;import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class MqttManager {private static final String TAG = "MqttManager";private static MqttManager instance;private Map<String, MqttAndroidClient> mqttClients = new HashMap<>(); // 支持多服务器连接private Map<String, MqttConnectOptions> mqttConnectOptionsMap = new HashMap<>();private Map<String, Boolean> connectionStatusMap = new HashMap<>(); // 连接状态private Map<String, List<MqttMessage>> messageQueueMap = new HashMap<>(); // 消息队列private Map<String, List<String>> subscribedTopicsMap = new HashMap<>(); // 已订阅的主题private ExecutorService executorService = Executors.newCachedThreadPool(); // 线程池private ConnectionStateListener connectionStateListener;private static final int DEFAULT_QOS = 1;private static final boolean DEFAULT_RETAINED = false;private static final int MAX_MESSAGE_QUEUE_SIZE = 100; // 消息队列最大数量private static final long MESSAGE_QUEUE_TIMEOUT = 60000; // 消息队列超时时间(毫秒)private static final int MAX_RETRY_COUNT = 3; // 最大重试次数private static final int RETRY_INTERVAL = 5000; // 重试间隔(毫秒)// 单例模式public static synchronized MqttManager getInstance() {if (instance == null) {instance = new MqttManager();}return instance;}private MqttManager() {}/*** 初始化MQTT客户端*/public void initClient(Context context, String serverUri, String clientId) {if (mqttClients.containsKey(serverUri)) {Log.w(TAG, "Client already initialized for server: " + serverUri);return;}MqttAndroidClient client = new MqttAndroidClient(context, serverUri, clientId);mqttClients.put(serverUri, client);mqttConnectOptionsMap.put(serverUri, new MqttConnectOptions());connectionStatusMap.put(serverUri, false);messageQueueMap.put(serverUri, new ArrayList<>());subscribedTopicsMap.put(serverUri, new ArrayList<>());// 设置回调client.setCallback(new MqttCallbackExtended() {@Overridepublic void connectComplete(boolean reconnect, String serverURI) {connectionStatusMap.put(serverURI, true);Log.d(TAG, "MQTT connected: " + serverURI);if (connectionStateListener != null) {connectionStateListener.onConnected(serverURI, reconnect);}// 连接成功后发送缓存的消息processMessageQueue(serverURI);// 重新订阅主题resubscribeTopics(serverURI);}@Overridepublic void connectionLost(Throwable cause) {for (Map.Entry<String, MqttAndroidClient> entry : mqttClients.entrySet()) {if (entry.getValue().equals(client)) {String serverUri = entry.getKey();connectionStatusMap.put(serverUri, false);Log.e(TAG, "MQTT connection lost: " + serverUri, cause);if (connectionStateListener != null) {connectionStateListener.onDisconnected(serverUri, cause);}// 尝试重新连接attemptReconnect(serverUri, 0);break;}}}@Overridepublic void messageArrived(String topic, MqttMessage message) throws Exception {Log.d(TAG, "Message arrived: " + new String(message.getPayload()));if (connectionStateListener != null) {connectionStateListener.onMessageReceived(topic, message);}}@Overridepublic void deliveryComplete(IMqttDeliveryToken token) {Log.d(TAG, "Message delivered");}});}/*** 设置连接参数*/public void setConnectionOptions(String serverUri, String username, String password) {MqttConnectOptions options = mqttConnectOptionsMap.get(serverUri);if (options != null) {options.setUserName(username);options.setPassword(password.toCharArray());}}/*** 设置遗言消息*/public void setWillMessage(String serverUri, String topic, String message, int qos, boolean retained) {MqttConnectOptions options = mqttConnectOptionsMap.get(serverUri);if (options != null) {options.setWill(topic, message.getBytes(), qos, retained);}}/*** 设置SSL/TLS加密连接*/public void setSSL(String serverUri, boolean useSSL) {MqttConnectOptions options = mqttConnectOptionsMap.get(serverUri);if (options != null && useSSL) {options.setSocketFactory(new DefaultSSLSocketFactory());}}/*** 连接到MQTT服务器*/public void connect(String serverUri) {if (connectionStatusMap.get(serverUri)) {Log.w(TAG, "Already connected to MQTT server: " + serverUri);return;}MqttAndroidClient client = mqttClients.get(serverUri);MqttConnectOptions options = mqttConnectOptionsMap.get(serverUri);if (client == null || options == null) {Log.e(TAG, "Client or options not initialized for server: " + serverUri);return;}executorService.execute(() -> {try {client.connect(options, null, new IMqttActionListener() {@Overridepublic void onSuccess(IMqttToken asyncActionToken) {Log.d(TAG, "Connected to MQTT server: " + serverUri);}@Overridepublic void onFailure(IMqttToken asyncActionToken, Throwable exception) {Log.e(TAG, "Failed to connect to MQTT server: " + serverUri, exception);attemptReconnect(serverUri, 0);}});} catch (MqttException e) {Log.e(TAG, "MQTT connection error: " + serverUri, e);attemptReconnect(serverUri, 0);}});}/*** 断开连接*/public void disconnect(String serverUri) {if (!connectionStatusMap.get(serverUri)) {Log.w(TAG, "Already disconnected from MQTT server: " + serverUri);return;}MqttAndroidClient client = mqttClients.get(serverUri);if (client == null) {Log.e(TAG, "Client not initialized for server: " + serverUri);return;}executorService.execute(() -> {try {client.disconnect(null, new IMqttActionListener() {@Overridepublic void onSuccess(IMqttToken asyncActionToken) {connectionStatusMap.put(serverUri, false);Log.d(TAG, "Disconnected from MQTT server: " + serverUri);}@Overridepublic void onFailure(IMqttToken asyncActionToken, Throwable exception) {Log.e(TAG, "Failed to disconnect from MQTT server: " + serverUri, exception);}});} catch (MqttException e) {Log.e(TAG, "MQTT disconnection error: " + serverUri, e);}});}/*** 订阅主题*/public void subscribe(String serverUri, String topic, int qos, IMqttActionListener listener) {if (!connectionStatusMap.get(serverUri)) {Log.w(TAG, "Not connected, subscription will be attempted after connection: " + serverUri);subscribedTopicsMap.get(serverUri).add(topic); // 缓存主题return;}MqttAndroidClient client = mqttClients.get(serverUri);if (client == null) {Log.e(TAG, "Client not initialized for server: " + serverUri);return;}executorService.execute(() -> {try {client.subscribe(topic, qos, null, listener);} catch (MqttException e) {Log.e(TAG, "MQTT subscription error: " + serverUri, e);}});}/*** 发布消息*/public void publish(String serverUri, String topic, String message, int qos, boolean retained, IMqttActionListener listener) {MqttMessage mqttMessage = new MqttMessage(message.getBytes());mqttMessage.setQos(qos);mqttMessage.setRetained(retained);if (!connectionStatusMap.get(serverUri)) {Log.w(TAG, "Not connected, message will be queued: " + serverUri);List<MqttMessage> queue = messageQueueMap.get(serverUri);if (queue.size() < MAX_MESSAGE_QUEUE_SIZE) {queue.add(mqttMessage); // 缓存消息} else {Log.w(TAG, "Message queue is full, discarding message: " + serverUri);}return;}MqttAndroidClient client = mqttClients.get(serverUri);if (client == null) {Log.e(TAG, "Client not initialized for server: " + serverUri);return;}executorService.execute(() -> {try {client.publish(topic, mqttMessage, null, listener);} catch (MqttException e) {Log.e(TAG, "MQTT publish error: " + serverUri, e);}});}/*** 处理消息队列*/private void processMessageQueue(String serverUri) {List<MqttMessage> queue = messageQueueMap.get(serverUri);for (MqttMessage message : queue) {publish(serverUri, "default/topic", new String(message.getPayload()), message.getQos(), message.isRetained(), null);}queue.clear();}/*** 重新订阅主题*/private void resubscribeTopics(String serverUri) {List<String> topics = subscribedTopicsMap.get(serverUri);for (String topic : topics) {subscribe(serverUri, topic, DEFAULT_QOS, null);}}/*** 尝试重新连接*/private void attemptReconnect(String serverUri, int retryCount) {if (retryCount >= MAX_RETRY_COUNT) {Log.w(TAG, "Max retry count reached for server: " + serverUri);return;}executorService.execute(() -> {try {Thread.sleep(RETRY_INTERVAL);connect(serverUri);} catch (InterruptedException e) {Log.e(TAG, "Reconnect attempt interrupted: " + serverUri, e);}});}/*** 设置连接状态监听器*/public void setConnectionStateListener(ConnectionStateListener listener) {this.connectionStateListener = listener;}/*** 连接状态监听器接口*/public interface ConnectionStateListener {void onConnected(String serverUri, boolean isReconnect);void onDisconnected(String serverUri, Throwable cause);void onMessageReceived(String topic, MqttMessage message);}
}
以下是一个使用 MqttManager 的完整示例。这个示例展示了如何初始化MQTT客户端、连接服务器、订阅主题、发布消息以及处理连接状态和消息回调。
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttMessage;public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";private static final String SERVER_URI = "tcp://your.mqtt.broker:1883"; // MQTT服务器地址private static final String CLIENT_ID = "android_client_" + System.currentTimeMillis(); // 客户端IDprivate static final String TOPIC = "your/topic"; // 订阅的主题private static final String WILL_TOPIC = "your/lwt/topic"; // 遗言主题private static final String WILL_MESSAGE = "Client disconnected"; // 遗言消息private MqttManager mqttManager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 初始化MQTT管理器mqttManager = MqttManager.getInstance();mqttManager.initClient(this, SERVER_URI, CLIENT_ID);// 设置连接参数mqttManager.setConnectionOptions(SERVER_URI, "username", "password");// 设置遗言消息mqttManager.setWillMessage(SERVER_URI, WILL_TOPIC, WILL_MESSAGE, 1, true);// 设置连接状态监听器mqttManager.setConnectionStateListener(new MqttManager.ConnectionStateListener() {@Overridepublic void onConnected(String serverUri, boolean isReconnect) {Log.d(TAG, "Connected to MQTT server: " + serverUri + ", isReconnect: " + isReconnect);// 订阅主题mqttManager.subscribe(SERVER_URI, TOPIC, 1, new IMqttActionListener() {@Overridepublic void onSuccess(IMqttToken asyncActionToken) {Log.d(TAG, "Subscribed to topic: " + TOPIC);}@Overridepublic void onFailure(IMqttToken asyncActionToken, Throwable exception) {Log.e(TAG, "Failed to subscribe to topic: " + TOPIC, exception);}});}@Overridepublic void onDisconnected(String serverUri, Throwable cause) {Log.e(TAG, "Disconnected from MQTT server: " + serverUri, cause);}@Overridepublic void onMessageReceived(String topic, MqttMessage message) {Log.d(TAG, "Received message from topic: " + topic + ", payload: " + new String(message.getPayload()));}});// 连接MQTT服务器mqttManager.connect(SERVER_URI);// 发布消息publishMessage("Hello, MQTT!");}/*** 发布消息*/private void publishMessage(String message) {mqttManager.publish(SERVER_URI, TOPIC, message, 1, false, new IMqttActionListener() {@Overridepublic void onSuccess(IMqttToken asyncActionToken) {Log.d(TAG, "Message published to topic: " + TOPIC);}@Overridepublic void onFailure(IMqttToken asyncActionToken, Throwable exception) {Log.e(TAG, "Failed to publish message to topic: " + TOPIC, exception);}});}@Overrideprotected void onDestroy() {super.onDestroy();// 断开连接mqttManager.disconnect(SERVER_URI);}
}
示例说明
初始化MQTT客户端:
使用 MqttManager.getInstance() 获取单例实例。
调用 initClient() 初始化MQTT客户端,传入服务器地址和客户端ID。
设置连接参数:
使用 setConnectionOptions() 设置用户名和密码。
设置遗言消息:
使用 setWillMessage() 设置遗言消息,当客户端异常断开时,服务器会发布该消息。
设置连接状态监听器:
实现 ConnectionStateListener 接口,监听连接状态变化和消息到达事件。
连接MQTT服务器:
调用 connect() 连接到MQTT服务器。
订阅主题:
在 onConnected() 回调中订阅主题。
发布消息:
使用 publish() 方法发布消息到指定主题。
断开连接:
在 onDestroy() 中调用 disconnect() 断开连接。
注意事项
服务器地址和主题:
替换 SERVER_URI 和 TOPIC 为实际的MQTT服务器地址和主题。
用户名和密码:
如果MQTT服务器需要认证,请设置正确的用户名和密码。
遗言消息:
遗言消息用于在客户端异常断开时通知其他客户端,确保设置合适的主题和消息内容。
线程安全:
MQTT操作在后台线程中执行,避免阻塞主线程。
相关文章:
高效Android MQTT封装工具:简化物联网开发,提升性能与稳定性
在Android开发中,封装MQTT工具可以帮助简化与MQTT服务器的通信。MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布/订阅消息传输协议,常用于物联网(IoT)设备之间的通信。 以下是一个简单的MQ…...
数据库原理7
1.“数据库系统运行与维护工具”的研究属于数据库管理系统软件 2.1970年IBM公司的高级研究员E.F.Codd提出了关系数据模型 3.每个属性的属性值是不可分解的,即关系的每个分量必须是一个不可分的数据项。属性值的取值应满足域完整性约束。 4.视图作用:简…...
2025最新比较使用的ai工具都有哪些,分别主要用于哪些方面?
文章目录 一、AI对话与交互工具二、AI写作与内容生成工具三、AI绘画与设计工具四、AI视频生成工具五、办公与效率工具六、其他实用工具选择建议 根据2025年最新行业动态和用户反馈,以下AI工具在多个领域表现突出,覆盖对话、写作、设计、视频生成等场景&a…...
什么是 MyBatis? 它的优点和缺点是什么?
一、 什么是 MyBatis? 定义: MyBatis 是一款优秀的持久层框架,用于简化 Java 应用程序与数据库之间的交互。MyBatis 通过 XML 或注解 的方式,将 SQL 语句与 Java 代码分离,提供了一种灵活的、易于维护的数据访问解决方…...
在ArcMap中通过Python编写自定义工具(Python Toolbox)实现点转线工具
文章目录 一、需求二、实现过程2.1、创建Python工具箱(.pyt)2.2、使用catalog测试代码2.3、在ArcMap中使用工具 三、测试 一、需求 通过插件的形式将点转线功能嵌入ArcMap界面,如何从零开始创建一个插件,包括按钮的添加、工具的实…...
Array and string offset access syntax with curly braces is deprecated
警告信息 “Array and string offset access syntax with curly braces is deprecated” 是 PHP 中的一个弃用警告(Deprecation Notice),表明在 PHP 中使用花括号 {} 来访问数组或字符串的偏移量已经被标记为过时。 背景 在 PHP 的早期版本…...
moodle 开源的在线学习管理系统(LMS)部署
一、Moodle 简介 Moodle(Modular Object-Oriented Dynamic Learning Environment)是一个开源的在线学习管理系统(LMS),广泛应用于教育机构和企业培训。其核心功能包括课程管理、作业提交、在线测试、论坛互动和成绩跟…...
后智能体时代的LLM和Agent
文章目录 1. 关于AI重塑的哲学体系2. 关于AI大模型体系的认知3. 关于AI大模型体系的畅想4. 关于人和AI大模型体系的共处5. 写在最后 随着OpenAI、Deepseek、Manus等等智能体的爆火,人们茶前饭后、插科打诨的话题都离不开这些智能体,现状也正如《人民日报…...
Day6 DFS
一、跳台阶 一个楼梯共有 nn 级台阶,每次可以走一级或者两级,问从第 00 级台阶走到第 nn 级台阶一共有多少种方案。 输入格式 共一行,包含一个整数 nn。 输出格式 共一行,包含一个整数,表示方案数。 数据范围 1…...
Releases(发布) 和 版本管理 是两个紧密相关的概念
在软件开发和维护中,Releases(发布) 和 版本管理 是两个紧密相关的概念,特别是在开源项目或企业软件开发中。 1. Releases(发布) Release 是指软件的一个正式发布版本,通常经过开发、测试、修复 Bug,并被认为是足够稳定和可用于生产环境的版本。 主要特点 里程碑:通…...
模型微调——模型性能提升方法及注意事项(自用)
名词补充 人为为训练数据标注的标签称为黄金标准或真实值,这个过程一定程度上保证训练的准确性,但是其人工标注的成本和时间很高,并且标注的标签受人的主观因素影响。 导致模型性能不佳的因素和解决办法 ①不同类别的数据不平衡:统…...
景联文科技:以精准数据标注赋能AI进化,构筑智能时代数据基石
在人工智能技术席卷全球的浪潮中,高质量数据已成为驱动AI模型进化的核心燃料。作为全球领先的AI数据服务解决方案提供商,景联文科技深耕数据标注领域多年,以技术为基、以专业为本,致力于为全球客户提供全场景、高精度、多模态的数…...
嵌入式L6计算机网络
Telnet不加密 socket是应用层和下面的内核...
华为鸿蒙系统全景解读:从内核设计到生态落地的技术革命
华为鸿蒙系统全景解读:从内核设计到生态落地的技术革命 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,可以分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/ccc 文章目录 华为鸿蒙系统全景解读&#x…...
2025最新软件测试面试八股文(含答案+文档)
1、请试着比较一下黑盒测试、白盒测试、单元测试、集成测试、系统测试、验收测试的区别与联系。 参考答案: 黑盒测试:已知产品的功能设计规格,可以进行测试证明每个实现了的功能是否符合要求。 白盒测试:已知产品的内部工作过程…...
微前端框架 Qiankun 的应用及问题分析
一、Qiankun 的核心应用场景与优势 多技术栈共存与灵活集成 Qiankun 支持主应用与子应用使用不同技术栈(如 Vue、React、Angular 等),通过 HTML Entry 方式接入子应用,无需深度改造子应用即可实现集成,降低了技术迁移成…...
八卡5090服务器首发亮相!
AI 人工智能领域热度居高不下。OpenAI 的 GPT - 4 凭强悍语言处理能力,在内容创作、智能客服等领域广泛应用。清华大学团队的 DeepSeek 大模型在深度学习训练优势突出,正促使各行业应用端算力需求向推理主导转变,呈爆发式增长 。 随着 DeepS…...
C#类型转换基本概念
一、基本定义 C# 类型转换是将数据从一种类型转换为另一种类型的过程,分为 隐式转换 和 显式转换 两类。 强类型语言特性:C# 要求变量类型在编译时确定,类型转换需满足兼容性或显式规则。目的:处理不同数据类…...
基于SSM+Vue+uniapp的驾校预约管理小程序+LW示例
系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…...
关于C++数据类型char的类型是整数的思考
学习数据类型时,整数类型中有一个特殊的类型char,可以使用字符来为其赋,也可以用整数来为其赋值,这是怎么一回事?其实任何类型,在计算机的内存中,在最小的存储单元比特中,内部只有0或…...
在Spring Boot项目中分层架构
常见的分层架构包括以下几层: 1. Domain 层(领域层) 作用:领域层是业务逻辑的核心,包含与业务相关的实体类、枚举、值对象等。它是对业务领域的抽象,通常与数据库表结构直接映射。 主要组件: 实体类(Entity):与数据库表对应的Java类,通常使用JPA或MyBatis等ORM框架…...
《用Python+PyGame开发双人生存游戏!源码解析+完整开发思路分享》
导语 "你是否想过用Python开发一款可玩性高的双人合作游戏?本文将分享如何从零开始实现一款类《吸血鬼幸存者》的生存射击游戏!包含完整源码解析、角色系统设计、敌人AI逻辑等核心技术点,文末提供完整代码包下载!" 哈…...
ArcGIS操作:13 生成最小外接矩阵
应用情景:筛选出屋面是否能放下12*60m的长方形,作为起降场候选点(一个不规则的形状内,判断是否能放下指定长宽的长方形) 1、面积初步筛选 Area ≥ 720 ㎡ 面积计算见 2、打开 ArcToolbox → Data Management Tools …...
manus对比ChatGPT-Deep reaserch进行研究类学术相关数据分析!谁更胜一筹?
没有账号,只能挑选一个案例 一夜之间被这个用全英文介绍全华班出品的新爆款国产AI产品的小胖刷频。白天还没有切换语言的选项,晚上就加上了。简单看了看团队够成,使用很长实践的Monica创始人也在其中。逐渐可以理解,重心放在海外产…...
android为第三方提供部分系统接口
文章目录 Settings - 亮灭屏Settings - 恢复出厂设置Settings - 数字锁屏/解锁Settings - 设置系统时间PackageInstaller - 安装/卸载第三方应用摘要:本文对系统模块进行改造,提供广播等形式的接口对外提供无法直接调用的系统级别接口,实现部分功能的集合。如果是广播形式,…...
在虚拟机上安装Hadoop
以下是在虚拟机上安装Hadoop的一般步骤: 准备工作 - 安装虚拟机软件:如VMware Workstation或VirtualBox等。 - 创建虚拟机:选择合适的操作系统镜像,如Ubuntu或CentOS等Linux发行版,为虚拟机分配足够的CPU、内存和磁盘…...
Python —— pow()函数
一、示例1 # 计算 2 的 3 次幂 result1 pow(2, 3) print(result1) # 输出: 8# 计算 2.5 的 2 次幂 result2 pow(2.5, 2) print(result2) # 输出: 6.25 二、示例2 # 计算 (2 ** 3) % 5 result3 pow(2, 3, 5) print(result3) # 输出: 3 三、示例3 ntxt input("请输…...
开发环境搭建-完善登录功能
一.完善登录功能 我们修改密码为md5中的格式,那么就需要修改数据库中的密码和将从前端获取到的密码转化成md5格式,然后进行比对。比对成功则登录成功,失败则禁止登录。 二.md5格式 使用DigestUtils工具类进行md5加密,调用md4Dig…...
el-table(elementui)表格合计行使用以及滚动条默认样式修改
一、el-table新增合计行以及el-table展示数据出现的问题 1. 使用合计行 el-table的属性show-summary设为true,即可在表格尾部展示合计行。默认情况下,第一列不展示数据,而显示合计二字,可以通过sum-text自己配置,其余…...
STM32G431RBT6--(3)片上外设及其关系
前边我们已经了解了STM32的内核,下面我们来介绍片上外设,对于这些外设,如果我们弄清楚一个单片机都有什么外设,弄清他们之间的关系,对于应用单片机有很大的帮助,我们以G431为例: 这个表格描述了…...
