Qt 天气预报项目
参考引用
- QT开发专题-天气预报
1. JSON 数据格式
1.1 什么是 JSON
- JSON (JavaScript Object Notation),中文名 JS 对象表示法,因为它和 JS 中对象的写法很类似
- 通常说的 JSON,其实就是 JSON 字符串,本质上是一种特殊格式的字符串
- JSON 是一种轻量级的数据交换格式,客户端和服务端数据交互,基本都是 JSON 格式的
- JSON 有以下特点
- 便于阅读和书写
- 除了 JSON 格式,还有一种数据传输格式 XML,相对于 XML,JSON 更加便于阅读和书写独立于编程语言
- 网络传输的标准数据格式
- 完全独立于编程语言
- 几乎在所有的编程语言和开发环境中,都有解析和生成 JSON 字符串的库
// C Jansson cJSON// C++ jsonCpp、JSON for Modern C++// Java json-lib、org-json// Qt QJSONxxx - 便于阅读和书写
1.2 JSON 的两种数据格式
JSON 有两种数据格式
- JSON 对象(被大括号包裹)
- JSON 数组(被中括号包裹)
1.2.1 JSON 数组
- JSON 数组格式
[元素1, 元素2, 元素3, ... 元素n] - 类似于 c/C++ 中的数组,元素之间以逗号分隔。不同的是,JSON 数组中的元素可以是不同的数据类型
- 包括:整型、浮点、字符串、布尔类型、JSON 数组、JSON 对象、空值
// JSON 数组中的元素是同一类型 [1, 2, 3, 4] ["Spring", "Summer", "Autumn", "Winter"]// JSON 数组中的元素是不同类型 [1, 2.5, "hello", true, false, null]// JSON 数组的嵌套 [[1, 2, 3, 4],["Spring", "Summer", "Autumn", "Winter"],[1, 2.5, "hello", true, false, null] ]// JSON 数组嵌套 JSON 对象 [{"name": "Tom","age": 18,"gender": "male"}{"name": "Lucy","age": 20,"gender": "female"} ]
1.2.2 JSON 对象
- JSON 对象格式
{"key1": value1,"key2": value2,"key3": value3 } - JSON 对象内部使用键值对的方式来组织
- 键和值之间使用冒号分隔,多个键值之间使用逗号分隔
- 键是字符串类型,值的类型可以是:整型、浮点、字符串、布尔类型、JSON 数组、JSON 对象、空值
{"name": "Tom","age": 18,"gender": "male" } - JSON 对象中,还可以嵌套 JSON 对象和 JSON 数组
{"name": "China","info": {"capital": "beijing","asian": true,"founded": 1949},"provinces": [{"name": "hunan","capital": "changsha"}, {"name": "hubei","capital": "wuhan"}] }
1.3 JSON 在线解析
- JSON 本质就是一种特殊格式的字符串
- 实际工作中,这个 JSON 字符串可能是自己手写的,也可能是来自网络接收的数据
- 下面的一段 JSON 字符串,它可能是自己写的,也可能是服务端返回的
- 它是压缩的格式,也就是没有换行和缩进,不方便判断格式是否正确
- 可以通过 JSON 在线解析工具来校验这个 JSON 的格式是否正确
{"name":"China","info":{"capital":"beijing","asian":true,"founded":1949},"provinces": [{"name":"hunan","capital":"changsha"},{"name":"hubei","capital": "huhan"}]}

