Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QJson组件的实现对JSON文本的灵活解析功能。

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它易于人阅读和编写,也易于机器解析和生成。该格式是基于JavaScript语言的一个子集,但它是一种独立于语言的数据格式,因此可以在许多不同的编程语言中使用。

该数据是以键值对的形式组织的,其中键是字符串,值可以是字符串、数字、布尔值、数组、对象(即嵌套的键值对集合)或null,在Qt中默认提供了QJson系列类库,使用该类库可以很方便的解析和处理JSON文档。

1.1 解析单一键值对

实现解析根中的单一键值对,例如解析config.json配置文件中的blog,enable,status等这些独立的字段值,在解析之前需要先通过QJsonDocument::fromJson将内存中的字符串格式化为QJsonDocument类型,当有着该类型之后,则我们可以使用*.object()将其转换为对应的QJsonObject对象,在对象中我们可以调用各种方法对内存中的JSON数据进行处理。

以下是关于 QJsonDocument 类的一些常用方法的说明:

方法 说明
QJsonDocument() 构造函数,创建一个空的 JSON 文档。
QJsonDocument(const QJsonObject &object) 通过给定的 JSON 对象构造 JSON 文档。
QJsonDocument(const QJsonArray &array) 通过给定的 JSON 数组构造 JSON 文档。
QJsonDocument(const QJsonValue &value) 通过给定的 JSON 值构造 JSON 文档。
QJsonDocument(const QJsonDocument &other) 复制构造函数。
QJsonDocument &operator=(const QJsonDocument &other) 赋值运算符。
bool isNull() const 检查文档是否为空。
bool isEmpty() const 检查文档是否为空,包括 JSON 数组或对象为空的情况。
QJsonObject object() const 返回文档中的 JSON 对象。
QJsonArray array() const 返回文档中的 JSON 数组。
QJsonValue value() const 返回文档中的 JSON 值。
bool isArray() const 检查文档是否包含 JSON 数组。
bool isObject() const 检查文档是否包含 JSON 对象。
QByteArray toBinaryData() const 将文档转换为二进制数据。
bool fromBinaryData(const QByteArray &data) 从二进制数据恢复文档。
QString toJson(QJsonDocument::JsonFormat format = QJsonDocument::Compact) const 返回 JSON 字符串表示,可以选择格式化的方式。
static QJsonDocument fromJson(const QString &json, QJsonParseError *error = nullptr) 从 JSON 字符串创建文档。

以下是关于 QJsonObject 类的一些常用方法的说明:

方法 说明
QJsonObject() 构造函数,创建一个空的 JSON 对象。
QJsonObject(const QJsonObject &other) 复制构造函数。
QJsonObject &operator=(const QJsonObject &other) 赋值运算符。
bool isEmpty() const 检查对象是否为空。
int size() const 返回对象中键值对的数量。
bool contains(const QString &key) const 检查对象中是否包含指定的键。
QStringList keys() const 返回对象中所有键的列表。
QJsonValue value(const QString &key) const 返回与指定键关联的值。
void insert(const QString &key, const QJsonValue &value) 向对象中插入键值对。
QJsonObject &unite(const QJsonObject &other) 将另一个对象的键值对合并到当前对象。
void remove(const QString &key) 从对象中移除指定键及其关联的值。
QJsonValue take(const QString &key) 移除并返回与指定键关联的值。
void clear() 移除对象中的所有键值对,使其变为空对象。
QJsonDocument toDocument() const 将对象转换为 JSON 文档。

当需要读取参数时只需要使用find()方法查询特定字段中的key值即可,按钮on_pushButton_clicked被点击后执行如下流程;

void MainWindow::on_pushButton_clicked()
{
// 字符串格式化为JSON
QJsonParseError err_rpt;
QJsonDocument root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
if(err_rpt.error != QJsonParseError::NoError)
{
QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
} // 获取到Json字符串的根节点
QJsonObject root_object = root_document.object(); // 解析blog字段
QString blog = root_object.find("blog").value().toString();
//std::cout << "字段对应的值 = > "<< blog.toStdString() << std::endl;
ui->lineEdit_blog->setText(blog); // 解析enable字段
bool enable = root_object.find("enable").value().toBool();
//std::cout << "是否开启状态: " << enable << std::endl;
ui->lineEdit_enable->setText(QString::number(enable)); // 解析status字段
int status = root_object.find("status").value().toInt();
//std::cout << "状态数值: " << status << std::endl;
ui->lineEdit_status->setText(QString::number(status));
}

