Python 解析JSON实现主机管理
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它以易于阅读和编写的文本形式表示数据。JSON 是一种独立于编程语言的数据格式,因此在不同的编程语言中都有对应的解析器和生成器。JSON 格式的设计目标是易于理解、支持复杂数据结构和具有良好的可扩展性。
JSON 数据是以键值对的形式存在的,而且易于阅读和编写。以下是一个简单的 JSON 示例:
{"name": "John Doe","age": 30,"city": "New York","isStudent": false,"grades": [95, 88, 75, 92],"address": {"street": "123 Main St","zipCode": "10001"}
}
在这个例子中,JSON 对象包含了一些属性,包括字符串、数字、布尔值、数组和嵌套的对象。
"name": "John Doe":字符串键值对。"age": 30:数字键值对。"city": "New York":字符串键值对。"isStudent": false:布尔键值对。"grades": [95, 88, 75, 92]:数组键值对。"address": {...}:嵌套对象。
在实际应用中,JSON 数据通常用于前后端之间的数据交换,或者配置文件的存储。各种编程语言都提供了处理 JSON数据的库或模块。
很早之前大概是两年前,当时为了实现批量管理SSH账号密码并实现自动巡检功能,写过一个简单的命令行工具,通过使用JSON实现对特定主机账号密码与组的管理,如下代码,通过定义AdminDataBase()类,传如数据库文件名database.json实现对特定JSON文件的增删改查功能,在编写该案例后我对JSON的使用变得更加深刻了。
# -*- coding: utf-8 -*-
import os,jsonclass AdminDataBase(object):def __init__(self, database_path):self.database_path = database_path# 判断数据库文件是否存在,不存则则创建一个.def InitDatabase(self):if os.path.exists(self.database_path) != None :init_database = \{"HostList": [["1000", "127.0.0.1", "username", "password", "22"]],"HostGroup": [{"DefaultGroup": ["1000"]}, ],}with open(self.database_path, "w", encoding="utf-8") as fp:fp.write(json.dumps(init_database))print("[+] {} 结构已被初始化.".format(self.database_path))# table 接收一个列表名,根据列表名输出列表中的数据def ShowHostList(self):with open(self.database_path, "r", encoding="utf-8") as Read_Pointer:load_json = json.loads(Read_Pointer.read())base = load_json.get("HostList")print("-" * 80)print("UUID \t 主机地址 \t\t\t 登录用户 \t\t 登录密码 \t 端口")print("-" * 80)for each in range(0, len(base)):print("{0:4} \t {1:15} \t {2:10} \t {3:10} \t {4:10}".format(base[each][0], base[each][1], base[each][2], base[each][3], base[each][4]))print()# 在原来的基础上添加一台新的主机,添加到HostList表中def AddHost(self, uuid, address, username, password, port):with open(self.database_path, "r", encoding="utf-8") as Read_Pointer:# 读取 database.json 中的数据到内存中load_json = json.loads(Read_Pointer.read())# 先读入内存,修改后全部替换进去host_list = load_json.get("HostList")# 获取到最后一次循环的元素列表for each in range(len(host_list) - 1, len(host_list)):# 判断如果UUID不重复则添加,否则跳过添加if (host_list[each][0] != uuid):host_list.append([uuid, address, username, password, port])load_json["HostList"] = host_list# 最后再次将改好的数据,回写到文件保存with open(self.database_path, "w", encoding="utf-8") as Write_Pointer:dump_json = json.dumps(load_json)Write_Pointer.write(dump_json)print("[+] UUID {} 添加成功.".format(uuid))else:print("[-] UUID {} 列表中存在,添加失败.".format(uuid))return 0# 根据传入UUID号修改特定主机数据def ModifyHost(self,uuid,modify_address,modify_username,modify_password,modify_port):with open(self.database_path, "r", encoding="utf-8") as Read_Pointer:# 读取 database.json 中的数据到内存中load_json = json.loads(Read_Pointer.read())host_list = load_json.get("HostList")# 根据uuid寻找一维数组的下标位置index = -1for index, value in enumerate(host_list):if value[0] == uuid:print("[*] 已找到UUID {} 所在下标为 {}".format(uuid,index))breakelse:index = -1# 判断是否找到了,找到了则修改if index != -1:# 修改指定下标数值,并将修改后的数据放入原始JSON文件中host_list[index] = [uuid,modify_address,modify_username,modify_password,modify_port]load_json["HostList"] = host_list# 最后再次将改好的数据,回写到文件保存with open(self.database_path, "w", encoding="utf-8") as Write_Pointer:dump_json = json.dumps(load_json)Write_Pointer.write(dump_json)print("[+] UUID {} 修改完成.".format(uuid))return 0else:print("[-] UUID {} 不存在.".format(uuid))return 0# 根据传入的UUID号删除主机数据,先删除所对的组中的数据,然后在删除主机数据def DeleteHost(self,uuid):with open(self.database_path, "r", encoding="utf-8") as Read_Pointer:load_json = json.loads(Read_Pointer.read())host_group = load_json.get("HostGroup")# 首先在HostGroup中寻找并弹出相应UUIDfor each in range(0,len(host_group)):try:# 循环每个字典for k,v in host_group[each].items():# 判断UUID是否存在于每个字典中if v.count(uuid) != 0:# 移除并放入原始JSON中v.remove(uuid)load_json["HostGroup"] = v# 最后再次将改好的数据,回写到文件保存with open(self.database_path, "w", encoding="utf-8") as Write_Pointer:dump_json = json.dumps(load_json)Write_Pointer.write(dump_json)#print("[+] UUID {} 修改完成.".format(uuid))else:#print("[-] 当前组 {} 不能存在: {}".format(k,uuid))breakexcept Exception:print("[-] 当前组不能存在: {}".format(uuid))return 0# ----------------------------------------------# 其次寻找HostList中的数据并弹出host_list = load_json.get("HostList")try:# 根据uuid寻找一维数组的下标位置index = -1for index, value in enumerate(host_list):if value[0] == uuid:#print("[*] 已找到UUID {} 所在下标为 {}".format(uuid,index))breakelse:index = -1# 如果找到了,则直接根据下标弹出数据if index != -1:host_list.pop(index)load_json["HostList"] = host_list# 最后再次将改好的数据,回写到文件保存with open(self.database_path, "w", encoding="utf-8") as Write_Pointer:dump_json = json.dumps(load_json)Write_Pointer.write(dump_json)print("[+] UUID {} 主机: {} 已被移除.".format(uuid,host_list[index][1]))return 0except Exception:return 0# 向数据库中的HostGroup字段中添加一个主机组def AddHostGroup(self,add_group_name):with open(self.database_path, "r", encoding="utf-8") as Read_Pointer:load_json = json.loads( Read_Pointer.read() )group_obj = load_json.get("HostGroup")# 循环所有字典中的组for each in range(0, len(group_obj)):list_name = str(list(group_obj[each].keys())[0])# print("组节点: {}".format(list_name))# 循环判断表中是否存在指定的组名称if (list_name == add_group_name):print("[-] {} 存在于组中,无法继续添加.".format(list_name))return 0# 读取原始JSON文件,并构建回写参数tmp = {}tmp[add_group_name] = ["1000"]group_obj.append(tmp)# 回写添加主机组with open(self.database_path, "w", encoding="utf-8") as Write_Pointer:dump_json = json.dumps(load_json)Write_Pointer.write(dump_json)print("[+] 主机组 {} 已添加".format(add_group_name))# 在主机组中删除一个主机组def DeleteHostGroup(self,delete_group_name):with open(self.database_path, "r", encoding="utf-8") as Read_Pointer:load_json = json.loads( Read_Pointer.read() )group_obj = load_json.get("HostGroup")# 循环所有字典中的组for each in range(0, len(group_obj)):list_name = str(list(group_obj[each].keys())[0])# 循环判断表中是否存在指定的组名称if (list_name == delete_group_name):# 如果存在于组中,那我们就把他的each弹出列表group_obj.pop(each)# 将弹出后的列表再次写回JSON序列中with open(self.database_path, "w", encoding="utf-8") as Write_Pointer:dump_json = json.dumps(load_json)Write_Pointer.write(dump_json)print("[-] 主机组 {} 已移除.".format(delete_group_name))return 0print("[-] 主机组 {} 不存在.".format(delete_group_name))return 0# 向指定主机组中添加一个主机UUIDdef AddHostGroupOnUUID(self,group_name, uuid):with open(self.database_path, "r", encoding="utf-8") as Read_Pointer:load_json = json.loads( Read_Pointer.read() )group_obj = load_json.get("HostGroup")# 循环所有字典中的所有组for each in range(0, len(group_obj)):list_name = str(list(group_obj[each].keys())[0])# 如果找到了需要添加的组if (list_name == group_name):tmp = group_obj[each]# 获取到原始列表中的数据val = list(tmp.values())[0]# 判断输入的UUID号,是否在val列表中,不在则添加if str(uuid) not in val:val.append(str(uuid))# 将原始数据赋值到新的表中group_obj[each][list_name] = valelse:print("[-] UUID {} 已存在于 {} 主机组,添加失败.".format(uuid,group_name))return 0with open(self.database_path, "w", encoding="utf-8") as Write_Pointer:dump_json = json.dumps(load_json)Write_Pointer.write(dump_json)print("[+] 向主机组 {} 增加UUID {} 完成".format(group_name, uuid))return 0# 从指定主机组中删除一个指定的UUID号def DeleteHostGroupOnUUID(self,group_name, uuid):with open(self.database_path, "r", encoding="utf-8") as Read_Pointer:load_json =json.loads( Read_Pointer.read() )group_obj = load_json.get("HostGroup")# 循环所有字典中的组for each in range(0, len(group_obj)):list_name = str(list(group_obj[each].keys())[0])# 先来寻找到需要删除的主机组if (list_name == group_name):tmp = group_obj[each]# 寻找指定组中的指定列表val = list(tmp.values())[0]for x in range(0, len(val)):if (val[x] == uuid):print("[*] 搜索UUID: {} 索引值: {}".format(val[x], x))# 将要删除的UUID弹出列表val.pop(x)# 将弹出后的列表重新复制到主机组中group_obj[each][list_name] = val# 保存弹出后的列表到序列中with open(self.database_path, "w", encoding="utf-8") as write_fp:dump_json = json.dumps(load_json)write_fp.write(dump_json)print("[+] 从主机组 {} 弹出UUID {} 完成".format(group_name, uuid))return 0return 0# 输出所有主机组和全部节点信息def ShowAllGroup(self):with open(self.database_path, "r", encoding="utf-8") as Read_Pointer:load_json = json.loads( Read_Pointer.read() )group_obj = load_json.get("HostGroup")# 循环解析所有组,并解析出UUID所对应的主机地址等信息for each in range(0, len(group_obj)):for k, v in group_obj[each].items():print("-" * 140)print("主机组: {}".format(k))print("-" * 140)for each in range(0, len(v)):# print("--> UUID: {}".format(v[each]))# 循环判断,拿着组内UUID判断是否存在,如果存在则打印出主机详细信息base_obj = load_json.get("HostList")for x in range(0, len(base_obj)):if (v[each] == base_obj[x][0]):print("UUID: {0:6} \t 主机地址: {1:15} \t 主机账号: {2:15} \t 主机密码: {3:15} \t 端口: {4:5} \t".format(base_obj[x][0], base_obj[x][1], base_obj[x][2], base_obj[x][3],base_obj[x][4]))print("\n")# 只显示所有的主机组,包括组中主机数def ShowGroup(self):with open(self.database_path, "r", encoding="utf-8") as Read_Pointer:load_json = json.loads( Read_Pointer.read() )group_obj = load_json.get("HostGroup")print("-" * 80)print("{0:20} \t {1:5} \t {2:100}".format("主机组名","主机数","主机列表"))print("-" * 80)for each in range(0,len(group_obj)):for k,v in group_obj[each].items():print("{0:20} \t {1:5} \t {2:100}".format(k,str(len(v)), str(v)))print()return 0# 对指定的主机组进行Ping测试def PingGroup(self,group_name):with open(self.database_path, "r", encoding="utf-8") as Read_Pointer:load_json = json.loads( Read_Pointer.read() )group_obj = load_json.get("HostGroup")# 循环遍历主机列表for each in range(0, len(group_obj)):for k, v in group_obj[each].items():# 寻找主机组,找到后提取出所有的Valueif (k == group_name):item_list = v# 再循环,拿着v的值对base进行循环,提取出其中的用户名密码等for val in range(0, len(item_list)):# 得到循环列表:print(item_list[val])base_obj = load_json.get("HostList")# 循环base表中的计数器for base_count in range(0, len(base_obj)):# 判断base表中是否存在指定UUID,如果存在则输出其值if (base_obj[base_count][0] == item_list[val]):print("地址: {} \t 用户名: {} [ok]".format(base_obj[base_count][1],base_obj[base_count][2]))
if __name__ == "__main__":db = AdminDataBase("database.json")while True:try:cmd = str(input("[LyShell] # ")).split()if (cmd == ""):continueelif (cmd[0] == "exit"):exit(1)elif (cmd[0] == "clear"):os.system("cls")elif(cmd[0] == "Init"):db.InitDatabase()elif(cmd[0] == "ShowHostList"):db.ShowHostList()elif(cmd[0] == "ShowGroup"):db.ShowGroup()elif(cmd[0] == "ShowAllGroup"):db.ShowAllGroup()elif(cmd[0] == "AddHost" or cmd[0] == "ModifyHost"):if (len(cmd) - 1 >= 5):uuid = str(cmd[1]).split("=")[1]address = str(cmd[2]).split("=")[1]username = str(cmd[3]).split("=")[1]password = str(cmd[4]).split("=")[1]port = str(cmd[5]).split("=")[1]if cmd[0] == "AddHost":db.AddHost(uuid,address,username,password,port)elif cmd[0] == "ModifyHost":db.ModifyHost(uuid,address,username,password,port)elif(cmd[0] == "DeleteHost"):if(len(cmd)-1 >= 1):uuid = str(cmd[1]).split("=")[1]db.DeleteHost(uuid)elif(cmd[0] == "AddHostGroup"):group_name = str(cmd[1]).split("=")[1]db.AddHostGroup(group_name)elif(cmd[0] == "DeleteHostGroup"):group_name = str(cmd[1]).split("=")[1]db.DeleteHostGroup(group_name)elif(cmd[0] == "AddHostGroupOnUUID"):group_name = str(cmd[1]).split("=")[1]uuid = str(cmd[2]).split("=")[1]db.AddHostGroupOnUUID(group_name,uuid)elif(cmd[0] == "DelHostGroupOnUUID"):group_name = str(cmd[1]).split("=")[1]uuid = str(cmd[2]).split("=")[1]db.DeleteHostGroupOnUUID(group_name,uuid)elif(cmd[0] == "PingGroup"):group_name = str(cmd[1]).split("=")[1]db.PingGroup(group_name)elif (cmd[0] == "help"):print("By: LyShark")else:print("Not Command")except Exception:continue
使用案例
管理数据库(AdminDataBase)中的主机信息和主机分组信息。用户通过输入命令来执行不同的操作,如初始化数据库、显示主机列表、添加主机、修改主机信息、删除主机等。
以下是代码的主要功能和命令列表:
- 初始化数据库:
Init - 显示主机列表:
ShowHostList - 显示主机分组:
ShowGroup - 显示所有主机分组:
ShowAllGroup - 添加主机:
AddHost - 修改主机信息:
ModifyHost - 删除主机:
DeleteHost - 添加主机分组:
AddHostGroup - 删除主机分组:
DeleteHostGroup - 将主机添加到指定分组:
AddHostGroupOnUUID - 从指定分组删除主机:
DelHostGroupOnUUID - 按组执行 Ping 操作:
PingGroup - 清屏:
clear - 退出程序:
exit - 帮助:
help
Init
初次使用需要执行本命令,对数据库文件进行写出,如下所示;