1.4 Qt 中使用 JSON
1.4.1 JSON 相关的类
(1)QJsonObject
- QJsonObject 封装了 JSON 中的对象,可以存储多个键值对
- 其中,键为字符串类型,值为 QJsonValue 类型
- 创建一个 QJsonObject 对象
QJsonObject::QJsonObject(); - 将键值对添加到 QJsonObject 对象中
QJsonObject::iterator insert(const QString &key, const QJsonValue &value); - 获取 QJsonObject 对象中键值对的个数
int QJsonObject::count() const; int QJsonObject::size() const; int QJsonObject::length() const; - 通过 key 得到 value
QJsonValue QJsonObject::value(const QString &key) const; QJsonValue QJsonObject::operator[](const QString &key) const; - 检查 key 是否存在
iterator QJsonObject::find(const QString &key); bool QJsonObject::contains(const QString &key) const; - 遍历 key
QStringList QJsonObject::keys() const;
(2)QJsonArray
- QJsonArray 封装了 Json 中的数组,数组中元素类型统一为 QJsonValue 类型
- 创建一个 QJsonArray
QJsonArray::QJsonArray(); - 添加数组元素
// 添加到头部和尾部 void QJsonArray::append(const QJsonValue &value); void QJsonArray::prepend(const QJsonValue &value);// 插入到 i 的位置之前 void QJsonArray::insert(int i, const QJsonValue &value);// 添加到头部和尾部 void QJsonArray::push_back(const QJsonValue &value); void QJsonArray::push_front(const QJsonValue &value); - 获取 QJsonArray 中元素个数
int QJsonArray::count() const; int QJsonArray::size() const; - 获取元素的值
// 获取头部和尾部 QJsonValue QJsonArray::first() const; QJsonValue QJsonArray::last() const;// 获取指定位置 QJsonValue QJsonArray::at(int i) const; QJsonValueRef QJsonArray::operator[](int i); - 删除元素
// 删除头部和尾部 void QJsonArray::pop_back(); void QJsonArray::pop_front();void QJsonArray::removeFirst(); void QJsonArray::removeLast();// 删除指定位置 void QJsonArray::removeAt(int i); QJsonValue QJsonArray::takeAt(int i);
(3)QJsonValue
-
封装了 JSON 支持的六种数据类型
QJsonValue::Bool // 布尔类型 QJsonValue::Double // 浮点(含整型)类型 QJsonValue::String // 字符串类型 QJsonValue::Array // Json 数组类型 QJsonValue::Object // Json 对象类型 QJsonValue::Null // 空值类型 -
可以通过以下方式构造 QJsonValue 对象
// 字符串 QJsonValue(const char *s); QJsonValue(QLatin1String s); QJsonValue(const QString &s);// 整型 and 浮点型 QJsonValue(qint64 v); QJsonValue(int v); QJsonValue(double v);// 布尔类型 QJsonValue(bool b);// Json 对象 QJsonValue(const QJsonObject &o);// Json 数组 QJsonValue(const QJsonArray &a);// 空值类型 QJsonValue(QJsonValue::Type type = Null); -
判断一个 QJsonValue 对象内部封装数据类型
// 是否是字符串类型 bool isString() const;// 是否是浮点类型(整形也是通过该函数判断) bool isDouble const;// 是否是布尔类型 bool isBool() const;// 是否是Json对象 bool isObject() const;// 是否是 Json 数组 bool isArray() const;// 是否是未定义类型(无法识别的类型) bool isUndefined() const;// 是否是空值类型 bool isNull() const; -
数据类型之间的转换 API 函数
// 转换为字符串类型 QString toString() const; QString toString(const QString &defaultValue) const;// 转换为浮点类型 double toDouble(double defaultValue = 0) const;// 转换为整形 int toInt(int defaultValue = 0) const;// 转换为布尔类型 bool toBool(bool defaultValue = false) const;// 转换为 Json 对象 QJsonObject toObject() const; QJsonObject toObject(const QJsonObject &defaultValue) const;// 转换为 Json 数组 QJsonArray toArray() const; QJsonArray toArray(const QJsonArray &defaultValue) const;
(3)QJsonDocument
-
它封装了一个完整的 JSON 文档
- 它可以从 UTF-8 编码的基于文本的表示,以及 Qt 本身的二进制格式读取和写入该文档
- QJsonObject 和 QJsonArray 不能直接转换为字符类型,需通过 QJsonDocument 来完成二者的转换
-
QJsonObject/QJsonArray ==> 字符串
// 1. 创建 QJsonDocument 对象 // 以 QJsonObject 或 QJsonArray 为参数来创建 QJsonDocument 对象 QJsonDocument::QJsonDocument(const QJsonObject &object); QJsonDocument::QJsonDocument(const QJsonArray &array);// 2. 将 QJsonDocument 对象中的数据进行序列化 // 通过调用 toXXX() 方法就可得到文本格式或者二进制格式的 Json 字符串 QByteArray QJsonDocument::toBinaryData() const; // 二进制格式的 json 字符串 QByteArray QJsonDocument::toJson(JsonFormat format = Indented) const; // 文本格式// 3. 使用得到的字符串进行数据传输,或者保存到文件 -
字符串 ==> QJsonObject/QJsonArray
- 通常,通过网络接收或者读取磁盘文件,会得到一个 JSON 格式的字符审,之后可以按照如下步骤,解析出 JSON 字符串中的一个个字段
// 1. 将 JSON 字符串转换为 QJsonDocument 对象 [static] QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data,DataValidation validation = Validate); [static] QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error = Q_NULLPTR);// 2. 将文档对象转换为 json 数组 / 对象 // 2.1 判断文档对象中存储的数据是 JSON 数组还是 JSON 对象 bool QJsonDocument::isArray() const; bool QJsonDocument::isObject() const;// 2.2 转换为 JSON 数组或 JSON 对象 QJsonObject QJsonDocument::object() const; QJsonArray QJsonDocument::array() const;// 3. 调用 QJsonArray / QJsonObject 类提供的 API 获取存储在其中的数据
1.4.2 构建 JSON 字符串
- 在网络传输时,通常是传输的 JSON 字符串,传输之前,首先要生成 JSON 字符串
- 接下来使用 Qt 提供的工具类,来生成如下格式的 JSON 字符串
{"name": "China","info": {"capital": "beijing","asian": true,"founded": 1949},"provinces": [{"name": "hunan","capital": "changsha"}, {"name": "hubei","capital": "wuhan"}] } - 代码实现
#include <QCoreApplication>#include <QJsonObject> #include <QJsonArray> #include <QJsonDocument>#include <QFile> #include <QByteArray> #include <QDebug> #include <QString>void writeJson() {QJsonObject rootObj;// 1. 插入 name 字段rootObj.insert("name", "China");// 2. 插入 info 字段QJsonObject infoObj;infoObj.insert("capital", "beijing");infoObj.insert("asian", true);infoObj.insert("founded", 1949);rootObj.insert("info", infoObj);// 3. 插入 provinces 字段QJsonArray provinceArray;QJsonObject hunanObj;hunanObj.insert("name", "hunan");hunanObj.insert("capital", "changsha");QJsonObject hubeiObj;hubeiObj.insert("name", "hubei");hubeiObj.insert("capital", "wuhan");provinceArray.append(hunanObj);provinceArray.append(hubeiObj);rootObj.insert("provinces", provinceArray);// 4. 将 QJsonObject 对象 rootObj 转换为 Json 字符串QJsonDocument doc(rootObj);QByteArray json = doc.toJson();// 5.1 打印输出qDebug() << QString(json).toUtf8().data();// 5.2 将 json 字符串写入文件QFile file("d:\\china.json");file.open(QFile::WriteOnly);file.write(json);file.close(); }int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);writeJson();return a.exec(); }
1.4.3 解析 JSON 字符串
- 通常接收网络数据的格式是JSON 格式,在接收完毕之后,需要解析出其中的每一个字段,根据各个字段的值做相应的显示或者其他处理
#include <QCoreApplication>#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonValue>#include <QFile>
#include <QByteArray>
#include <QDebug>
#include <QString>
#include <QStringList>void fromJson() {// 1. 读取文件QFile file("d:\\china.json");file.open(QFile::ReadOnly);QByteArray json = file.readAll();file.close();QJsonDocument doc = QJsonDocument::fromJson(json);if (!doc.isObject()) {qDebug() << "Not an object!";return;}// 2. 开始解析QJsonObject obj = doc.object();QStringList keys = obj.keys();for (int i = 0; i < keys.size(); i++) {// 获取 key-value 对QString key = keys[i];QJsonValue value = obj.value(key);if (value.isBool()) {qDebug() << key << ":" << value.toBool();} else if (value.isString()) {qDebug() << key << ":" << value.toString();} else if (value.isDouble()) {qDebug() << key << ":" << value.toInt();} else if (value.isObject()) {qDebug() << key << ":";QJsonObject infoObj = value.toObject();QString capital = infoObj["capital"].toString();bool asian = infoObj["asian"].toBool();int founded = infoObj["founded"].toInt();qDebug() << " " << "capital" << capital;qDebug() << " " << "asian" << asian;qDebug() << " " << "founded" << founded;} else if (value.isArray()) {qDebug() << key;QJsonArray provinceArray = value.toArray();for (int i = 0; i < provinceArray.size(); i++) {QJsonObject provinceObj = provinceArray[i].toObject();QString name = provinceObj["name"].toString();QString capital = provinceObj["capital"].toString();qDebug() << " " << "name" << ":" << name << ", capital" << ":" << capital;}}}
}int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);fromJson();return a.exec();
}
- 控制台输出
"info" :capital "beijing"asian truefounded 1949 "name" : "China" "provinces"name : "hunan" , capital : "changsha"name : "hubei" , capital : "wuhan"
2. HTTP 通信
2.1 HTTP 概述
HTTP:超文本传输协议 (HyperText Transfer Protocol),HTTP 是浏览器端 web 通信的基础
2.1.1 两种架构
- B/S 架构:Browser/server,浏览器/服务器架构
- B:浏览器,比如 Firefox、Internet Explorer、Google Chrome、Safari、Opera 等
- S:服务器,比如 Apache、nginx 等
- C/S 架构:client/server,客户端/服务器架构
- B/S 架构相对于 C/S 架构,客户机上无需安装任何软件,使用浏览器即可访问服务器,因此,越来越多的 C/S 架构正被 B/S 架构所替代
2.1.2 基于请求响应的模式
- HTTP 协议永远都是客户端发起请求,服务器做出响应
- 也就是说,请求必定是先从客户端发起的,服务器端在没有接收到请求之前不会发送任何响应
- 这就无法实现这样一种场景:服务端主动推送消息给客户端
2.1.3 无状态
-
当浏览器第一次发送请求给服务器时,服务器做出了响应
-
当浏览器第二次发送请求给服务器时,服务器同样可以做出响应,但服务器并不知道第二次的请求和第一次来自同一个浏览器
- 也就是说,服务器不会记住你是谁,所以是无状态的
-
而如果要使 HTTP 协议有状态,就可以使浏览器访问服务器时,加入 cookie,这样,只要你在请求时有了这个 cookie,服务器就能够通过 cookie 知道,你就是之前那个浏览器,这样,HTTP 协议就有状态了
2.1.4 请求报文
请求报文由四部分组成
- 请求行 + 请求头(请求首部字段) + 空行 + 实体
-
请求行
- 请求方法:比如 GET、POST
- 资源对象 (URL)
- 协议名称和版本号 (HTTP/1.1)