运行后点击读取数据按钮,输出效果如下;

1.2 解析单数组键值

实现解析简单的单一对象与单一数组结构,如配置文件中的GetDictGetList既是我们需要解析的内容,在解析时我们需要通过toVariantMap将字符串转换为对应的Map容器,当数据被转换后则就可以通过Map[]的方式很容易的将其提取出来。

void MainWindow::on_pushButton_2_clicked()
{
// 字符串格式化为JSON
QJsonParseError err_rpt;
QJsonDocument root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
if(err_rpt.error != QJsonParseError::NoError)
{
QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
} // 获取到Json字符串的根节点
QJsonObject root_object = root_document.object(); // 解析单一对象
QJsonObject get_dict_ptr = root_object.find("GetDict").value().toObject();
QVariantMap map = get_dict_ptr.toVariantMap(); if(map.contains("address") && map.contains("username") && map.contains("password") && map.contains("update"))
{
QString address = map["address"].toString();
QString username = map["username"].toString();
QString password = map["password"].toString();
QString update = map["update"].toString(); std::cout
<< " 地址: " << address.toStdString()
<< " 用户名: " << username.toStdString()
<< " 密码: " << password.toStdString()
<< " 更新日期: " << update.toStdString()
<< std::endl; ui->listWidget->addItem(address);
ui->listWidget->addItem(username);
ui->listWidget->addItem(password);
ui->listWidget->addItem(update);
} // 解析单一数组
QJsonArray get_list_ptr = root_object.find("GetList").value().toArray(); for(int index=0; index < get_list_ptr.count(); index++)
{
int ref_value = get_list_ptr.at(index).toInt();
std::cout << "输出数组元素: " << ref_value << std::endl; ui->listWidget_2->addItem(QString::number(ref_value));
}
}

运行后点击解析数据按钮,输出效果如下;

1.3 解析多数组键值

实现解析字典嵌套字典或字典嵌套数组的结构,如配置文件中的ObjectInArrayJson则是一个字典中嵌套了另外两个字典而每个字典中的值又是一个Value数组,而与之相对应的ArrayJson则是在列表中嵌套了另外一个列表,这两中结构的使用读者可参照如下案例;

首先我们来看ObjectInArrayJson是如何被解析的,我们分别准备两个ComboBox选择框,当读者点击按钮时我们通过toVariantMap将字典转换为一个MAP容器,并通过toJsonArray转换内部的列表到JsonArray容器内,其初始化部分如下所示;

void MainWindow::on_pushButton_3_clicked()
{
// 字符串格式化为JSON
QJsonParseError err_rpt;
QJsonDocument root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
if(err_rpt.error != QJsonParseError::NoError)
{
QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
} // 获取到Json字符串的根节点
QJsonObject root_object = root_document.object(); // 找到Object对象
QJsonObject one_object_json = root_object.find("ObjectInArrayJson").value().toObject(); // 转为MAP映射
QVariantMap map = one_object_json.toVariantMap(); // 寻找One键
QJsonArray array_one = map["One"].toJsonArray(); for(int index=0; index < array_one.count(); index++)
{
QString value = array_one.at(index).toString(); std::cout << "One => "<< value.toStdString() << std::endl;
ui->comboBox->addItem(value);
} // 寻找Two键
QJsonArray array_two = map["Two"].toJsonArray(); for(int index=0; index < array_two.count(); index++)
{
QString value = array_two.at(index).toString(); std::cout << "Two => "<< value.toStdString() << std::endl;
ui->comboBox_2->addItem(value);
}
}

同理,要实现解析数组中的数组也可以通过该方式实现,如配置文件中的ArrayJson既是我们需要解析的内容,首先我们通过isArray判断该节点是否为数组,如果是则通过toArray().at方法以此得到不同下标元素参数,并依次循环即可,其代码如下所示;

