Express+MySQL后臺開發實戰:從模塊化到錯誤處理的全鏈路解析

Express+MySQL后臺開發實戰:從模塊化到錯誤處理的全鏈路解析

摘要:本文將以Node.js+Express框架為基礎,結合MySQL數據庫實戰,深度剖析后臺系統中數據庫模塊化設計、安全查詢、錯誤處理等核心開發要點。

一、項目環境與技術棧

├── src/
│   ├── db/             # 數據庫模塊
│   │   └── querys/     # 數據模型
│   │   └── index.js    # 數據庫連接池
│   ├── routes/         # 路由層
│   └── app.js          # 主入口
└── .env                # 環境配置

實現后臺實戰開發必須用到的依賴庫:
在這里插入圖片描述

二、核心實現解析

1. 安全連接配置

.env環境配置示例:

SQL_PORT=3306
SQL_HOST='localhost'
SQL_USER='root'
SQL_PASSWORD='your_password'
SQL_DATABASE='back_system'
REDIS_HOST='localhost'
REDIS_PORT=6379
REDIS_PASSWORD='your_redis_password'

連接池初始化邏輯:

const mysql = require('mysql2/promise');const pool = mysql.createPool({host: process.env.SQL_HOST,user: process.env.SQL_USER,password: process.env.SQL_PASSWORD,database: process.env.SQL_DATABASE,waitForConnections: true,connectionLimit: 10,queueLimit: 0
});

2. 模塊化數據層

用戶模型封裝示例:

class UserModel {// 通用查詢方法async find(params = {}) {try {let sql = 'SELECT * FROM users';const whereClauses = [];const values = [];// 動態構建WHERE條件Object.keys(params).forEach(key => {whereClauses.push(`${key} = ?`);values.push(params[key]);});if (whereClauses.length) {sql += ` WHERE ${whereClauses.join(' AND ')}`;}const [rows] = await this.pool.execute(sql, values);return rows;} catch (error) {this.handleError(error, '查詢操作');return false;}}// 統一錯誤處理handleError(error, operation) {console.error(`[DB Error] ${operation}:`, {code: error.code,sqlState: error.sqlState,sqlMessage: error.sqlMessage});}
}

3. 路由層最佳實踐

