C/C++ 通过SQLiteSDK增删改查

SQLite,作为一款嵌入式关系型数据库管理系统,一直以其轻量级、零配置以及跨平台等特性而备受青睐。不同于传统的数据库系统,SQLite是一个库,直接与应用程序一同编译和链接,无需单独的数据库服务器进程,实现了数据库的零配置管理。这种设计理念使得SQLite成为许多嵌入式系统、移动应用和小型项目中的首选数据库引擎。

SQLite的特点包括:

  1. 嵌入式数据库引擎: SQLite 是一个嵌入式数据库引擎,意味着它是一个库,与应用程序一同编译和链接,而不是作为独立的进程运行。
  2. 零配置: 无需配置或管理。SQLite 不需要一个独立的数据库服务器进程,所有的操作都是直接在存储在文件中的数据库上执行。
  3. 轻量级: SQLite 是一个轻量级的数据库,相对于一些其他数据库管理系统来说,它的内存占用和资源消耗相对较小。
  4. 支持 SQL: SQLite 支持大部分标准的 SQL 语法,并提供了事务支持,包括隔离级别和回滚。
  5. 跨平台: SQLite 可以在各种操作系统上运行,包括 Windows、Linux、macOS 和其他嵌入式系统。
  6. 自给自足: SQLite 数据库是一个单一的磁盘文件,整个数据库被存储在一个文件中,这使得备份、复制或传输数据库变得非常容易。
  7. 开源: SQLite 是一个开源项目,采用公共领域授权(Public Domain License),可以在商业和非商业项目中免费使用。

SQLite 数据库以其独特的自给自足特性脱颖而出,整个数据库被存储在一个单一的磁盘文件中,使得备份、复制或传输数据库变得异常简单。而作为一款开源项目,SQLite采用了公共领域授权,可以在商业和非商业项目中免费使用。

  • SQLiteSDK下载:https://download.csdn.net/download/lyshark_csdn/88568197

由于该数据库的小巧和简洁所以在使用上也非常容易,当读者下载好附件以后会看到如下图所示的文件;

使用时只需要将sqlite3.hsqlite3.c文件导入到项目中并使用#include "sqlite3.h"即可,无需做其他配置,图中的sqlite3.dll是动态库,sqlite3.exe则是一个命令行版本的数据库可在测试时使用它。

打开与关闭库

sqlite3_open 用于打开或创建一个 SQLite 数据库文件。该函数的原型如下:

int sqlite3_open(const char *filename,   /* Database filename (UTF-8) */sqlite3 **ppDb          /* OUT: SQLite db handle */
);
  • filename: 要打开或创建的 SQLite 数据库文件的路径。如果文件不存在,将会创建一个新的数据库文件。
  • ppDb: 用于存储 SQLite 数据库句柄(handle)的指针。SQLite 数据库句柄是与一个打开的数据库关联的结构,它在后续的 SQLite 操作中用作标识。

该函数返回一个整数值,代表函数的执行状态。如果函数成功执行,返回 SQLITE_OK。如果有错误发生,返回一个表示错误代码的整数值。可以通过 sqlite3_errmsg 函数获取更详细的错误信息。

sqlite3_close 用于关闭数据库连接的函数。其原型如下:

int sqlite3_close(sqlite3*);
  • sqlite3: 要关闭的 SQLite 数据库连接的句柄。

该函数返回一个整数值,用于表示函数的执行状态。如果函数成功执行,返回 SQLITE_OK。如果有错误发生,返回一个表示错误代码的整数值。

使用 sqlite3_close 函数可以释放与数据库连接相关的资源,并确保数据库文件被正确关闭。在关闭数据库连接之前,应该确保已经完成了所有需要执行的 SQL 语句,并在需要的情况下检查执行结果。

// 打开数据库并返回句柄
sqlite3* open_database(std::string database_name)
{int ref =-1;sqlite3 *db = 0;ref = sqlite3_open(database_name.c_str(), &db);if (ref == SQLITE_OK)return db;return false;
}// 关闭数据库
bool close_database(sqlite3 *db)
{int ref = sqlite3_close(db);if (ref == SQLITE_OK)return true;return false;
}

执行查询语句

sqlite3_exec 用于执行 SQL 语句的高级接口函数。它的原型如下:

int sqlite3_exec(sqlite3* db,                    /* Database handle */const char* sql,                /* SQL statement, UTF-8 encoded */int (*callback)(                /* Callback function */void*,                        /* Callback parameter */int,                          /* Number of columns in the result set */char**,                       /* Array of column values */char**                        /* Array of column names */),void* callback_param,           /* 1st argument to callback function */char** errmsg                   /* Error msg written here */
);
  • db: SQLite 数据库连接的句柄。
  • sql: 要执行的 SQL 语句,以 UTF-8 编码。
  • callback: 回调函数,用于处理查询结果的每一行数据。
  • callback_param: 传递给回调函数的参数。
  • errmsg: 用于存储错误消息的指针。

sqlite3_exec 函数执行一个或多个 SQL 语句,并对每一条语句的执行结果调用指定的回调函数。回调函数的原型如下:

int callback(void* callback_param, /* 参数,由 sqlite3_exec 传递给回调函数 */int num_columns,      /* 结果集中的列数 */char** column_values,  /* 指向结果集中当前行的列值的数组 */char** column_names    /* 指向结果集中列名的数组 */
);
  • callback_param: 回调函数的参数,由 sqlite3_exec 传递给回调函数。
  • num_columns: 结果集中的列数。
  • column_values: 指向结果集中当前行的列值的数组。
  • column_names: 指向结果集中列名的数组。

回调函数返回一个整数,用于指示是否继续执行后续的 SQL 语句。如果回调函数返回非零值,sqlite3_exec 将停止执行 SQL,并立即返回。

sqlite3_prepare_v2 用于准备 SQL 语句的接口函数。它的原型如下:

int sqlite3_prepare_v2(sqlite3* db,            /* Database handle */const char* sql,        /* SQL statement, UTF-8 encoded */int sql_len,            /* Length of SQL statement in bytes, or -1 for zero-terminated */sqlite3_stmt** stmt,    /* OUT: Statement handle */const char** tail       /* OUT: Pointer to unused portion of SQL statement */
);
  • db: SQLite 数据库连接的句柄。
  • sql: 要准备的 SQL 语句,以 UTF-8 编码。
  • sql_len: SQL 语句的长度,如果为 -1,则表示 SQL 语句以 null 结尾。
  • stmt: 用于存储准备好的语句句柄的指针。
  • tail: 用于存储未使用的 SQL 语句的指针。

sqlite3_prepare_v2 函数用于将 SQL 语句编译成一个 SQLite 语句对象(prepared statement)。这个对象可以被多次执行,每次执行时可以绑定不同的参数。stmt 参数将用于存储编译后的语句的句柄,以供后续的操作。

sqlite3_step 执行预编译 SQL 语句的接口函数。它的原型如下:

int sqlite3_step(sqlite3_stmt*);
  • sqlite3_stmt*: 由 sqlite3_prepare_v2 预编译的 SQL 语句的句柄。

sqlite3_step 函数用于执行由 sqlite3_prepare_v2 预编译的 SQL 语句。在执行过程中,可以通过不断调用 sqlite3_step 来逐行获取查询结果,直到结果集结束。对于非查询语句(如 INSERTUPDATEDELETE),sqlite3_step 函数执行一次即可完成操作。

该函数的返回值表示执行的结果,可能的返回值包括:

  • SQLITE_ROW: 成功获取一行数据。
  • SQLITE_DONE: 执行完成,没有更多的数据可用(用于非查询语句)。
  • 其他错误码,表示执行过程中出现了错误。

sqlite3_column_text 用于获取查询结果集中某一列的文本值。其原型为:

const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
  • sqlite3_stmt*: 由 sqlite3_prepare_v2 预编译的 SQL 语句的句柄。
  • int iCol: 列的索引,从0开始。

该函数返回指向字符串值的指针,该字符串值是查询结果集中指定列的文本表示。需要注意的是,返回的指针指向 SQLite 内部的存储区,应该在使用完之后尽早释放资源。

sqlite3_column_int 用于获取查询结果集中某一列的整数值。其原型为:

int sqlite3_column_int(sqlite3_stmt*, int iCol);
  • sqlite3_stmt*: 由 sqlite3_prepare_v2 预编译的 SQL 语句的句柄。
  • int iCol: 列的索引,从0开始。

该函数返回查询结果集中指定列的整数表示。需要注意的是,如果该列不是整数类型,或者包含的数据无法转换为整数,那么返回的结果可能不是有效的整数值。

sqlite3_finalize 用于释放一个预备语句对象(prepared statement)。在使用 sqlite3_prepare_v2 函数准备 SQL 语句后,需要使用 sqlite3_finalize 来释放相应的语句对象。

该函数的原型为:

int sqlite3_finalize(sqlite3_stmt *pStmt);
  • sqlite3_stmt *pStmt: 指向要释放的语句对象的指针。

该函数返回 SQLITE_OK 表示成功,返回其他错误码表示失败。

// 执行SQL语句
bool exec_sql(sqlite3 *db, char *sql)
{char *error_code = 0;int ref = sqlite3_exec(db, sql, 0, 0, &error_code);if (ref == SQLITE_OK){return true;}return false;
}// 插入数据
bool insert_data(sqlite3 *db, char *sql)
{sqlite3_stmt *stmt = 0;// 插入前检查语句合法性, -1自动计算SQL长度int ref = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);if (ref == SQLITE_OK){sqlite3_step(stmt);       // 执行语句sqlite3_finalize(stmt);   // 清理语句句柄return true;}sqlite3_finalize(stmt);return false;
}// 查询数据集
bool select_data(sqlite3 *db, char *sql)
{sqlite3_stmt *stmt = 0;int ref = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);if (ref == SQLITE_OK){// 每调一次sqlite3_step()函数,stmt就会指向下一条记录while (sqlite3_step(stmt) == SQLITE_ROW){// 取出第1列字段的值const unsigned char *name = sqlite3_column_text(stmt, 1);// 取出第2列字段的值int age = sqlite3_column_int(stmt, 2);std::cout << "姓名: " << name << " 年龄: " << age << std::endl;}}else{sqlite3_finalize(stmt);return false;}sqlite3_finalize(stmt);return true;
}

调用查询语句

创建数据库

首先打开了名为 "database.db" 的 SQLite 数据库,并创建了一个名为 "LySharkDB" 的表,该表格包含了id、name、agemsg四个字段。随后,通过执行 SQL 语句创建了这个表格。最后,关闭了数据库连接。这段代码主要用于数据库初始化操作,确保了数据库中包含了指定的表格结构。