void MainWindow::on_pushButton_4_clicked()
{
// 字符串格式化为JSON
QJsonParseError err_rpt;
QJsonDocument root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
if(err_rpt.error != QJsonParseError::NoError)
{
QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
} // 获取到Json字符串的根节点
QJsonObject root_object = root_document.object(); // 获取MyJson数组
QJsonValue array_value = root_object.value("ArrayJson"); // 验证节点是否为数组
if(array_value.isArray())
{
// 得到数组个数
int array_count = array_value.toArray().count(); // 循环数组个数
for(int index=0;index <= array_count;index++)
{
QJsonValue parset = array_value.toArray().at((index));
if(parset.isArray())
{
QString address = parset.toArray().at(0).toString();
QString username = parset.toArray().at(1).toString();
QString userport = parset.toArray().at(2).toString(); std::cout
<< "地址: " << address.toStdString()
<< "用户名: " << username.toStdString()
<< "端口号: " << userport.toStdString()
<< std::endl; ui->comboBox_3->addItem(address);
ui->comboBox_4->addItem(username);
ui->comboBox_5->addItem(userport);
}
}
}
}

运行后点击两个初始化按钮则可以将字典或列表中的数据依次解析到不同的ComBobox列表框内,输出效果如下;

1.4 解析多字典键值

实现解析字典中嵌套多个参数或字典中嵌套参数中包含列表的数据集,如配置文件中的ObjectJson则是字典中存在多个键值对,而ObjectArrayJson则更进一步在多键值对中增加了列表的支持,解析此类内容只需要依次逐级拆分即可,我们来看下如何实现对这些键值的灵活提取;

首先我们来实现对ObjectJson的参数解析功能,读者可自行对比与之前1.3中的区别,可以发现这两者的差别其实不大,解析ObjectJson完整代码如下所示;

void MainWindow::on_pushButton_5_clicked()
{
// 字符串格式化为JSON
QJsonParseError err_rpt;
QJsonDocument root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
if(err_rpt.error != QJsonParseError::NoError)
{
QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
} // 获取到Json字符串的根节点
QJsonObject root_object = root_document.object(); // 获取MyJson数组
QJsonValue object_value = root_object.value("ObjectJson"); // 验证是否为数组
if(object_value.isArray())
{
// 获取对象个数
int object_count = object_value.toArray().count(); // 循环个数
for(int index=0;index <= object_count;index++)
{
QJsonObject obj = object_value.toArray().at(index).toObject(); // 验证数组不为空
if(!obj.isEmpty())
{
QString address = obj.value("address").toString();
QString username = obj.value("username").toString(); std::cout << "地址: " << address.toStdString() << " 用户: " << username.toStdString() << std::endl;
ui->comboBox_6->addItem(address);
ui->comboBox_7->addItem(username);
}
}
}
}

接着我们来实现一个更为复杂的需求,解析多字典中嵌套的数组,如配置文件中的ObjectArrayJson则是我们需要解析的内容,在之前解析字典部分保持与上述案例一致,唯一不同的是我们需要通过value("ulist").toArray()获取到对应字典中的数组,并通过循环的方式输出。

如下案例中,当读者点击初始化按钮时我们首先让字典中的数据填充之ComboBox列表框中,接着当读者点击第一个列表框时我们让其过滤出特定的内容并赋值到第二个列表框中,以此实现联动效果,首先初始化部分如下所示;

void MainWindow::on_pushButton_6_clicked()
{
// 字符串格式化为JSON
QJsonParseError err_rpt;
QJsonDocument root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
if(err_rpt.error != QJsonParseError::NoError)
{
QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
} // 获取到Json字符串的根节点
QJsonObject root_object = root_document.object(); // 获取MyJson数组
QJsonValue object_value = root_object.value("ObjectArrayJson"); // 验证是否为数组
if(object_value.isArray())
{
// 获取对象个数
int object_count = object_value.toArray().count(); // 循环个数
for(int index=0;index <= object_count;index++)
{
QJsonObject obj = object_value.toArray().at(index).toObject(); // 验证数组不为空
if(!obj.isEmpty())
{
QString uname = obj.value("uname").toString();
std::cout << "用户名: " << uname.toStdString() << std::endl; ui->comboBox_8->addItem(uname); // 解析该用户的数组
int array_count = obj.value("ulist").toArray().count(); std::cout << "数组个数: "<< array_count << std::endl; for(int index=0;index < array_count;index++)
{
QJsonValue parset = obj.value("ulist").toArray().at(index); int val = parset.toInt(); std::cout << "Value = > "<< val << std::endl;
ui->comboBox_9->addItem(QString::number(val));
}
}
}
}
}

