当前位置: 首页 > news >正文

智能图书馆管理系统开发实战系列(四):后端C++ DLL开发与模块化设计

前言

在前端工程化搭建完成后,我们需要构建高性能的后端业务逻辑层。本文将深入介绍位于 code/backend/dll/ 目录下的C++ DLL开发实践,包括模块化架构设计、CMake构建系统配置,以及如何实现可扩展的业务逻辑框架。

后端架构设计理念

为什么选择C++ DLL?

相比纯Web后端方案,C++ DLL架构具有以下优势:

  1. 性能优势: 原生C++代码执行效率高,特别适合数据密集型操作
  2. 内存管理: 精确的内存控制,避免垃圾回收开销
  3. 系统集成: 可以直接调用操作系统API和第三方库
  4. 部署简单: 单文件DLL部署,无需复杂的运行时环境
  5. 前后端解耦: 通过标准化接口实现完全的前后端分离

模块化设计原则

code/backend/dll/CMakeLists.txt 中可以看到我们的模块化组织:

# 按功能模块组织源代码文件
file(GLOB IMPL_BOOKMANAGER_GROUP_FILES"${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/BookManager/*.cpp""${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/BookManager/*.h"
)file(GLOB IMPL_BOOKMANAGER_ADDBOOK_GROUP_FILES"${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/BookManager/AddBook/*.cpp""${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/BookManager/AddBook/*.h"
)file(GLOB IMPL_LOANMANAGER_GROUP_FILES"${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/LoanManager/*.cpp""${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/LoanManager/*.h"
)file(GLOB IMPL_DASHBOARD_GROUP_FILES"${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/DashBoard/*.cpp""${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/DashBoard/*.h"
)

模块设计特点:

  • 功能内聚: 每个模块负责特定的业务领域
  • 层次分明: 主模块下按操作类型进一步细分
  • 接口统一: 所有模块遵循统一的调用约定
  • 依赖清晰: 模块间依赖关系明确可控

项目结构深度解析

目录结构设计

code/backend/dll/
├── CMakeLists.txt              # CMake构建配置
├── Src/                        # 源代码目录
│   ├── Impl/                  # 业务逻辑实现
│   │   ├── BookManager/       # 图书管理模块
│   │   │   ├── AddBook/       # 添加图书功能
│   │   │   ├── DeleteBook/    # 删除图书功能
│   │   │   ├── EditBook/      # 编辑图书功能
│   │   │   └── GetBookList/   # 图书列表功能
│   │   ├── ReaderManager/     # 读者管理模块
│   │   ├── LoanManager/       # 借阅管理模块
│   │   ├── DashBoard/         # 仪表板模块
│   │   ├── QuerySearch/       # 查询搜索模块
│   │   ├── StatisticsReport/  # 统计报表模块
│   │   ├── SystemSettings/    # 系统设置模块
│   │   ├── LibGlobal/         # 全局管理模块
│   │   └── Persist/           # 数据持久化模块
│   ├── ModExport/             # 模块导出定义
│   ├── BookManagerCAPI.cpp    # 图书管理C接口
│   ├── ReaderManagerCAPI.cpp  # 读者管理C接口
│   ├── LoanManagerCAPI.cpp    # 借阅管理C接口
│   └── DashBoardCAPI.cpp      # 仪表板C接口
└── export/                    # 导出头文件

CMake构建系统分析

code/backend/dll/CMakeLists.txt 的配置可以看出严格的构建规范:

cmake_minimum_required(VERSION 3.10)
project (libBackend)# 环境变量配置
SET(UNISDK_ROOT_PROJ "$ENV{UNISDK_ROOT}")# 头文件包含路径
include_directories(./Src)
include_directories(${UNISDK_ROOT_PROJ}/export_csdk/)
include_directories(${UNISDK_ROOT_PROJ}/export_cppsdk/)
include_directories(${UNISDK_ROOT_PROJ}/export_cppsdk/cppsdk/third/)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../submod_include)

构建特点:

  • 模块化编译: 每个功能模块独立编译
  • 依赖管理: 统一的头文件和库依赖管理
  • 环境适配: 支持不同开发环境的配置
  • 版本控制: CMake版本要求明确

核心业务模块实现

1. 图书管理模块 (BookManager)

图书管理是系统的核心功能,我们采用CRUD+列表的标准模式:

// Src/Impl/BookManager/BookManager.h
#ifndef BOOK_MANAGER_H
#define BOOK_MANAGER_H#include "Common/BaseResult.h"
#include "Common/JsonHelper.h"
#include <string>namespace LibrarySystem {
namespace BookManager {class BookManagerImpl {
public:static bool AddBook(const std::string& bookJson, std::string& resultJson);static bool DeleteBook(const std::string& bookId, std::string& resultJson);static bool EditBook(const std::string& bookJson, std::string& resultJson);static bool GetBookList(const std::string& queryJson, std::string& resultJson);static bool GetBookDetail(const std::string& bookId, std::string& resultJson);private:static bool ValidateBookData(const JsonObject& bookData);static bool CheckBookExists(const std::string& bookId);static std::string GenerateBookId();
};} // namespace BookManager
} // namespace LibrarySystem#endif // BOOK_MANAGER_H
添加图书功能实现
// Src/Impl/BookManager/AddBook/AddBookImpl.cpp
#include "BookManager.h"
#include "Database/DatabaseManager.h"
#include "Common/LogManager.h"namespace LibrarySystem {
namespace BookManager {bool BookManagerImpl::AddBook(const std::string& bookJson, std::string& resultJson) {bool bRet = false;JsonObject result;try {// 解析输入JSONJsonObject bookData;if (!JsonHelper::Parse(bookJson, bookData)) {result["success"] = false;result["error"] = "Invalid JSON format";resultJson = JsonHelper::Stringify(result);goto exit;}// 验证数据完整性if (!ValidateBookData(bookData)) {result["success"] = false;result["error"] = "Invalid book data";resultJson = JsonHelper::Stringify(result);goto exit;}// 检查ISBN是否已存在std::string isbn = bookData["isbn"].asString();if (CheckBookExists(isbn)) {result["success"] = false;result["error"] = "Book already exists";resultJson = JsonHelper::Stringify(result);goto exit;}// 生成唯一IDstd::string bookId = GenerateBookId();bookData["id"] = bookId;bookData["addedDate"] = JsonHelper::GetCurrentTimestamp();// 保存到数据库DatabaseManager& db = DatabaseManager::GetInstance();if (!db.InsertBook(bookData)) {result["success"] = false;result["error"] = "Database operation failed";resultJson = JsonHelper::Stringify(result);goto exit;}// 成功返回result["success"] = true;result["bookId"] = bookId;resultJson = JsonHelper::Stringify(result);bRet = true;} catch (const std::exception& e) {LogManager::Error("AddBook failed: %s", e.what());result["success"] = false;result["error"] = "Internal error";resultJson = JsonHelper::Stringify(result);}exit:return bRet;}bool BookManagerImpl::ValidateBookData(const JsonObject& bookData) {// 验证必需字段const std::vector<std::string> requiredFields = {"title", "author", "isbn", "category", "publisher"};for (const auto& field : requiredFields) {if (!bookData.has(field) || bookData[field].asString().empty()) {return false;}}// 验证ISBN格式std::string isbn = bookData["isbn"].asString();if (isbn.length() != 13 && isbn.length() != 10) {return false;}return true;
}} // namespace BookManager
} // namespace LibrarySystem

2. 借阅管理模块 (LoanManager)

借阅管理涉及复杂的业务逻辑,包括借书、还书、续借、超期处理等:

// Src/Impl/LoanManager/LoanManager.h
#ifndef LOAN_MANAGER_H
#define LOAN_MANAGER_H#include "Common/BaseResult.h"
#include <string>namespace LibrarySystem {
namespace LoanManager {class LoanManagerImpl {
public:static bool BorrowBook(const std::string& requestJson, std::string& resultJson);static bool ReturnBook(const std::string& requestJson, std::string& resultJson);static bool RenewBook(const std::string& requestJson, std::string& resultJson);static bool GetBorrowRecords(const std::string& queryJson, std::string& resultJson);static bool GetOverdueBooks(std::string& resultJson);private:static bool CheckBookAvailability(const std::string& bookId);static bool CheckUserBorrowLimit(const std::string& userId);static bool CalculateDueDate(const std::string& borrowDate, std::string& dueDate);static bool CheckOverdue(const std::string& dueDate);
};} // namespace LoanManager
} // namespace LibrarySystem#endif // LOAN_MANAGER_H
借书功能实现
// Src/Impl/LoanManager/BorrowBook/BorrowBookImpl.cpp
#include "LoanManager.h"
#include "Database/DatabaseManager.h"
#include "Common/DateTimeHelper.h"namespace LibrarySystem {
namespace LoanManager {bool LoanManagerImpl::BorrowBook(const std::string& requestJson, std::string& resultJson) {bool bRet = false;JsonObject result;try {JsonObject request;if (!JsonHelper::Parse(requestJson, request)) {result["success"] = false;result["error"] = "Invalid request format";resultJson = JsonHelper::Stringify(result);goto exit;}std::string bookId = request["bookId"].asString();std::string userId = request["userId"].asString();// 检查图书可用性if (!CheckBookAvailability(bookId)) {result["success"] = false;result["error"] = "Book not available";resultJson = JsonHelper::Stringify(result);goto exit;}// 检查用户借阅限制if (!CheckUserBorrowLimit(userId)) {result["success"] = false;result["error"] = "User borrow limit exceeded";resultJson = JsonHelper::Stringify(result);goto exit;}// 计算归还日期std::string currentDate = DateTimeHelper::GetCurrentDate();std::string dueDate;if (!CalculateDueDate(currentDate, dueDate)) {result["success"] = false;result["error"] = "Failed to calculate due date";resultJson = JsonHelper::Stringify(result);goto exit;}// 创建借阅记录JsonObject borrowRecord;borrowRecord["id"] = GenerateBorrowId();borrowRecord["bookId"] = bookId;borrowRecord["userId"] = userId;borrowRecord["borrowDate"] = currentDate;borrowRecord["dueDate"] = dueDate;borrowRecord["status"] = "active";DatabaseManager& db = DatabaseManager::GetInstance();// 开启事务if (!db.BeginTransaction()) {result["success"] = false;result["error"] = "Transaction failed";resultJson = JsonHelper::Stringify(result);goto exit;}// 插入借阅记录if (!db.InsertBorrowRecord(borrowRecord)) {db.RollbackTransaction();result["success"] = false;result["error"] = "Failed to create borrow record";resultJson = JsonHelper::Stringify(result);goto exit;}// 更新图书状态if (!db.UpdateBookStatus(bookId, "borrowed")) {db.RollbackTransaction();result["success"] = false;result["error"] = "Failed to update book status";resultJson = JsonHelper::Stringify(result);goto exit;}// 提交事务if (!db.CommitTransaction()) {result["success"] = false;result["error"] = "Transaction commit failed";resultJson = JsonHelper::Stringify(result);goto exit;}result["success"] = true;result["borrowId"] = borrowRecord["id"].asString();result["dueDate"] = dueDate;resultJson = JsonHelper::Stringify(result);bRet = true;} catch (const std::exception& e) {DatabaseManager::GetInstance().RollbackTransaction();LogManager::Error("BorrowBook failed: %s", e.what());result["success"] = false;result["error"] = "Internal error";resultJson = JsonHelper::Stringify(result);}exit:return bRet;
}} // namespace LoanManager
} // namespace LibrarySystem

3. 仪表板模块 (Dashboard)

仪表板提供系统概览数据,需要高效的数据聚合能力:

// Src/Impl/DashBoard/DashBoardImpl.cpp
#include "DashBoard.h"
#include "Database/DatabaseManager.h"namespace LibrarySystem {
namespace Dashboard {bool DashboardImpl::GetDashboardStats(std::string& resultJson) {bool bRet = false;JsonObject result;try {DatabaseManager& db = DatabaseManager::GetInstance();// 获取图书统计int totalBooks = db.GetTotalBooksCount();int availableBooks = db.GetAvailableBooksCount();int borrowedBooks = db.GetBorrowedBooksCount();// 获取用户统计int totalUsers = db.GetTotalUsersCount();int activeUsers = db.GetActiveUsersCount();// 获取借阅统计int activeBorrows = db.GetActiveBorrowsCount();int overdueBooks = db.GetOverdueBooksCount();int todayBorrows = db.GetTodayBorrowsCount();int todayReturns = db.GetTodayReturnsCount();// 组装结果JsonObject stats;stats["totalBooks"] = totalBooks;stats["availableBooks"] = availableBooks;stats["borrowedBooks"] = borrowedBooks;stats["totalUsers"] = totalUsers;stats["activeUsers"] = activeUsers;stats["activeBorrows"] = activeBorrows;stats["overdueBooks"] = overdueBooks;stats["todayBorrows"] = todayBorrows;stats["todayReturns"] = todayReturns;// 获取图表数据JsonArray borrowTrend = db.GetBorrowTrendData(30); // 最近30天JsonArray categoryDistribution = db.GetCategoryDistributionData();result["success"] = true;result["stats"] = stats;result["borrowTrend"] = borrowTrend;result["categoryDistribution"] = categoryDistribution;resultJson = JsonHelper::Stringify(result);bRet = true;} catch (const std::exception& e) {LogManager::Error("GetDashboardStats failed: %s", e.what());result["success"] = false;result["error"] = "Failed to get dashboard stats";resultJson = JsonHelper::Stringify(result);}return bRet;
}} // namespace Dashboard
} // namespace LibrarySystem