-
请求头(请求首部字段)
- 请求头用于告诉服务器该请求的一些信息,起到传递额外信息的目的

- 请求头用于告诉服务器该请求的一些信息,起到传递额外信息的目的
-
空行
- 空行是为了区分请求头和请求实体
-
请求实体
- 请求实体即真正所需要传输的数据
2.1.5 响应保文
响应报文同样是由四部分组成
- 状态行 + 响应头(响应报文首部) + 空行 + 消息体
-
状态行
- HTTP 版本
- 状态码 (表示相应的结果)
- 原因短语 (解释)

-
响应头(响应报文首部)
- 和请求报文首部一样,响应报文首部同样是为了传递额外信息

- 和请求报文首部一样,响应报文首部同样是为了传递额外信息
-
空行
- 同样是为了区别响应实体和响应首部
-
响应实体
- 真正存储响应信息的部分
2.1.6 请求方式
- HTTP 常用的请求方式有很多中,最常用的是 GET 和 POST
- 二者最主要的区别就是
- GET 请求的参数位于 URL 中,会显示在地址栏上
- POST 请求的参数位于 request body 请求体中
因此,GET 请求的安全性不如 POST 请求,并且 GET 请求的参数有长度限制,而 POST 没有
2.2 调试利器 Postman
- HTTP 包含客户端和服务端,试想下面的两种情况(Postman 使用场景)
- 服务端开发完毕,而客户端还未完成开发,此时服务端开发人员能否对自己写的服务端程序进行测试呢?
- 客户端开发人员访问服务端出错,比如无法访问服务端,有没有第三方的测试工具做进一步验证呢?
- Postman 是一个接口测试工具,主要是用来模拟各种 HTTP 请求 (比如 GET 请求、POST 请求等),在做接口测试的时候,Postman 相当于客户端,它可模拟用户发起的各类 HTTP 请求,将请求数据发送至服务端,并获取对应的响应结果
2.2.1 安装
- Postman 下载
2.2.2 发送请求
- 这里以获取北京的天气为例
- 获取北京天气的 URL 为:http://t.weather.itboy.net/api/weather/city/101010100
- 其中,101010100 是北京的城市编码,是 9 位的