当第一个选择框被选中时我们触发currentIndexChanged信号,在其中只需要判断uname.compare(arg1)是否相等如果相等则addItem追加到新的列表内,运行效果如下所示,详细实现可参考附件。

1.5 解析多字典嵌套

实现解析多个字典嵌套或多个列表嵌套的结构,如配置文件中的NestingObjectJson则是字典中嵌套字典,而ArrayNestingArrayJson则是列表中嵌套列表,两种的解析方式基本一致。

我们首先来实现第一种格式的解析,当按钮被点击后,我们首先查询uuid字段并赋值到ComBobox列表中,实现代码如下所示;

void MainWindow::on_pushButton_7_clicked()
{
// 字符串格式化为JSON
QJsonParseError err_rpt;
QJsonDocument root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
if(err_rpt.error != QJsonParseError::NoError)
{
QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
} // 获取到Json字符串的根节点
QJsonObject root_object = root_document.object(); // 获取NestingObjectJson数组
QJsonValue array_value = root_object.value("NestingObjectJson"); // 验证节点是否为数组
if(array_value.isArray())
{
// 得到内部对象个数
int count = array_value.toArray().count();
std::cout << "对象个数: " << count << std::endl; for(int index=0; index < count; index++)
{
// 得到数组中的index下标中的对象
QJsonObject array_object = array_value.toArray().at(index).toObject(); QString uuid = array_object.value("uuid").toString(); // 追加数据
std::cout << uuid.toStdString() << std::endl;
ui->comboBox_10->addItem(uuid); // 开始解析basic中的数据
QJsonObject basic = array_object.value("basic").toObject(); QString lat = basic.value("lat").toString();
QString lon = basic.value("lon").toString(); std::cout << "解析basic中的lat字段: " << lat.toStdString() << std::endl;
std::cout << "解析basic中的lon字段: " << lon.toStdString()<< std::endl; // 解析单独字段
QString status = array_object.value("status").toString();
std::cout << "解析字段状态: " << status.toStdString() << std::endl;
}
}
}

ComBobox组件中的currentIndexChanged信号被触发时,则直接执行对LineEdit编辑框的赋值操作,其代码如下所示;

void MainWindow::on_comboBox_10_currentIndexChanged(const QString &arg1)
{
// 字符串格式化为JSON
QJsonParseError err_rpt;
QJsonDocument root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
if(err_rpt.error != QJsonParseError::NoError)
{
QMessageBox::information(nullptr,"提示","JSON格式错误",QMessageBox::Ok);
} // 获取到Json字符串的根节点
QJsonObject root_object = root_document.object(); // 获取NestingObjectJson数组
QJsonValue array_value = root_object.value("NestingObjectJson"); // 验证节点是否为数组
if(array_value.isArray())
{
// 得到内部对象个数
int count = array_value.toArray().count();
std::cout << "对象个数: " << count << std::endl; for(int index=0; index < count; index++)
{
// 得到数组中的index下标中的对象
QJsonObject array_object = array_value.toArray().at(index).toObject(); QString uuid = array_object.value("uuid").toString(); // 对比是否相等
if(uuid.compare(arg1) == 0)
{
// 开始解析basic中的数据
QJsonObject basic = array_object.value("basic").toObject(); QString lat = basic.value("lat").toString();
QString lon = basic.value("lon").toString(); std::cout << "解析basic中的lat字段: " << lat.toStdString() << std::endl;
std::cout << "解析basic中的lon字段: " << lon.toStdString()<< std::endl; ui->lineEdit->setText(lat);
ui->lineEdit_2->setText(lon); // 解析单独字段
QString status = array_object.value("status").toString();
std::cout << "解析字段状态: " << status.toStdString() << std::endl;
}
}
}
}