// 用戶刪除操作
router.post('/delete/:account', async (req, res) => {try {const { account } = req.params;// 參數校驗if (!account) {return res.status(400).json({ code: 400,message: '缺少必要參數' });}const result = await userModel.deleteById(account);if (result > 0) {res.json({code: 200,data: { affectedRows: result },message: '刪除成功'});} else {res.status(404).json({code: 404,message: '用戶不存在'});}} catch (error) {res.status(500).json({code: 500,message: '服務器內部錯誤',debug: process.env.NODE_ENV === 'development' ? error.stack : undefined});}
});

三、關鍵技術解析

1. 安全防護措施

(1) 參數化查詢:所有SQL語句使用?占位符
await this.pool.execute('DELETE FROM users WHERE account = ?', [account])
(2) 輸入驗證:路由層校驗必要參數
router.post('/delete/:id', async function (req, res) {
// 驗證參數if(!req.params.id){return res.send({code: 500,message: '缺少參數'})}const { id } = req.paramsconst user = await userModel.deleteById(id)...后續代碼邏輯
});
(3) 錯誤信息脫敏:生產環境隱藏堆棧詳情
// 錯誤處理中間件
app.use((err, req, res, next) => {console.error(err.stack); // 服務器端仍然記錄完整錯誤const response = {code: err.status || 500,message: err.message || '內部服務器錯誤'};// 開發環境返回完整錯誤信息if (process.env.NODE_ENV === 'development') {response.stack = err.stack;response.details = err;}res.status(response.code).json(response);
});

以刪除用戶為例:

// 刪除用戶
router.post('/delete/:id', async function (req, res) {try {if(!req.params.id) {throw { code: 400, message: '缺少參數' };}if(req.user.identity !== 0) {throw { code: 403, message: '權限不足' };}const { id } = req.params;const result = await userModel.deleteById(id);if (!result) {throw { code: 500, message: '刪除失敗' };}res.json({ code: 200,data: result,message: '刪除成功' });} catch (error) {// 這里會進入上面定義的錯誤處理中間件next(error); }
});

2. 多級錯誤處理

// 模型層記錄原始錯誤
handleError(error) {console.error('[Database Error]', {code: error.code,sql: error.sql,stack: error.stack});
}// 路由層返回友好提示
res.status(500).json({code: 500,message: '請求處理失敗',requestId: req.requestId // 添加請求ID便于追蹤
});

3. 性能優化方案

(1) 連接池配置:
const pool = mysql.createPool({// ...connectionLimit: 10,       // 最大連接數queueLimit: 0,             // 無限制排隊acquireTimeout: 30000      // 30秒獲取超時
});
(2) 索引優化:為account字段添加唯一索引
ALTER TABLE users ADD UNIQUE INDEX idx_account (account);

四、擴展思考

1. 事務處理:多操作原子性保證

const conn = await pool.getConnection();
try {await conn.beginTransaction();// 執行多個操作await conn.query('...');await conn.query('...');await conn.commit();
} catch (error) {await conn.rollback();throw error;
} finally {conn.release();
}

2. 數據緩存:結合Redis提升查詢性能

const { createClient } = require('redis');
// 創建Redis客戶端(添加到現有數據庫配置)
const redisClient = createClient({socket: {host: process.env.REDIS_HOST,port: process.env.REDIS_PORT},password: process.env.REDIS_PASSWORD
});
// 初始化Redis連接
(async () => {try {await redisClient.connect();console.log('Redis connected successfully');} catch (err) {console.error('Redis connection failed:', err);}
})();
// 導出Redis客戶端(保留原有MySQL導出)
module.exports = { pool, redisClient };

操作數據庫函數內:

// 生成唯一緩存鍵
const cacheKey = `user:${JSON.stringify(params)}`;
// 嘗試獲取緩存
const cachedData = await redisClient.get(cacheKey);
if (cachedData) {return JSON.parse(cachedData);
}
// 無緩存則查詢數據庫
const [rows] = await this.pool.execute(/* 原有SQL邏輯 */);
// 設置緩存(1小時過期)
await redisClient.setEx(cacheKey, 3600, JSON.stringify(rows));
return rows;

五、總結

通過模塊化設計,我們將數據庫操作封裝為獨立服務層,配合:

  • 參數化查詢保障安全
  • 多級錯誤處理提升健壯性
  • 連接池優化提升性能

完整項目代碼已開源在:Gitee鏈接

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/84765.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/84765.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/84765.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring AI 智能體代理模式(Agent Agentic Patterns)

AgentAgenticPatterns 簡介 在最近的一篇研究報告《構建高效代理》 中,Anthropic分享了關于構建高效大語言模型(LLM)代理的寶貴見解。這項研究特別有趣的地方在于,它強調簡單性和可組合性,而非復雜的框架。讓我們來探…

基于 Vue3 與 exceljs 實現自定義導出 Excel 模板

在開發中,我們需要常常為用戶提供更多的數據錄入方式,Excel 模板導出與導入是一個常見的功能點。本文將介紹如何使用 Vue3、exceljs 和 file-saver 實現一個自定義導出 Excel 模板,并在特定列添加下拉框選擇的數據驗證功能。 技術選型 excelj…

git 命令之-git cherry-pick

今天得到一個通知,這個業務版本里面部分已經開發但還沒測試的內容要新開一個分支提交,但是我已經有幾個提交上去了,難道只能一個一個文件復制到新的分支嗎?我不,我找到了這個git命令,可以解決我的困惑&…

浙大版《Python 程序設計》題目集6-3,6-4,6-5,6-6列表或元組的數字元素求和及其變式(遞歸解法)

目錄 6-3 輸入格式: 輸出格式: 輸入樣例: 輸出樣例: 6-4 輸入格式: 輸出格式: 輸入樣例: 輸出樣例: 6-5 輸入格式: 輸出格式: 輸入樣例: 輸出樣例: 6-6 輸入格式: 輸出格式: 輸入樣例: 輸出樣例: 6-3 第6章-3 列表或元組的數字元素求和 分數 20 全屏瀏覽 切換布局 作者 陳春暉 …

【b站計算機拓荒者】【2025】微信小程序開發教程 - chapter2 小程序核心

1 尺寸單位和樣式 1.1 創建小程序項目-純凈環境 // 該刪的刪掉。 1.2 尺寸單位 # 小程序內 手機屏幕大小可能不一樣,使用px像素就會出現樣式問題 --> 小程序統一了整個寬度,即750rpx,屏幕一半則是375rpx -->因此不管什么手機都可以…

攻防世界逆向刷題筆記(新手模式9-1?)

bad_python 看樣子是pyc文件損壞了。利用工具打開,發現是MAGIC壞了。搜下也沒有頭緒。 攻防世界-難度1- bad_python - _rainyday - 博客園 python Magic Number對照表以及pyc修復方法 - iPlayForSG - 博客園 看WP才知道36已經提示了pyc版本了。參考第二個文章&am…

mysql ACID 原理

序言:ACID 是一組數據庫設計原則,他是業務數據和關鍵業務程序的可靠性保障。 1、atomicity(原子性) 依賴如下能力 autocommit commit rollback2、一致性 2.1 double write buffer 1、定義:double write buffer 是…

WebStorm 高效快捷方式全解析

作為前端開發的黃金搭檔,WebStorm 憑借強大的功能和高度可定制的快捷鍵體系,成為眾多開發者提升編碼效率的利器。本文基于 IntelliJ IDEA 的快捷鍵體系(WebStorm 作為 JetBrains 家族成員,快捷鍵邏輯高度一致)&#xf…

基于 STM32 的農村污水處理控制系統設計與實現

摘要 針對農村污水處理自動化程度低、運維成本高的問題,本文設計了一種基于 STM32 單片機的污水處理控制系統。系統通過多傳感器實時監測水質參數,結合 PID 控制算法實現污水處理全流程自動化,并集成遠程監控功能,滿足農村地區低成本、易維護的需求。 一、硬件系統設計 …

自動生成md文件以及config.mjs文件-vitepress

效果: config.mjs文件 import {defineConfig} from vitepress import hljs from highlight.js/lib/core import javascript from highlight.js/lib/languages/javascript import xml from highlight.js/lib/languages/xml import {ref} from "./cache/deps/vue…

Tailwind css實戰,基于Kooboo構建AI對話框頁面(二)

基于上篇內容,添加交互邏輯,實現一個偽聊天功能的對話框效果: Tailwind css實戰,基于Kooboo構建AI對話框頁面(一)-CSDN博客 在前期文章中,我們完成了 AI 對話框的靜態頁面搭建。本文將聚焦交互…

Conda:環境移植及更新1--使用conda-pack

更多內容:XiaoJ的知識星球 目錄 一、使用conda-pack1.安裝 conda-pack2.移植整個 Anaconda 環境3.移植單個虛擬環境4.驗證是否生效 在相同Linux設備上移植Miniconda3(Anaconda3同理)常用方法有。 使用conda-pack:使用conda-pack工…

樹莓派超全系列教程文檔--(50)如何查找樹莓派的IP地址

如何查找樹莓派的IP地址 找到您的Raspberry Pi的IP地址桌面命令行引導輸出網絡管理器使用mDNS解析 raspberrypi.local檢查路由器的設備列表使用 nmap 查找設備使用智能手機應用程序查找設備 文章來源: http://raspberry.dns8844.cn/documentation 原文網址 找到您…

如何優化 MySQL 存儲過程的性能?

文章目錄 1. 優化 SQL 語句避免全表掃描減少子查詢,改用 JOIN避免 SELECT 2. 合理使用索引3. 優化存儲過程結構減少循環和臨時變量避免重復計算 4. 使用臨時表和緩存5. 優化事務處理6. 分析和監控性能7. 優化數據庫配置8. 避免用戶自定義函數(UDF&#…

尚硅谷redis7 47-48 redis事務之理論簡介

47 redis事務之理論簡介 什么是事務 可以一次執行多個命令,本質是一組命令的集合。一個事務中的所有命令都會序列化,按順序地串行化執行而不會被其它命令插入 能干什么? 一個隊列中,一次性、順序性、排他性的執行一系列操作 redis事務vs數據庫事務 …

Nginx 在四大核心場景中的應用實踐與優化

一、Nginx 核心應用場景深度解析 1. HTTP 服務器:靜態資源的高性能承載者 Nginx 作為 HTTP 服務器時,憑借輕量級架構和高效的事件驅動模型,成為靜態資源服務的首選方案。 核心能力與場景 靜態文件高效處理:直接響應 HTML、CSS…

亞當·斯密思想精髓的數學建模與形式化表征

亞當斯密思想精髓的數學建模與形式化表征 摘要:本文運用數學建模方法對亞當斯密的經濟與倫理思想進行形式化表征。通過分工的規模經濟模型和市場均衡條件展現《國富論》中"看不見的手"原理;采用擴展效用函數與合作博弈均衡解釋《道德情操論》…

FastDFS集群部署與性能優化實戰

目錄 一、介紹 二、FastDFS原理 三、FastDFS部署 1.資源清單 2.修改主機名 3.安裝libfastcommon(tracker01、tracker02、storage1、storage2) 4.安裝編譯FastDFS(tracker01、tracker02、storage1、storage2) 5.配置tracker…

學習心得(14--16)

模板: 前端的頁面單獨存在模板當中 jinja2 :模板語法 保持前端頁面不變的情況下,返回內容給前端做法: 寫一個data,并在return中的render_template中,寫上datadata 使用時,要將templa…

stm與51單片機哪個更適合新手學

一句話總結 51單片機:像學騎自行車,簡單便宜,但只能在小路上騎。 STM32:像學開汽車,復雜但功能強,能上高速公路,還能拉貨載人(做復雜項目)。 1. 為啥有人說“先學51單片…