2.3 Qt 实现 HTTP 请求
2.3.1 创建 “网络访问管理” 对象
- 首先需要创建一个 QNetworkAccessManager 对象,这是 Qt 中进行 HTTP 请求的开端
mNetAccessManager = new QNetworkAccessManager(this);
2.3.2 关联信号槽
- 在发送 HTTP 请求之前,先关联信号槽
// 获取到数据之后 connect(mNetAccessManager, &QNetworkAccessManager::finished, this, &MainWindow::onReplied);
2.3.3 发送请求
- 根据请求的地址构建出一个 Qurl 对象,然后直接调用 QNetworkAccessManager 的 get 方法,即可发送一个 GET 请求
Qurl ur1("http://t.weather.itboy.net/api/weather/city/101010100"); mNetAccessManager->get(QNetworkRequest(url));
2.3.4 接收数据
- 由于上面绑定了信号槽,服务器返回数据后,自动调用自定义的槽函数 onReplied
- 如下是 onReplied 函数的标准写法,QNetworkReply 中封装了服务器返回的所有数据,包括响应头、响应的状态码、响应体等
void MainWindow::onReplied(QNetworkReply *reply) {// 响应的状态码为200,表示请求成功int status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();qDebug() << "operation:" << reply->operation(); // 请求方式qDebug() << "status code:" << status_code; // 状态码qDebug() << "url:" << reply->url(); // urlqDebug() << "raw header:" << reply->rawHeaderList(); // headerif (reply->error() != QNetworkReply::NoError || status_code != 200) {QMessageBox::warning(this, "提示", "请求数据失败!", QMessageBox::OK);} else {// 获取响应信息QByteArray reply_data = reply->readAll();QByteArray byteArray = QString(reply_data).toUtf8();qDebug() << "read all:" << byteArray.data();// parseJson()}reply->deleteLater(); }
3. 详细代码实现
- WeatherForecast
相关文章:
Qt 天气预报项目
参考引用 QT开发专题-天气预报 1. JSON 数据格式 1.1 什么是 JSON JSON (JavaScript Object Notation),中文名 JS 对象表示法,因为它和 JS 中对象的写法很类似 通常说的 JSON,其实就是 JSON 字符串,本质上是一种特殊格式的字符串…...
新知识-Tuple元组的使用
文章目录 前言一、tuple元组是什么?二、解决方法总结 前言 这次碰到一个需求,大致需要把表A中的字段1和字段2作为共同的表去查表B,并且一次性需要查多条,一开始是想的是根据字段1和字段2去查然后循环多次,但是这样反复…...
“此应用专为旧版android打造,因此可能无法运行”,问题解决方案
当用户在Android P系统上打开某些应用程序时,可能会弹出一个对话框,提示内容为:“此应用专为旧版Android打造,可能无法正常运行。请尝试检查更新或与开发者联系”。 随着Android平台的发展,每个新版本通常都会引入新的…...
【Leetcode题单】(01 数组篇)刷题关键点总结03【数组的改变、移动】
【Leetcode题单】(01 数组篇)刷题关键点总结03【数组的改变、移动】(3题) 数组的改变、移动453. 最小操作次数使数组元素相等 Medium665. 非递减数列 Medium283. 移动零 Easy 大家好,这里是新开的LeetCode刷题系列&…...
Lag-Llama:基于 LlaMa 的单变量时序预测基础模型
文章构建了一个通用单变量概率时间预测模型 Lag-Llama,在来自Monash Time Series库中的大量时序数据上进行了训练,并表现出良好的零样本预测能力。在介绍Lag-Llama之前,这里简单说明什么是概率时间预测模型。概率预测问题是指基于历史窗口内的…...
vue3 :deep() 深度选择器不生效
vue3 :deep() 深度选择器不生效 问题出在根节点上,如果没有这个根节点,那么:deep()不起作用,我把根节点加上,:deep()样式就生效了。在组件外加个 就生效了 参考: 添加链接描述...
从零构建属于自己的GPT系列1:数据预处理(文本数据预处理、文本数据tokenizer、逐行代码解读)
🚩🚩🚩Hugging Face 实战系列 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在PyCharm中进行 本篇文章配套的代码资源已经上传 从零构建属于自己的GPT系列1:文本数据预处理 从零构建属于自己的GPT系列2:语…...
c++中函数的引用
函数中的引用 引用可以作为函数的形参 不能返回局部变量的引用 #include<iostream> #include<stdlib.h> using namespace std; //形参是引用 void swap(int *x, int *y)//*x *y表示对x y取地址 { int tmp *x; *x *y; *y tmp; } void test01() { …...
IDA常用操作、快捷键总结以及使用技巧
先贴一张官方的图,然后我再总结一下,用的频率比较高的会做一些简单标注 快捷键 F系列【主要是调试状态的处理】 F2 添加/删除断点F4 运行到光标所在位置F5 反汇编F7 单步步入F8 单步跳过F9 持续运行直到输入/断点/结束 shift系列【主要是调出对应的页…...
Kibana使用指南
使用介绍主要特点应用场景数据可视化还有哪些类型安装步骤安装配置参数Elasticsearch配置参数注意事项 使用介绍 Kibana是一个开源的分析与可视化平台,设计出来用于和Elasticsearch一起使用的。可以用Kibana搜索、查看、交互存放在Elasticsearch索引里的数据&#…...
wvp如果确认音频udp端口开放成功
用到工具 在服务器上开启端口监听 选中udp server,点击创建按钮 设置服务器监听端口 在客户端连接服务器端口 选中udp客户端,点击创建 输入服务器地址 远程端口和本地端口,本地端口只要没被占用都可以使用 ,点击确认 发送数据 …...
C#文件夹基本操作(判断文件夹是否存在、创建文件夹、移动文件夹、删除文件夹以及遍历文件夹中的文件)
目录 一、判断文件夹是否存在 1.Directory类的Exists()方法 2. DirectoryInfo类的Exists属性 二、创建文件夹 1. Directory类的CreateDirectory()方法 2.DirectoryInfo类的Create()方法 三、移动文件夹 1. Directory类的Move()方法 2.DirectoryInfo类的MoveT…...
python 交互模式和命令行模式的问题
python 模式的冲突 unexpected character after line continuation character 理论上 ide里,输入 python 文件路径\文件.py 就可以执行 但是有时候却报错 unexpected character after line continuation character 出现上述错误的原因是没有退出解释器&#x…...
计算机网络——数据链路层
目录 一、数据链路层的基本概念 (一)数据链路层的概念 (二)帧 (三)数据链路层分为哪两个部分 (1)LLC(逻辑控制访问) (2)MAC&…...
【限时免费】20天拿下华为OD笔试之【哈希集合】2023B-明明的随机数【欧弟算法】全网注释最详细分类最全的华为OD真题题解
文章目录 题目描述与示例题目描述输入描述输出描述:示例 1输入输出说明 解题思路代码PythonJavaC时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 题目描述与示例 题目描述 明明生成了N 个 1 至 500 之间的随机整数。请你删去其中重复的数字,即…...
播放器开发(五):视频帧处理并用SDL渲染播放
目录 学习课题:逐步构建开发播放器【QT5 FFmpeg6 SDL2】 步骤 VideoOutPut模块 1、初始化【分配缓存、读取信息】 2、开始线程工作【从队列读帧->缩放->发送渲染信号到窗口】 VideoWidget自定义Widget类 1、定义内部变量 2、如果使用SDL,需要进…...
Spring MVC数据绑定的几种方法(一)
这篇文章包含spring mvc的默认数据类型绑定和简单数据类型绑定。内容来自实验。 准备: (1)在IDEA环境中从archetye创建webapp类型的maven项目exp6。 (2)在src\main目录下创建并标注java源代码文件夹和resources资源文…...
CSP-坐标变换(其二)
问题描述 对于平面直角坐标系上的坐标 (x,y),小 P 定义了如下两种操作: 拉伸 k 倍:横坐标 x 变为 kx,纵坐标 y 变为 ky; 旋转 θ:将坐标 (x,y) 绕坐标原点 (0,0) 逆时针旋转 θ 弧度(0≤θ<…...
docker 安装jekins
echo Asia/Shanghai >/etc/timezone,容器中操作报错:docker容器中 Permission denied 使用该-u选项时,可以使用root用户(ID 0),而不是用默认用户登录docker容器 docker exec -u 0 -it f8a2b3d91455 /bin/bash 或者ÿ…...
ChatGPT 问世一周年之际,开源大模型能否迎头赶上?
就在11月30日,ChatGPT 迎来了它的问世一周年,这个来自 OpenAI 的强大AI在过去一年里取得了巨大的发展,迅速吸引各个领域的用户群体。 我们首先回忆一下 OpenAI和ChatGPT这一年的大事记(表格由ChatGPT辅助生成)&#x…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