同理,我们也可以实现字典中嵌套列表结构,如配置文件中的ArrayNestingArrayJson既我们需要解析的内容,解析实现方法与上述代码保持一致,首先当按钮被点击后我们直接对ComBobox组件进行初始化,代码如下所示;

void MainWindow::on_pushButton_8_clicked()
{
// 字符串格式化为JSON
QJsonParseError err_rpt;
QJsonDocument root_document = QJsonDocument::fromJson(config.toUtf8(), &err_rpt);
if(err_rpt.error != QJsonParseError::NoError)
{
std::cout << "json 格式错误" << std::endl;
} // 获取到Json字符串的根节点
QJsonObject root_object = root_document.object(); // 获取NestingObjectJson数组
QJsonValue array_value = root_object.value("ArrayNestingArrayJson"); // 验证节点是否为数组
if(array_value.isArray())
{
// 得到数组中的0号下标中的对象
QJsonObject array_object = array_value.toArray().at(0).toObject(); // 解析手机号字符串
QString telephone = array_object.value("telephone").toString();
std::cout << "手机号: " << telephone.toStdString() << std::endl; ui->comboBox_11->addItem(telephone); // 定位外层数组
QJsonArray root_array = array_object.find("path").value().toArray();
std::cout << "外层循环计数: " << root_array.count() << std::endl; for(int index=0; index < root_array.count(); index++)
{
// 定位内层数组
QJsonArray sub_array = root_array.at(index).toArray();
std::cout << "内层循环计数: "<< sub_array.count() << std::endl; for(int sub_count=0; sub_count < sub_array.count(); sub_count++)
{
// 每次取出最里层数组元素
float var = sub_array.toVariantList().at(sub_count).toFloat(); std::cout << "输出元素: " << var << std::endl;
// std::cout << sub_array.toVariantList().at(0).toFloat() << std::endl; ui->listWidget_3->addItem(QString::number(var));
}
}
}
}

运行效果如下图所示;

