Qt使用sqlite数据库及项目实战
一.sqlite使用介绍
在Qt中使用SQLite数据库非常简单,SQLite是一个轻量级的嵌入式数据库,不需要单独的数据库服务器,完全使用本地文件来存储数据。
当在Qt中使用SQLite数据库时,需要涉及到一些SQL语句以及Qt中的相关函数,接下来我将从头开始介绍所有涉及的语句以及相应的解释。
1. 连接到数据库:addDatabase
在Qt中,你可以使用QSqlDatabase来连接数据库。首先需要添加数据库类型,然后指定数据库的名称:
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("mydatabase.db");
if(!db.open()) {qDebug() << "无法连接到数据库";return;
}
在这段代码中,我们首先创建了一个名为mydatabase.db的SQLite数据库,然后通过open()函数来打开数据库连接。如果连接失败,将会输出错误信息。
2. 创建表:CREATE TABLE
一般来说,你需要在数据库中创建表来存储数据。这可以通过执行CREATE TABLE语句来实现:
QSqlQuery query;
query.exec("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)");
这里我们使用exec()函数执行SQL语句,创建了一个名为users的表,包含id、name和age三个列。
3. 插入数据:INSERT
当需要在表中插入新的数据时,可以使用SQL的INSERT INTO语句。在Qt中,可以使用QSqlQuery对象的prepare()和bindValue()函数来执行预处理插入语句:
- 常规的数据库插入语句
INSERT into users(id,name,age)VALUES(111,"name",12)
- Qt中
QString name = "Alice";
int age = 25;
QSqlQuery query;
query.prepare("INSERT INTO users (name, age) VALUES (:name, :age)");
query.bindValue(":name", name);
query.bindValue(":age", age);
if(!query.exec()) {qDebug() << "插入数据失败:" << query.lastError().text();
}
- prepare和bindValue函数介绍
当在Qt中进行数据库操作时,使用query.prepare()和query.bindValue()方法可以帮助你执行预处理SQL语句并绑定参数的值。这两个方法在插入操作中起到了重要作用,下面我将详细介绍它们的功能和作用:
- query.prepare():
在Qt中,query.prepare()方法用于准备要执行的SQL语句。它的主要作用是将SQL语句中的参数部分用占位符(如:variable)代替,从而形成一个预处理的SQL语句。通过这种方式,可以避免SQL注入攻击,并提高程序的安全性。
例如,在插入操作中,你可能会使用INSERT INTO table_name (column1, column2, …) VALUES (:value1, :value2, …)这样的SQL语句,其中的:value1、:value2是占位符,用于将实际的数值动态地填充进去。使用query.prepare()方法可以将这个SQL语句准备好,等待绑定参数值。
- query.bindValue():
一旦调用了query.prepare()方法准备好了SQL语句,接下来就可以使用query.bindValue()方法为每个占位符绑定具体的数值。这个方法的作用是设置预处理语句中的占位符的值,从而将真实的数据插入到SQL语句中。
例如,在前面的插入操作示例中,我们对name和age这两个占位符使用了query.bindValue()方法,将实际的name和age变量的值绑定到了这两个占位符上。
使用query.bindValue()方法可以方便地将变量的值插入到SQL语句中,同时还可以防止数据类型转换错误和SQL注入攻击。
综上所述,query.prepare()方法用于准备预处理SQL语句,并替换其中的占位符,而query.bindValue()方法则用于将实际的数值绑定到这些占位符上,从而完成对数据库的插入操作。这两个方法的结合使用可以简化代码编写,同时提高程序的安全性和可维护性。
4. 查询数据:SELECT
查询数据最常见的方式是使用SELECT语句。在Qt中,我们可以通过exec()函数执行SELECT语句,并使用next()函数来逐行获取结果:
QSqlQuery query;
query.exec("SELECT * FROM users");
while(query.next()) {int id = query.value(0).toInt();QString name = query.value(1).toString();int age = query.value(2).toInt();qDebug() << "ID:" << id << " Name:" << name << " Age:" << age;
}
这段代码遍历了users表中的所有行,并输出每一行的ID、名称和年龄。
- query.next介绍
在Qt中,query.next()方法用于遍历查询结果集中的下一行数据。当执行SELECT查询语句并通过exec()方法获取结果集后,可以使用query.next()方法逐行访问查询结果中的数据。
每次调用query.next()方法,会将查询结果集中的指针移到下一行数据。如果存在下一行数据,则该方法返回true,并允许获取下一行数据;如果不存在下一行数据,则返回false,表示已经遍历完所有结果。
一般来说,可以在一个循环中使用query.next()方法来遍历整个查询结果集,逐行获取数据并进行相应的处理。在循环中,通常会结合query.value()方法用于获取特定列的值。
5. 更新数据:UPDATE
在 Qt 中使用 SQLite 实现更新(修改)数据库操作可以通过执行 SQL UPDATE 语句来实现。下面是一个简单的示例代码,演示了如何使用 Qt 和 SQLite 执行更新操作:
#include <QCoreApplication>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);// 连接到SQLite数据库QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName("database.db"); // 指定SQLite数据库文件if (!db.open()) {qDebug() << "Error: Unable to connect to database.";return 1;}// 执行 UPDATE 操作QSqlQuery query;query.prepare("UPDATE student SET name = :newName WHERE id = :id");query.bindValue(":newName", "New Name"); // 设置要更新的新名称query.bindValue(":id", 1); // 设置要更新的记录的 IDif (query.exec()) {qDebug() << "Update successful";} else {qDebug() << "Update failed:" << query.lastError().text();}return app.exec();
}
6. 删除数据:DELETE
使用 QSqlQuery 类删除数据:
QSqlQuery query;
query.prepare("DELETE FROM your_table WHERE condition = :condition"); // 设置删除语句
query.bindValue(":condition", value); // 绑定条件值
bool success = query.exec(); // 执行删除操作
if(success) {// 删除成功
} else {// 删除失败,处理错误qDebug() << "Error:" << query.lastError().text();
}
7. 更新数据库中的数据:submitAll
- 这是对模型进行了修改,将数据提交回数据库中,以保持同步。
// 创建 QSqlTableModel 并设置数据库表QSqlTableModel model;model.setTable("student");model.select(); // 从数据库中选择数据// 创建 QTableView 并设置模型QTableView tableView;tableView.setModel(&model);// 创建一个按钮,当点击时提交更新QPushButton updateButton("Update Database");QObject::connect(&updateButton, &QPushButton::clicked, [&model](){if (model.submitAll()) {qDebug() << "Database update successful";} else {qDebug() << "Database update failed:" << model.lastError().text();}});
- model.submitAll介绍
QSqlTableModel 中的 submitAll() 函数是用于将对模型数据的更改提交到数据库中的方法。当您在 QTableView 中对数据进行了修改、插入或删除等操作后,调用 submitAll() 函数可将这些更改应用到数据库中。
submitAll() 函数会执行以下操作:
- 检查模型中的每一行,如果该行的状态为 Inserted、Deleted 或 Modified,则将对应的更改提交到数据库中。
- 如果提交成功,会返回 true;如果提交失败,会返回 false。您可以通过检查返回值来确定提交是否成功。
- 如果提交失败,您可以调用 model.lastError().text() 来获取详细的错误信息。这将返回一个描述在提交过程中发生的错误的字符串。
在模型视图的结构中,对model是临时修改数据的中转站。
8. 更新QSqlQueryModel中的数据
QSqlQueryModel 是一个只读模型,无法直接编辑数据,因此更新数据的方式不同于可编辑的模型,比如 QSqlTableModel。如果您想要更新 QSqlQueryModel 中的数据,可以重新执行查询语句或者重新设置查询。
以下是更新 QSqlQueryModel 中数据的一种常见方法:
- 重新执行查询语句:您可以重新设置 QSqlQueryModel 的查询语句,然后调用 setQuery() 方法重新执行查询。这将重新从数据库中读取数据并更新模型中的数据。
QSqlQueryModel model;
model.setQuery("SELECT * FROM your_table");
- 使用 clear() 方法清空数据:如果需要清空 QSqlQueryModel 中的数据,您可以调用 clear() 方法。清空数据后,您可以重新设置查询或数据源,从而实现更新。
model.clear();
需要注意的是,QSqlQueryModel 是一个只读模型,不支持直接编辑数据,如果您需要在界面上进行编辑和更新操作,可以考虑使用 QSqlTableModel 或自定义的 QAbstractTableModel。
9. 对指定列进行排序
- 这是对模型进行排序
// 创建 QSqlQueryModel 并设置查询语句
QSqlQueryModel *queryModel = new QSqlQueryModel;
queryModel->setQuery("SELECT * FROM your_table");// 创建 QSortFilterProxyModel 并设置源模型为 QSqlQueryModel
QSortFilterProxyModel *sortModel = new QSortFilterProxyModel(this);
sortModel->setSourceModel(queryModel);// 设置排序的列索引
int sortColumn = 1; // 假设要按第1列排序
sortModel->sort(sortColumn, Qt::AscendingOrder); // 进行升序排序// 将排序后的模型设置给视图
yourTableView->setModel(sortModel);
- 对数据库进行排序
-- 以id列的升序方式进行排序
SELECT id, name, age
FROM your_table
ORDER BY id ASC;SELECT id ,name ,score FROM student ORDER BY id DESC//对模型中的数据进行排序
model->setQuery("SELECT id, name, score FROM student ORDER BY id DESC");
二.成绩管理系统实战
1. 项目效果
- 项目说明:底层存储数据用的是sqlite,界面展示数据用的是tableView和QSqlQueryModel的视图模型模式。
2. 项目源码:
- 类定义
#ifndef STUDENTDLG_H
#define STUDENTDLG_H#include <QDialog>#include <QSqlDatabase> // 专用于连接、创建数据库
#include <QSqlQuery> // 专用于DML(数据操纵语言)、DDL(数据定义语言)
#include <QSqlQueryModel>//数据库模型,用来和tableview关联
#include <QSqlError>
#include <QDebug>
#include <QMessageBox>QT_BEGIN_NAMESPACE
namespace Ui { class StudentDlg; }
QT_END_NAMESPACEclass StudentDlg : public QDialog
{Q_OBJECTpublic:StudentDlg(QWidget *parent = nullptr);~StudentDlg();private slots:void on_pushButtonSort_clicked();void on_pushButton_INSERT_clicked();void on_pushButton_DELETE_clicked();void on_pushButton_UPDATE_clicked();void on_pushButton_SEARCH_clicked();
private: void CreateDatabaseFunc(); // 创建SQLite数据库void CreateTableFunc(); // 创建SQLite数据表void QueryTableFunc(); // 执行查询操作QSqlDatabase sqldb; // 创建Qt和数据库链接QSqlQueryModel *model=nullptr;//用来存储数据
private:Ui::StudentDlg *ui;};
#endif // STUDENTDLG_H
- 类实现
#include "studentdlg.h"
#include "ui_studentdlg.h"
#include<QSortFilterProxyModel>StudentDlg::StudentDlg(QWidget *parent): QDialog(parent), ui(new Ui::StudentDlg)
{ui->setupUi(this);// 调用函数创建且打开数据库CreateDatabaseFunc();// 调用函数创建数据表CreateTableFunc();
}StudentDlg::~StudentDlg()
{delete ui;
}void StudentDlg::CreateDatabaseFunc() // 创建SQLite数据库
{// 1:添加数据库驱动sqldb=QSqlDatabase::addDatabase("QSQLITE");// 2:设置数据库名称sqldb.setDatabaseName("studentmis.db");// 3:打开此数据库是否成功if(sqldb.open()==true){QMessageBox::information(0,"正确","恭喜你,数据库打开成功!",QMessageBox::Ok);}else{QMessageBox::critical(0,"错误","数据库打开失败,请重新检测!",QMessageBox::Ok);}
}void StudentDlg::CreateTableFunc() // 创建SQLite数据表
{QSqlQuery createquery;// 创建SQL语句QString strsql=QString("CREATE TABLE IF NOT EXISTS student(""id int primary key not null,""name text not null,""score real not null)");// 执行SQL语句if(createquery.exec(strsql)==false){QMessageBox::critical(0,"失败","数据表创建失败,请重新检查!",QMessageBox::Ok);}else{QMessageBox::information(0,"成功","恭喜你,数据表创建成功!",QMessageBox::Ok);}// 准备数据模型model = new QSqlQueryModel();model->setQuery("SELECT id, name, score FROM student"); // 执行查询// 将数据模型与QTableView绑定//QTableView *tableView = new QTableView();ui-> tableView->setModel(model);ui->tableView->resizeColumnsToContents(); // 调整列宽度使数据能够完全显示// 显示QTableViewui->tableView->show();}
void StudentDlg::QueryTableFunc() // 执行查询操作
{QSqlQuery query;query.exec("SELECT * FROM users");while(query.next()) {int id = query.value(0).toInt();QString name = query.value(1).toString();double score = query.value(2).toDouble();qDebug() << "ID:" << id << " Name:" << name << " Score:" << score;}}void StudentDlg::on_pushButtonSort_clicked()
{// QSortFilterProxyModel *sortModel = new QSortFilterProxyModel(this);
// sortModel->setSourceModel(model);// // 设置排序的列索引
// int sortColumn = 1; // 假设要按第1列排序
// sortModel->sort(sortColumn, Qt::DescendingOrder); // 进行升序排序// // 将排序后的模型设置给视图
// ui->tableView->setModel(sortModel);// //使用sql语句进行操作
// QSqlQuery query;
// query.exec("SELECT id ,name ,score FROM student ORDER BY id DESC");//更新数据库中的数据model->setQuery("SELECT id, name, score FROM student ORDER BY id DESC");//model->setQuery("SELECT * FROM student");ui->tableView->viewport()->update();
}void StudentDlg::on_pushButton_INSERT_clicked()
{QSqlQuery sqlquery;int id=ui->lineEdit_ID->text().toInt();if(id==0){QMessageBox::critical(this,"失败","提示:输入错误?学号不能为0?",QMessageBox::Ok);return ;}QString name=ui->lineEdit_NAME->text();if(name==""){QMessageBox::critical(this,"失败","提示:输入错误?姓名不能为空?",QMessageBox::Ok);return ;}double score=ui->lineEdit_SCORE->text().toDouble();if(score<0 || score>100){QMessageBox::critical(this,"失败","提示:输入错误?分数范围(0-100)?",QMessageBox::Ok);return ;}QString strs=QString("insert into student ""values(%1,'%2',%3)").arg(id).arg(name).arg(score);if(sqlquery.exec(strs)==false){QMessageBox::critical(0,"失败","向数据表插入记录失败,请重新检查!",QMessageBox::Ok);}else{QMessageBox::information(0,"成功","恭喜你,向数据表插入记录成功!",QMessageBox::Ok);}}void StudentDlg::on_pushButton_DELETE_clicked()
{int id = ui->lineEdit_ID->text().toInt();QSqlQuery query;query.prepare("DELETE FROM student WHERE id = :id"); // 设置删除语句query.bindValue(":id", id); // 绑定条件值bool success = query.exec(); // 执行删除操作if(success) {// 删除成功} else {// 删除失败,处理错误qDebug() << "Error:" << query.lastError().text();}//更新数据库中的数据model->setQuery("SELECT * FROM student");ui->tableView->viewport()->update();
}void StudentDlg::on_pushButton_UPDATE_clicked()
{// 执行 UPDATE 操作QString New_Name=ui->lineEdit_NAME->text();int id=ui->lineEdit_ID->text().toUInt();QSqlQuery query;query.prepare("UPDATE student SET name = :newName WHERE id = :id");query.bindValue(":newName", New_Name); // 设置要更新的新名称query.bindValue(":id", id); // 设置要更新的记录的 IDif (query.exec()) {qDebug() << "Update successful";} else {qDebug() << "Update failed:" << query.lastError().text();}}void StudentDlg::on_pushButton_SEARCH_clicked()
{QSqlQuery query;query.exec("SELECT * FROM student");while(query.next()) {int id = query.value(0).toInt();QString name = query.value(1).toString();double score = query.value(2).toDouble();qDebug() << "ID:" << id << " Name:" << name << " Score:" << score;}//更新数据库中的数据model->setQuery("SELECT * FROM student");ui->tableView->viewport()->update();
}
相关文章:

Qt使用sqlite数据库及项目实战
一.sqlite使用介绍 在Qt中使用SQLite数据库非常简单,SQLite是一个轻量级的嵌入式数据库,不需要单独的数据库服务器,完全使用本地文件来存储数据。 当在Qt中使用SQLite数据库时,需要涉及到一些SQL语句以及Qt中的相关函数…...

开源模型应用落地-FastAPI-助力模型交互-进阶篇(一)
一、前言 FastAPI 的高级用法可以为开发人员带来许多好处。它能帮助实现更复杂的路由逻辑和参数处理,使应用程序能够处理各种不同的请求场景,提高应用程序的灵活性和可扩展性。 在数据验证和转换方面,高级用法提供了更精细和准确的控制&#…...
精准选择广告工具,提升推广效果
在考虑使用巨量引擎之前,我们首先要明白它的本质。巨量引擎是一个付费广告平台,包含了多种推广工具,如巨量ID、巨量千川、巨量本地推,以及企业蓝V等。很多人希望通过这个平台提升抖音账号的流量和曝光度,但真正有效的流…...
Swagger的原理及应用详解(六)
本系列文章简介: 在当今快速发展的软件开发领域,特别是随着微服务架构和前后端分离开发模式的普及,API(Application Programming Interface,应用程序编程接口)的设计与管理变得愈发重要。一个清晰、准确且易于理解的API文档不仅能够提升开发效率,还能促进前后端开发者之…...

世界人工智能大会今日开幕:人工智能如何成为引领发展的新引擎
人工智能如何成为引领上海发展的新引擎?今日(7月4日)开幕的2024世界人工智能大会暨人工智能全球治理高级别会议(简称“WAIC 2024”)将带来答案。 “新”和“全”是今年大会的亮点所在:“新”在于技术新&…...

tinyshop项目部署
参考软件测试之测试用例设计(四)_管理后台 测试用例-CSDN博客 1、下载xampp 2、修改apache和mysql的端口分别为4431 ,8013和3306 3、访问页面:输入ip:端口号,出现以下页面即成功 4、安装tinyshop商城 将解压的tinys…...

Gemini for China 大更新,现已上架 Android APP!
官网:https://gemini.fostmar.online/ Android APP:https://gemini.fostmar.online/gemini_1.0.apk 一、Android APP 如果是 Android 设备,则会直接识别到并给下载链接。PC 直接对话即可。 二、聊天记录 现在 Gemini for Chinaÿ…...
Unity渲染管线介绍
Unity中的渲染管线渲染场景主要分为三个阶段 剔除(Culling) 剔除摄像机不可见对象(视锥体剔除Frustum Culling)和被遮挡对象(遮挡剔除Occlusion Culling)。 渲染(Rendering) 将可见…...

【UML用户指南】-31-对体系结构建模-制品图
目录 1、对源代码建模 2、对可执行程序的发布建模 3、对物理数据库建模 4、对可适应系统建模 制品图是对面向对象系统的物理方面进行建模时要用到的两种图之一。制品图展示一组制品之间的组织以及其间依赖关系。 利用制品图可以对系统的静态实现视图建模。这包括对存在于结…...

《基于 Kafka + Flink + ES 实现危急值处理措施推荐和范围校准》
📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 近期刚转战 CSDN,会严格把控文章质量,绝不滥竽充数,欢迎多多交流。&am…...

计算机的进制转换
十进制:以0-9这九个数字组成。 二进制:由0和1两个数字组成。 八进制:由0-7数字组成,不存在8和9。 十六进制:由0-9和A-F组成。A-F对应的是10-15。 ____________ 十进制 1 2 3 4 5 6 7 8 9 10 二进制 0 1 10 11 1…...

String类(STL开始)
相信大家都知道STL在C中的重要性,作为其模板库中的一部分,包含了常见的数据结构和算法,是C的标准库 而我们今天要讲的String类(String底层是一个字符顺序数组的顺序表对象,可以归类为容器),其实…...

【数据结构】单链表:数据结构中的舞者,穿梭于理论与实践的舞池
欢迎来到白刘的领域 Miracle_86.-CSDN博客 系列专栏 数据结构与算法 先赞后看,已成习惯 创作不易,多多支持! 一、链表的概念和结构 1.1 链表的概念 在上一篇文章中,我们了解了线性表(linear list),并且学习了其…...

html三级菜单
示例 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>Menu Example</title> <link re…...

【人工智能】—基于成都市各区(市)县租房价格预测建模研究
引言 随着城市化进程的加速,人口流动日益频繁,租房市场作为城市生活的重要组成部分,其价格波动对居民生活质量和城市经济发展具有显著影响。成都市,作为中国西部地区的经济、文化、交通和科技中心,近年来吸引了大量人…...
3213. 最小代价构造字符串
Powered by:NEFU AB-IN Link 文章目录 3213. 最小代价构造字符串题意思路代码 3213. 最小代价构造字符串 题意 给你一个字符串 target、一个字符串数组 words 以及一个整数数组 costs,这两个数组长度相同。 设想一个空字符串 s。 你可以执行以下操作任意次数&a…...

提取重复数据
直接上控制台代码: Module Module1Sub Main()Console.WriteLine("请输入数据,以"",""相隔:")Dim str As String Console.ReadLineDim result From x In str.Split(",")Group By x Int…...
Go语言标准库之log和三方库zap
一、Log 1.1 logger基本使用 Go语言内置的log包实现了简单的日志服务。本包也提供了一个预定义的“标准”logger,可以通过调用函数Print系列(Print|Printf|Println)、Fatal系列(Fatal|Fatalf|Fatalln)、和Panic系列(Panic|Panicf|Panicln)来…...

Linux:进程终止和进程替换
Linux:Linux:进程终止和进程替换 一、进程终止1.1 进程退出场景和创建退出方式 1.2 exit 和 _exit区别二、进程程序替换2.1 进程替换函数2.2 函数解释及命名解释函数解释命名解释 2.3 单进程程序替换(无子进程)2.3.1 带l函数进程替…...
使用Java实现异步消息处理与队列消费
使用Java实现异步消息处理与队列消费 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 在现代软件系统中,处理异步消息和队列消费是常见的需求。通过…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...