公共基础设施

1. 数据库管理器

// Src/Common/Database/DatabaseManager.h
#ifndef DATABASE_MANAGER_H
#define DATABASE_MANAGER_H#include <sqlite3.h>
#include <string>
#include <memory>
#include "Common/Singleton.h"namespace LibrarySystem {class DatabaseManager : public Singleton<DatabaseManager> {
public:bool Initialize(const std::string& dbPath);void Shutdown();// 事务管理bool BeginTransaction();bool CommitTransaction();bool RollbackTransaction();// 图书操作bool InsertBook(const JsonObject& bookData);bool UpdateBook(const std::string& bookId, const JsonObject& bookData);bool DeleteBook(const std::string& bookId);bool GetBookById(const std::string& bookId, JsonObject& bookData);// 统计查询int GetTotalBooksCount();int GetAvailableBooksCount();JsonArray GetBorrowTrendData(int days);private:sqlite3* m_db;bool m_initialized;bool CreateTables();bool ExecuteSQL(const std::string& sql);bool PrepareStatement(const std::string& sql, sqlite3_stmt** stmt);
};} // namespace LibrarySystem#endif // DATABASE_MANAGER_H

2. JSON处理工具

// Src/Common/JsonHelper.h
#ifndef JSON_HELPER_H
#define JSON_HELPER_H#include <json/json.h>
#include <string>namespace LibrarySystem {using JsonObject = Json::Value;
using JsonArray = Json::Value;class JsonHelper {
public:static bool Parse(const std::string& jsonStr, JsonObject& jsonObj);static std::string Stringify(const JsonObject& jsonObj);static std::string GetCurrentTimestamp();static bool ValidateSchema(const JsonObject& jsonObj, const JsonObject& schema);private:static Json::StreamWriterBuilder GetWriterBuilder();static Json::CharReaderBuilder GetReaderBuilder();
};} // namespace LibrarySystem#endif // JSON_HELPER_H

3. 日志管理系统

// Src/Common/LogManager.h
#ifndef LOG_MANAGER_H
#define LOG_MANAGER_H#include <string>
#include <fstream>
#include <mutex>namespace LibrarySystem {enum class LogLevel {DEBUG = 0,INFO = 1,WARNING = 2,ERROR = 3
};class LogManager {
public:static void Initialize(const std::string& logPath, LogLevel level = LogLevel::INFO);static void Shutdown();static void Debug(const char* format, ...);static void Info(const char* format, ...);static void Warning(const char* format, ...);static void Error(const char* format, ...);private:static void WriteLog(LogLevel level, const std::string& message);static std::string GetCurrentTime();static std::string GetLogLevelString(LogLevel level);static std::ofstream s_logFile;static std::mutex s_logMutex;static LogLevel s_logLevel;static bool s_initialized;
};} // namespace LibrarySystem#endif // LOG_MANAGER_H

DLL导出接口设计

统一的C接口