C++ Qt开发:运用QJSON模块解析数据的更多相关文章

  1. 一起来开发Android的天气软件(四)——使用Gson解析数据

    离上一篇文章过去才4.5天,我们赶紧趁热打铁继续完毕该系列的天气软件的开发. 承接上一章的内容使用Volley实现网络的通信.返回给我们的是这一串Json数据{"weatherinfo&qu ...

  2. Android商城开发系列(六)——使用 OkHttpUtils 请求网络 + 使用 fastjson解析数据

    OkHttp是Google推荐使用的一个开源的网络请求框架,Android开发中涉及到网络请求和接口调用现在大部分都是使用OkHttp,网上已经有不少人针对OkHttp进行了封装,这里推荐一下鸿洋大神 ...

  3. 一步一步开发sniffer(Winpcap+MFC)(五)莫道无人能识君,其实我懂你的心——解析数据包(转)

    前文已经讲过,解析数据包主要通过analyze_frame()这个函数实现的,实际上并非这个函数完成了所有的功能,其实从名字就可以看出,它只是完成了对“帧”的解析,也就是链路层数据的解析,还有anal ...

  4. Qt开发北斗定位系统融合百度地图API及Qt程序打包发布

    Qt开发北斗定位系统融合百度地图API及Qt程序打包发布 1.上位机介绍 最近有个接了一个小型项目,内容很简单,就是解析北斗GPS的串口数据然后输出经纬度,但接过来觉得太简单,就发挥了主观能动性,增加 ...

  5. QT json字符串生成和解析

    1         QT json字符串生成和解析 1.1  QT Json解析流程 (1)  字符串转化为QJsonDocument QJsonParseError json_error; QJso ...

  6. 【应用笔记】【AN005】Qt开发环境下基于RS485的4-20mA电流采集

    简介 4-20mA电流环具有广泛的应用前景,在许多行业中都发挥着重要作用.本文主要介绍在Qt开发环境下基于RS485实现4-20mA电流采集,实现WINDOWS平台对数据的采集.分析及显示. 系统组成 ...

  7. QT开发之旅三串口设备调试工具

    这里首先说明一下,这个为什么叫串口设备调试工具而不是串口调试工具,是因为这个工具比网络上的串口调试工具多出了一些真实需要的用来调试设备的功能,首先一点就是大部分的串口调试工具收到数据都是立即返回,这样 ...

  8. [转]使用QT开发GoogleMap瓦片显示和下载工具

    第一节 之前做项目的时候经常遇到需要大量地图背景数据,然后没有数据被逼着去Google上下载瓦片数据在拼接成整张影像的工作,其实遥感影像晚上有很多可以下载到的,但是大部分是作为研究用的,作为GIS的背 ...

  9. windows下VisualStudio和QtCreator搭建Qt开发环境

    一.简介 集成开发平台IDE都有各自的长处,编写Qt程序可根据自己的喜好来选择相应的IDE.下述文章都是装载博友的文章,其中有很多细节还得自己调整. 二.详解 1.VisualStudio搭建Qt开发 ...

  10. 基于arm的嵌入式QT开发(课程设计)

    一. 项目要求 配置QT5.7基于x86及arm 等两种CPU架构的调试及开发环境: 移植arm编译后的QT5.7及屏幕校准工具tslib1.4至CORTEX ARM9实验平台: 开发基于QT5.7的 ...

随机推荐

  1. 【短道速滑六】古老的视频去噪算法(FLT_GradualNoise)解析并优化,可实现1920*1080 YUV数据400fps的处理能力。

    这个好像没有啥对应的论文可以找到,在百度上搜索也能找到一些相关的资料,不过就直接是代码,可以看到其实来自于一个叫做DScaler的项目,在github上目前还能找到该项目的完整资料. 详见:https ...

  2. 【Docker】容器操作 mysql部署 redis部署 nginx部署 迁移与备份 Dockerfile

    目录 上节回顾 今日内容 1 容器操作 2 应用部署 2.1 mysql 部署 2.2 redis 2.3 nginx 3 迁移与备份 4 Dockerfile 练习 上节回顾 # 1 docker ...

  3. Android 黑马 52 期视频,不加密,免费下载

    Android 黑马学习视频 目录 01.安卓基础+JNI (14天) 02.Android应用开 发-代码版本管理和实战(1天) 03.android案 例与项目_手机安全卫士(12天) 04.自定 ...

  4. 百年奥运的凌空之美,AI 云智剪背后的新算法

    奥运赛事每天都在上演冰雪奇迹,而捕捉发生瞬间,凝结最精彩.最动人的体育人文画面,让"冰之舞"."雪之舞"."速度之美"."凌空之美 ...

  5. 三、springboot集成达梦

    1.数据库中创建表 1.数据库中创建表 CREATE TABLE TEST_BLOCK_T ( BLOCK_ID VARCHAR2(10 BYTE) PRIMARY KEY, --编码 BLOCK_N ...

  6. 二、mongo集群搭建

    系列导航 一.linux单机版mongo安装(带密码验证) 二.mongo集群搭建 三.java连接mongo数据库 四.java对mongo数据库增删改查操作 五.mongo备份篇 mongoexp ...

  7. C# Redis的五大数据结构相关操作及应用场景

    Cache和NoSql.Redis ServiceStack.Redis 下面额代码类均是通过 ServiceStack.Redis 来对Redis进行各种操作 redis 文件配置类 /// < ...

  8. shell脚本(13)-shell函数

    一.函数介绍 将相同功能的代码模块化,使得代码逻辑上比较简单,代码量少,排错容易 函数的优点: 1.代码模块化,调用方便,节省内存 2.代码模块化,代码量少,排错简单 3.代码模块化,可以改变代码的执 ...

  9. Dubbo入门1:Spirngboot+Dubbo2.6.0整合

    整合springboot+dubbo2.6.0 demo 本文简要说明了springboot和dubbo整合的配置文件的写法 目录结构 整体目录 如下图所示:整体项目是一个父子工程,common作为一 ...

  10. 如何学习 Photoshop

    你有没有想过"图像处理或图形设计看起来很酷,我要学习 Photoshop!" 然后你第一次打开 Photoshop,并被你所看到的东西所震撼. Photoshop 是一款功能强大的 ...