int main(int argc, char *argv[])
{sqlite3* open_db = open_database("database.db");if (open_db != false){bool create_table_ref;std::string sql = "create table LySharkDB(""id int auto_increment primary key,""name char(30) not null," "age int not null,""msg text default null"")";// 运行创建表操作char run_sql[1024] = { 0 };strcpy(run_sql, sql.c_str());create_table_ref = exec_sql(open_db, run_sql);}close_database(open_db);std::system("pause");return 0;
}

上述代码运行后则可以创建一个数据库database.db表名为LySharkDB读者可以使用数据库工具打开该表,其结构如下所示;

插入数据测试

创建数据库后,接着就是插入数据测试,插入时可以使用insert_data,如下代码项数据库中插入5条记录;

int main(int argc, char *argv[])
{sqlite3* open_db = open_database("./database.db");if (open_db != false){bool create_table_ref;// 运行插入记录if (create_table_ref == true){bool insert_ref = 0;insert_ref = insert_data(open_db, "insert into LySharkDB(id,name,age,msg) values(1,'lyshark',1,'hello lyshark');");insert_ref = insert_data(open_db, "insert into LySharkDB(id,name,age,msg) values(2,'guest',2,'hello guest');");insert_ref = insert_data(open_db, "insert into LySharkDB(id,name,age,msg) values(3,'admin',3,'hello admin');");insert_ref = insert_data(open_db, "insert into LySharkDB(id,name,age,msg) values(4,'wang',4,'hello wang');");insert_ref = insert_data(open_db, "insert into LySharkDB(id,name,age,msg) values(5,'sqlite',5,'hello sql');");if (insert_ref == true){std::cout << "插入完成" << std::endl;}}}close_database(open_db);std::system("pause");return 0;
}

插入后,打开数据库管理软件,可看到插入后的记录;

查询与删除数据

而查询删除与增加记录,我们这里直接使用exec_sql()函数,通过传入不同的SQL语句实现。

int main(int argc, char *argv[])
{sqlite3* open_db = open_database("./database.db");if (open_db != false){// 删除记录bool delete_ref = exec_sql(open_db, "delete from LySharkDB where id = 5;");if (delete_ref == true){std::cout << "删除完成." << std::endl;}// 更新记录bool update_ref = exec_sql(open_db, "update LySharkDB set name='lyshark' where id = 4;");if (update_ref == true){std::cout << "更新完成." << std::endl;}// 查询数据bool select_ref = select_data(open_db, "select * from LySharkDB;");if (select_ref == true){std::cout << "查询完毕." << std::endl;}}close_database(open_db);std::system("pause");return 0;
}

执行更新后的表记录如下所示;

查询区间数据

首先创建一些数据集,这里通过循环生成并插入数据,如下代码中新建一个TimeDB数据表,其中有三个字段uid,host_time,cpu_value

#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <time.h>
#include "sqlite3.h"#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>using namespace std;
using namespace boost;// 获取本地时间日期
std::string get_local_datetime()
{char ct[80];time_t  tt;struct tm *tblock;tt = time(NULL);tblock = localtime(&tt);strftime(ct, sizeof(ct), "%Y-%m-%d %H:%M:%S", tblock);return ct;
}// 初始化创建表结构
void Init_Database()
{sqlite3* open_db = open_database("./database.db");if (open_db != false){bool create_table_ref;std::string sql ="create table TimeDB(""uid primary key,""host_time char(128) not null,""cpu_value int not null"");";char run_sql[1024] = { 0 };strcpy(run_sql, sql.c_str());exec_sql(open_db, run_sql);}close_database(open_db);
}// 批量生成时间字符串并插入数据表
void Insert_Test()
{sqlite3* open_db = open_database("./database.db");for (int x = 0; x < 1000; x++){// 获取本地日期时间std::string local_times = get_local_datetime();std::string format_string = boost::str(boost::format("insert into TimeDB(uid,host_time,cpu_value) values(%d,'%s',%d);") % x %local_times %x);std::cout << "执行SQL: " << format_string << std::endl;char run_sql[1024] = { 0 };strcpy(run_sql, format_string.c_str());insert_data(open_db, run_sql);_sleep(1000);}close_database(open_db);
}int main(int argc, char *argv[])
{sqlite3* open_db = open_database("./database.db");Init_Database();Insert_Test();std::system("pause");return 0;
}

如下是五分钟的模拟数据;

当有了数据则再查询,代码中Select_Time_List函数演示了如何通过时间查询一个区间的数据,并返回一个容器列表给被调用者使用,查询代码如下所示;

#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <time.h>
#include "sqlite3.h"#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>using namespace std;
using namespace boost;// 打开数据库并返回句柄
sqlite3* open_database(std::string database_name)
{int ref = -1;sqlite3 *db = 0;ref = sqlite3_open(database_name.c_str(), &db);if (ref == SQLITE_OK)return db;return false;
}// 关闭数据库
bool close_database(sqlite3 *db)
{int ref = sqlite3_close(db);if (ref == SQLITE_OK)return true;return false;
}// 执行SQL语句
bool exec_sql(sqlite3 *db, char *sql)
{char *error_code = 0;int ref = sqlite3_exec(db, sql, 0, 0, &error_code);if (ref == SQLITE_OK){return true;}return false;
}// 插入数据
bool insert_data(sqlite3 *db, char *sql)
{sqlite3_stmt *stmt = 0;// 插入前检查语句合法性, -1自动计算SQL长度int ref = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);if (ref == SQLITE_OK){sqlite3_step(stmt);       // 执行语句sqlite3_finalize(stmt);   // 清理语句句柄return true;}sqlite3_finalize(stmt);return false;
}// 查询数据集
bool select_data(sqlite3 *db, char *sql)
{sqlite3_stmt *stmt = 0;int ref = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);if (ref == SQLITE_OK){// 每调一次sqlite3_step()函数,stmt就会指向下一条记录while (sqlite3_step(stmt) == SQLITE_ROW){// 取出第1列字段的值const unsigned char *name = sqlite3_column_text(stmt, 1);// 取出第2列字段的值int age = sqlite3_column_int(stmt, 2);std::cout << "姓名: " << name << " 年龄: " << age << std::endl;}}else{sqlite3_finalize(stmt);return false;}sqlite3_finalize(stmt);return true;
}// 获取本地时间日期
std::string get_local_datetime()
{char ct[80];time_t  tt;struct tm *tblock;tt = time(NULL);tblock = localtime(&tt);strftime(ct, sizeof(ct), "%Y-%m-%d %H:%M:%S", tblock);return ct;
}// 初始化创建表结构
void Init_Database()
{sqlite3* open_db = open_database("./database.db");if (open_db != false){bool create_table_ref;std::string sql ="create table TimeDB(""uid primary key,""host_time char(128) not null,""cpu_value int not null"");";char run_sql[1024] = { 0 };strcpy(run_sql, sql.c_str());exec_sql(open_db, run_sql);}close_database(open_db);
}// 批量生成时间字符串并插入数据表
void Insert_Test()
{sqlite3* open_db = open_database("./database.db");for (int x = 0; x < 1000; x++){// 获取本地日期时间std::string local_times = get_local_datetime();std::string format_string = boost::str(boost::format("insert into TimeDB(uid,host_time,cpu_value) values(%d,'%s',%d);") % x %local_times %x);std::cout << "执行SQL: " << format_string << std::endl;char run_sql[1024] = { 0 };strcpy(run_sql, format_string.c_str());insert_data(open_db, run_sql);_sleep(1000);}close_database(open_db);
}// 查询时间区间并返回 传入开始时间与结束时间,过滤出特定的记录
bool Select_Time_List(sqlite3 *db, std::vector<std::map<std::string, int>> &time_ref, std::string start_time, std::string end_time)
{sqlite3_stmt *stmt = 0;std::string format_string = boost::str(boost::format("select * from TimeDB where host_time >= '%s' and host_time <= '%s';") % start_time %end_time);char run_sql[1024] = { 0 };strcpy(run_sql, format_string.c_str());int ref = sqlite3_prepare_v2(db, run_sql, -1, &stmt, 0);if (ref == SQLITE_OK){while (sqlite3_step(stmt) == SQLITE_ROW){std::map < std::string, int > ptr;// 取出第一个和第二个字段const unsigned char *time_text = sqlite3_column_text(stmt, 1);const int cpu_value = sqlite3_column_int(stmt, 2);// 放入一个map容器中ptr[boost::lexical_cast<std::string>(time_text)] = cpu_value;time_ref.push_back(ptr);}sqlite3_finalize(stmt);return true;}sqlite3_finalize(stmt);return false;
}int main(int argc, char *argv[])
{sqlite3* open_db = open_database("./database.db");//Init_Database();//Insert_Test();// 查询 2023-11-25 19:52:31 - 2023-11-25 19:53:35 区间内的所有的负载情况std::vector<std::map<std::string, int>> db_time;bool is_true = Select_Time_List(open_db, db_time, "2023-11-25 19:52:31", "2023-11-25 19:53:35");if (is_true == true){for (int x = 0; x < db_time.size(); x++){// 输出该区间内的数据std::map < std::string, int>::iterator ptr;for (ptr = db_time[x].begin(); ptr != db_time[x].end(); ptr++){std::cout << "时间区间: " << ptr->first << " CPU利用率: " << ptr->second << std::endl;}}}std::system("pause");return 0;
}

例如代码中我们查询2023-11-25 19:52:31 - 2023-11-25 19:53:35这个区间内的数据信息,并返回一个map容器给被调用者,运行效果如下所示;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/169751.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣114. 二叉树展开为链表(java,用树模拟链表)

Problem: 114. 二叉树展开为链表 文章目录 题目描述思路解题方法复杂度Code 题目描述 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 1.展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左…

leetcode刷题详解二

160. 相交链表 本质上是走过自己的路&#xff0c;再走过对方的路&#xff0c;这是求两个链表相交的方法 ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {//本质上是走过自己的路&#xff0c;再走过对方的路if(headA NULL|| headB NULL){return NULL;}Lis…

el-uploader同一文件无法上传问题

在上传成功和失败的回调方法中&#xff0c;吊用一下clearFiles方法。 this.$refs.upload.clearFiles();

7、独立按键控制LED状态

按键的抖动 对于机械开关&#xff0c;当机械触点断开、闭合时&#xff0c;由于机械触点的弹性作用&#xff0c;一个开关在闭合时不回马上稳定地接通&#xff0c;在断开时也不会一下子断开&#xff0c;所以在开关闭合及断开的瞬间会伴随一连串的抖动 #include <REGX52.H…

我叫:希尔排序【JAVA】

1.我兄弟存在的问题 2.毛遂自荐 希尔排序提希尔(Donald Shell)于1959年提出的一种排序算法。 希尔排序&#xff0c;也称递减增量排序算法&#xff0c;是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。 希尔排序是基于插入排序的以下两点性质而提出改进方法的&…

postman和Jmeter做接口测试的区别(经验之谈)

接口测试的目的 API 测试作为集成测试的一部分&#xff0c;经过被测应用的接口&#xff08;API&#xff09;来确定是否在功能、可靠性、性能和安全方面达到预期的软件测试。因为 API 都没有 GUI 界面&#xff0c;API 测试都是在通信层进行的。 1.建立接口用例集 Postman功能…

第十八章 解读pytorch优化器与学习率设置(工具)

简介与解读基本概念 学习率对于模型训练效果来说相当重要。 学习率过低会导致学习速度太慢&#xff0c;学习率过高又容易导致难以收敛。 因此&#xff0c;很多炼丹师都会采用动态调整学习率的方法。刚开始训练时&#xff0c;学习率大一点&#xff0c;以加快学习速度&#xf…

2016年11月10日 Go生态洞察:七年的Go语言旅程

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

面试必问:如何快速定位BUG?BUG定位技巧及N板斧!

01 定位问题的重要性 很多测试人员可能会说&#xff0c;我的职责就是找到bug&#xff0c;至于找原因并修复&#xff0c;那是开发的事情&#xff0c;关我什么事&#xff1f; 好&#xff0c;我的回答是&#xff0c;如果您只想做一个测试人员最基本最本分的事情&#xff0c;那么可…

FPGA模块——SPI协议(读写FLASH)

FPGA模块——SPI协议&#xff08;读写FLASH&#xff09; &#xff08;1&#xff09;FLASH芯片 W25Q16BV&#xff08;2&#xff09;SPI协议&#xff08;3&#xff09;芯片部分命令1.Write Enable&#xff08;06h&#xff09;2.Chip Erase (C7h / 60h)3.写指令&#xff08;02h&am…

3.前端--HTML标签2【2023.11.25】

1.HTML常用标签(文本图像链接&#xff09; 文本标签 标题 <h1> - <h6> 段落<p> 我是一个段落标签 </p> 换行 <br /> <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta ht…

js无法请求后端接口,别的都可以?

在每个接口的控制器中加入以下代码即可&#xff1a; header(Access-Control-Allow-Methods:*); header("Access-Control-Allow-Origin:*"); 如果嫌麻烦可以添加在api初始函数里面

全面(16万字)深入探索深度学习:基础原理到经典模型网络的全面解析

前言 Stacking(堆叠) 网页调试 学习率&#xff1a;它决定了模型在每一次迭代中更新参数的幅度激活函数-更加详细 激活函数的意义: 激活函数主要是让模型具有非线性数据拟合的能力&#xff0c;也就是能够对非线性数据进行分割/建模 如果没有激活函数&#xff1a; 第一个隐层: l…

jpom学习

jpom学习 整理jpom 一键安装 部署会需要 mvn跟jdk环境 # 安装服务端和 jdk、maven 环境 yum install -y wget && \ wget -O install.sh https://jpom.top/docs/install.sh && \ bash install.sh Server jdkmvndocker安装 安装docker挂载方式安装 docker …

2023.11.23 云服务器实现 Spring Boot 项目文件上传并访问

环境介绍 云服务器&#xff1a;京东云云服务器系统&#xff1a; CentOS 7.9JDK 版本&#xff1a;1.8Spring Boot 版本&#xff1a;2.7.17 具体步骤 步骤一 首先我们得先创建一个 Spring Boot 项目 创建如下目录结构 关于如何创建一个 Spring Boot 项目 请点击下方链接详细了解 …

【Linux】驱动程序同步和异步通知方式

一、应用程序APP&#xff0c;访问驱动程序/dev/input/enent1流程&#xff1a; 假设用户程序直接访问 /dev/input/event0 设备节点&#xff0c;或者使用 tslib 访问设备节点&#xff0c;数据的流程如下&#xff1a; APP 发起读操作&#xff0c;若无数据则休眠&#xff1b;用户操…

【Linux】 sudo命令使用

sudo sudo是linux系统管理指令&#xff0c;是允许系统管理员让普通用户执行一些或者全部的root命令的一个工具&#xff0c;如halt&#xff0c;reboot&#xff0c;su等等。这样不仅减少了root用户的登录 和管理时间&#xff0c;同样也提高了安全性。sudo不是对shell的一个代替…

AVD黑屏

启动android studio的AVD后&#xff0c;无法开启&#xff0c;一直处于黑屏状态 【解决方案】 1.点击 Android Virtual Device Manager中avd后面的编辑按钮 2.点击Show Advanced Settings按钮 3.找到Boot option中的Cold boot并选中 4.重启AVD

【nacos】配置使用

nacos配置 遇见的问题 代码启动成功&#xff0c;但是配置文件未生效 观察报错 无报错&#xff0c;也看到了加载的配置文件路径&#xff0c;但是配置未生效 [main] [TID: N/A] c.a.c.n.refresh.NacosContextRefresher : [Nacos Config] Listening config: dataIda-servi…

leetcode刷题:17.电话号码的字母组合

leetcode原题网页 题目描述&#xff1a;给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 思路&#xff1a;使用vector&#x…