// Src/Interface/LibraryAPI.h
#ifndef LIBRARY_API_H
#define LIBRARY_API_H#ifdef _WIN32#ifdef LIBRARY_EXPORTS#define LIBRARY_API __declspec(dllexport)#else#define LIBRARY_API __declspec(dllimport)#endif#define LIBRARY_CALL __stdcall
#else#define LIBRARY_API#define LIBRARY_CALL
#endifextern "C" {// 库初始化LIBRARY_API bool LIBRARY_CALL InitLibrary(const char* configJson);LIBRARY_API void LIBRARY_CALL ShutdownLibrary();// 图书管理LIBRARY_API bool LIBRARY_CALL AddBook(const char* bookJson, char* resultJson, int resultSize);LIBRARY_API bool LIBRARY_CALL DeleteBook(const char* bookId, char* resultJson, int resultSize);LIBRARY_API bool LIBRARY_CALL EditBook(const char* bookJson, char* resultJson, int resultSize);LIBRARY_API bool LIBRARY_CALL GetBookList(const char* queryJson, char* resultJson, int resultSize);// 借阅管理LIBRARY_API bool LIBRARY_CALL BorrowBook(const char* requestJson, char* resultJson, int resultSize);LIBRARY_API bool LIBRARY_CALL ReturnBook(const char* requestJson, char* resultJson, int resultSize);LIBRARY_API bool LIBRARY_CALL GetBorrowRecords(const char* queryJson, char* resultJson, int resultSize);// 仪表板LIBRARY_API bool LIBRARY_CALL GetDashboardStats(char* resultJson, int resultSize);
}#endif // LIBRARY_API_H

接口实现

// Src/Interface/LibraryAPI.cpp
#include "LibraryAPI.h"
#include "Impl/BookManager/BookManager.h"
#include "Impl/LoanManager/LoanManager.h"
#include "Impl/DashBoard/DashBoard.h"
#include "Common/LogManager.h"using namespace LibrarySystem;extern "C" {LIBRARY_API bool LIBRARY_CALL InitLibrary(const char* configJson) {try {JsonObject config;if (!JsonHelper::Parse(configJson, config)) {return false;}// 初始化日志系统std::string logPath = config["logPath"].asString();LogManager::Initialize(logPath);// 初始化数据库std::string dbPath = config["dbPath"].asString();DatabaseManager& db = DatabaseManager::GetInstance();if (!db.Initialize(dbPath)) {return false;}LogManager::Info("Library initialized successfully");return true;} catch (...) {return false;}
}LIBRARY_API bool LIBRARY_CALL AddBook(const char* bookJson, char* resultJson, int resultSize) {try {std::string result;bool success = BookManager::BookManagerImpl::AddBook(bookJson, result);if (result.length() < static_cast<size_t>(resultSize)) {strcpy_s(resultJson, resultSize, result.c_str());return success;}return false;} catch (...) {return false;}
}LIBRARY_API bool LIBRARY_CALL GetDashboardStats(char* resultJson, int resultSize) {try {std::string result;bool success = Dashboard::DashboardImpl::GetDashboardStats(result);if (result.length() < static_cast<size_t>(resultSize)) {strcpy_s(resultJson, resultSize, result.c_str());return success;}return false;} catch (...) {return false;}
}} // extern "C"

性能优化策略

1. 内存管理优化

// 使用智能指针管理资源
class BookManager {
private:std::unique_ptr<DatabaseConnection> m_dbConnection;std::shared_ptr<CacheManager> m_cache;public:BookManager() : m_dbConnection(std::make_unique<DatabaseConnection>()), m_cache(std::make_shared<CacheManager>()) {}
};// 使用内存池减少分配开销
class MemoryPool {
public:template<typename T>T* Allocate() {return static_cast<T*>(GetBlock(sizeof(T)));}template<typename T>void Deallocate(T* ptr) {ReturnBlock(ptr, sizeof(T));}
};

2. 数据库连接优化

// 连接池管理
class ConnectionPool {
private:std::queue<sqlite3*> m_availableConnections;std::mutex m_mutex;int m_maxConnections;public:sqlite3* AcquireConnection() {std::lock_guard<std::mutex> lock(m_mutex);if (!m_availableConnections.empty()) {sqlite3* conn = m_availableConnections.front();m_availableConnections.pop();return conn;}return CreateNewConnection();}void ReleaseConnection(sqlite3* conn) {std::lock_guard<std::mutex> lock(m_mutex);m_availableConnections.push(conn);}
};

3. 缓存策略