ShowHostList
用于输出当前主机列表信息,如下图所示;

ShowGroup
用于输出当前主机组,如下图所示;

ShowAllGroup
用于输出所有的主机组以及组内的主机详细信息,如下图所示;

AddHost
添加一个新的主机记录,如下图所示;

ModifyHost
修改一个已有的主机记录,此处以UUID作为修改条件,如下图所示;

DeleteHost
根据一个UUID唯一标识,删除一个已存在的主机记录,如下图所示;

AddHostGroup
新增一个组名,默认会携带1000为初始主机,如下图所示;

DeleteHostGroup
删除一整个主机组,如下图所示;

AddHostGroupOnUUID
根据UUID号将特定主机添加到特定组内,如下图所示;

DelHostGroupOnUUID
根据主机组名,删除特定的UUID,如下图所示;

PingGroup
对特定主机组执行Ping功能测试,此处可以扩展,如下图所示;

总结部分
该案例只是用于学习如何灵活运用JSON实现数据的增删改查,其实在实战中意义不大,因为完全可以使用SQLite这类精简数据库,此案例只是本人为了熟悉JSON的增删改查而写的一个Demo工具。
相关文章:
Python 解析JSON实现主机管理
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它以易于阅读和编写的文本形式表示数据。JSON 是一种独立于编程语言的数据格式,因此在不同的编程语言中都有对应的解析器和生成器。JSON 格式的设计目标是易于理解、…...
一体化污水处理设备材质怎么选
在环保意识日益增强的今天,污水处理设备成为城市建设过程中的重要环节。而选择合适的一体化污水处理设备材质,则成为了一项重要的决策。本文将从专业的角度出发,为您解析一体化污水处理设备材质的选取。 首先,一体化污水处理设备材…...
德国进口高速主轴电机在机器人上的应用及选型方案
随着机器人技术的日新月异,高速主轴电机在机器人领域的应用也日趋广泛。德国进口的SycoTec高速主轴电机,以其高转速、高精度、高刚度的特点,在机器人的切割、铣削、钻孔、去毛刺等加工应用中发挥着关键作用。 一、高速主轴电机的特点 SycoT…...
【软考中级——软件设计师】备战经验 笔记总结分享
考试成绩 我第一次备考是在2022 然后那时候取消了这次是第二次 靠前我一个月复习的看了以前的笔记 然后刷了七八道历年题目学习资料推荐 :zst——2021 b站链接自荐一下我的笔记 : 软考笔记专栏 视频确实很长 , 我的建议就是先看笔记 然后不会…...
146. LRU 缓存 --力扣 --JAVA
题目 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类: LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回…...
【C++】POCO学习总结(十):Poco::Util::Application(应用程序框架)
【C】郭老二博文之:C目录 1、Poco::Util::Application 应用框架 1.1 应用程序基本功能 Poco::Util::Application是POCO实现的的应用程序框架,支持功能如下: 命令行参数处理配置文件初始化和关机日志 1.2 命令行程序和守护进程 POCO支持…...
探索医学影像:如何通过ROI灰度直方图和ROI区域方格图揭示隐秘细节?
一、引言 医学影像是现代医学诊断的重要手段,其中nrrd文件格式作为一种常见的医学影像数据存储方式,被广泛应用于各种医学影像设备和软件中。这种文件格式具有丰富的元数据信息,可以精确记录影像的空间位置、方向和尺度等信息,对于…...
SASS基本语法总结
SASS是CSS预处理器,简单来说,SASS是比CSS更高一级的语言,它拥有CSS不具备的语法,比如if条件控制 SASS的预处理器 SASS是一种无法被浏览器直接执行的语言,我们需要通过预处理工具(可以理解为翻译工具&…...
【C++】简单工厂模式
2023年12月6日,周三下午 今天又学习了一次简单工厂模式 每多学习一次,都会加深对设计模式的理解 目录 什么是简单工厂模式简单工厂模式的优缺点举例说明 什么是简单工厂模式 简单工厂模式(Simple Factory Pattern)是一种创建型…...
el-tree数据量过大,造成浏览器卡死、崩溃
el-tree数据量过大,造成浏览器卡死、崩溃 场景:树形结构展示,数据超级多,超过万条,每次打开都会崩溃 我这里采用的是引入新的插件虚拟树,它是参照element-plus 中TreeV2改造vue2.x版本虚拟化树形控件&…...
2024 年甘肃省职业院校技能大赛中职组 电子与信息类“网络安全”赛项竞赛样题-A
2024 年甘肃省职业院校技能大赛中职组 电子与信息类“网络安全”赛项竞赛样题-A 目录 2024 年甘肃省职业院校技能大赛中职组 电子与信息类“网络安全”赛项竞赛样题-A 需要环境或者解析可以私信 (二)A 模块基础设施设置/安全加固(200 分&…...
面向LLM的App架构——业务维度
这是两篇面向LLM的大前端架构的第一篇,主要写我对LLM业务的认知以及由此推演出的大前端架构。由于我是客户端出身,所以主要以客户端角度来描述,并不影响对前端的适用性。 对LLM的认知 基于Google对AGI的论文,AGI或者LLM一定会朝…...
ElasticSearch之cat plugins API
命令样例如下: curl -X GET "https://localhost:9200/_cat/plugins?vtrue&pretty" --cacert $ES_HOME/config/certs/http_ca.crt -u "elastic:ohCxPHQBEs5*lo7F9"执行结果输出如下: name component version…...
【小米电脑管家】安装使用教程--非小米电脑
安装说明功能体验下载资源 Xiaomi HyperOS发布后,小米妙享电脑端独立版本也走向终点,最新的【小米电脑管家】将会内置妙享实现万物互联。那么本篇文章将分享非小米电脑用户如何绕过设备识别验证安装使用【小米电脑管家】实现万物互联 安装说明 1.解压文…...
视频讲解|基于多目标粒子群算法的配电网储能选址定容
1 主要内容 该视频为3012基于多目标粒子群算法的配电网储能选址定容matlab代码讲解内容,对应的资源下载链接为基于多目标粒子群算法的配电网储能选址定容,程序主要内容是:以系统节点电压水平(电网脆弱性)、网络损耗以…...
Android 13 - Media框架(22)- MediaCodec(三)
这一节开始我们将重新回到 MediaCodec 这一层来学习 buffer 的流转 status_t MediaCodec::dequeueOutputBuffer(size_t *index,size_t *offset,size_t *size,int64_t *presentationTimeUs,uint32_t *flags,int64_t timeoutUs) {sp<AMessage> msg new AMessage(kWhatDequ…...
git提交报错 fatal: LF would be replaced by CRLF in package-lock.json
报错 fatal: LF would be replaced by CRLF in package-lock.json 原因 git 在windows下,默认是CRLF作为换行符, git add 提交时,会检查文本中是否有LF 换行符(linux系统),如果有则会告警, 所…...
卷积详解和并行卷积
ps:在 TensorFlow Keras 中,构建 Sequential 模型的正确方式是将层作为列表传递,而不是作为一系列单独的参数。 modelmodels.Sequential([layers,layers]) 而不是modelmodels.Sequential(layers,layers) 文章目录 卷积…...
c#生成二维码二维码中间添加定制LoGo
🚀介绍 🍀QRCoder是一个开源的.NET库,用于生成QR码(Quick Response Code)。这个库是用C#编写的,并且可以在.NET框架的各种版本上使用,包括.NET Framework, .NET Core, Mono, Xamarin等。QRCode…...
设计CPU功能的数字电路
实验目的(1)熟悉Multisim 电路仿真软件的操作界面和功能; (2)掌握逻辑电路综合设计,并采用仿真软件进行仿真。 实验内容1.试设计一个简易CPU功能的数字电路,实验至少要求采用4个74HC/HCT194作为4个存储单元(可以预先对存储单元存储数据),74HC283作为计算单元。请实现…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