// LRU缓存实现
template<typename K, typename V>
class LRUCache {
private:std::unordered_map<K, typename std::list<std::pair<K, V>>::iterator> m_map;std::list<std::pair<K, V>> m_list;size_t m_capacity;public:V Get(const K& key) {auto it = m_map.find(key);if (it != m_map.end()) {// 移动到前面m_list.splice(m_list.begin(), m_list, it->second);return it->second->second;}return V{};}void Put(const K& key, const V& value) {auto it = m_map.find(key);if (it != m_map.end()) {it->second->second = value;m_list.splice(m_list.begin(), m_list, it->second);return;}if (m_list.size() >= m_capacity) {// 删除最少使用的m_map.erase(m_list.back().first);m_list.pop_back();}m_list.emplace_front(key, value);m_map[key] = m_list.begin();}
};

错误处理与调试

异常安全的代码结构

// RAII资源管理
class DatabaseTransaction {
private:DatabaseManager& m_db;bool m_committed;public:DatabaseTransaction(DatabaseManager& db) : m_db(db), m_committed(false) {m_db.BeginTransaction();}~DatabaseTransaction() {if (!m_committed) {m_db.RollbackTransaction();}}void Commit() {m_db.CommitTransaction();m_committed = true;}
};// 使用示例
bool AddBookWithTransaction(const JsonObject& bookData) {try {DatabaseTransaction trans(DatabaseManager::GetInstance());// 执行数据库操作if (!ValidateAndInsertBook(bookData)) {return false; // 析构函数会自动回滚}trans.Commit(); // 手动提交return true;} catch (...) {return false; // 异常时自动回滚}
}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

下期预告

在下一篇文章中,我们将详细介绍前后端集成的关键技术:如何使用koffi实现JavaScript与C++ DLL的无缝调用,包括数据类型转换、错误处理、性能优化等关键实践。

总结

本文深入介绍了C++ DLL后端开发的完整实践,包括:

  1. 模块化架构设计: 清晰的功能模块划分和依赖关系
  2. CMake构建系统: 灵活的构建配置和依赖管理
  3. 业务逻辑实现: 高质量的C++代码和最佳实践
  4. 公共基础设施: 数据库、日志、JSON等工具封装
  5. 性能优化策略: 内存管理、缓存、连接池等优化手段
  6. 错误处理机制: 异常安全和资源管理

通过这些实践,我们构建了一个高性能、可维护、可扩展的C++后端系统,为前端应用提供了坚实的业务逻辑支撑。

系列文章目录

  1. 项目架构设计与技术选型
  2. 高保真原型设计与用户体验测试
  3. 前端工程化实践:Electron + React + TypeScript
  4. 后端C++ DLL开发与模块化设计
  5. 前后端集成:koffi调用与接口设计
  6. Google Test单元测试实践
  7. CMake构建系统与持续集成
  8. 性能优化与部署发布

通过这个系列文章,您将学习到现代桌面应用开发的完整流程和最佳实践。

程序及源码附件下载

程序及源码

http://www.lryc.cn/news/606809.html

相关文章:

  • Dify版本升级实操
  • 体育直播系统搭建:核心数据详细接入指南
  • 网络编程-加密算法
  • CCleaner是否被过誉了?C盘满了怎么办?用ccleaner清除C盘垃圾,3款电脑系统磁盘清理和优化软件
  • 应用Builder模式在C++中进行复杂对象构建
  • Vue与Ajax快速入门
  • GXP6040K压力传感器可应用于医疗/汽车/家电
  • Python Flask框架Web应用开发完全教程
  • 【stm32】GPIO
  • 第3章 AB实验的统计学知识
  • 从Web2.0到Web3.0:社交参与方式的重塑与延伸
  • 报错[Vue warn]: Failed to resolve directive: else如何解决?
  • Linux9 root密码修改
  • 数据结构第5问:什么是队列?
  • 【科普】怎么理解Modbus、TCP、UDP
  • C++入门自学Day4-- c++类与对象(友元)
  • 《软件测试与质量控制》实验报告一 测试用例设计
  • 新一代PLC控制软件平台EsDA-AWStudio
  • Linux文件系统理解2
  • Python爬虫库性能与选型实战指南:从需求到落地的全链路解析
  • PendingIntent的flag和原理解析
  • 如何使用淘宝开放平台API获取商品详细信息?
  • Docker设置容器时间
  • 通过pendingIntent启动activity被block问题
  • 网站QPS多少才算高并发
  • TOGAF指南1
  • Effective C++ 条款16: 成对使用new和delete时要采用相同形式
  • pycharm快捷键设置为和vscode一样
  • 数据仓库、数据湖与湖仓一体技术笔记
  • 高防服务器租用:保障数据安全