@TOC
-
本项目是一个 Express 框架搭配 mysql 的后台管理系统后端开发
-
github 地址:点击跳转
- 使用 express 应用程序生成器生成项目:npx express-generator
- 初始化安装依赖:npm install
- 安装:npm install nodemon
- 修改:"start": "nodemon ./bin/www" --- 修改 package.json 文件
- 启动:npm start
-
安装:npm install mysql2
-
封装:
const mysql = require("mysql2"); // 创建数据库连接池 const pool = mysql.createPool({ host: "", // 地址 port: "", // 端口 user: "", // 用户名 password: "", // 密码 database: "" // 数据库名称 }); // 简单封装查询函数 const query = (sql, params) => { return new Promise((resolve, reject) => { // 会主动释放连接 pool.execute(sql, params, (error, results) => { if (error) reject(error); else resolve(results); }); }); }; module.exports = { query };
-
使用:
var db = require("../server/index"); router.get("/getUserList", async (req, res) => { try { const result = await db.query("select * from users"); res.status(result.code).json(result); // 根据 code 返回不同状态码 } catch (error) { res.status(error.code || 500).json(error); // 捕获错误并返回相应的 code 和错误信息 } });
-
产生问题:
- ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client:点击查看解决方案
-
在 routes 文件夹下创建 pages.js
/** * 路由模块 * prefix: 路由前缀 * component: 路由组件 */ const pages = [ { component: require("./index") // 主路由 }, { component: require("./users") // 用户路由 } ]; // 在此将所有路由模块手动导入并挂载到主路由 module.exports = (app) => { pages.forEach((page) => { app.use(`/${page.prefix || ""}`, page.component); }); };
-
在 app.js 中使用
// 导入主路由模块 const routes = require("./routes/pages"); // 挂载路由:需要在挂载中间件之后 routes(app);
-
在 utils 文件夹下创建 response.js
/** * 响应函数 * @param {*} res 响应对象 * @param {*} statusCode 状态码 * @param {*} status 状态 * @param {*} message 消息 * @param {*} data 数据 */ const sendResponse = (res, statusCode, status, message, data = null) => { const response = { status, code: statusCode, message, data }; res.status(statusCode).json(response); }; module.exports = sendResponse;
-
使用:
// 导入响应函数 const sendResponse = require("../utils/response"); // 查询用户列表 router.get("/getUserList", async (req, res) => { try { const result = await db.query("select * from users"); sendResponse(res, 200, "success", "请求成功", result); } catch (error) { sendResponse(res, 500, "error", error.message); } });
-
安装:npm install express-validator
-
封装:
const sendResponse = require("./response.js"); const { validationResult } = require("express-validator"); /** * 通用验证中间件生成器 * @param {Array} validations - express-validator 的规则数组 * @returns {Function} 中间件函数 */ const validate = (validations) => { return async (req, res, next) => { // 执行验证规则 for (const validation of validations) { const result = await validation.run(req); if (result.errors.length) break; } // 检查验证结果 const errors = validationResult(req); if (!errors.isEmpty()) return sendResponse(res, 400, "error", errors.array()[0].msg); next(); }; }; module.exports = validate;
-
使用:
const { body } = require("express-validator"); const sendResponse = require("../utils/response.js"); // 响应函数 const validate = require("../utils/validate.js"); // 数据校验 let loginValidators = [body("username").notEmpty().withMessage("用户名不能为空"), body("password").notEmpty().withMessage("密码不能为空")]; router.post("/login", validate(loginValidators), async (req, res) => { let { username, password } = req.body; try { const result = await db.query("select * from users where username =? and password =?", [username, password]); if (result.length > 0) { sendResponse(res, 200, "success", "登录成功", result); } else { sendResponse(res, 401, "error", "登录失败"); } } catch (error) { sendResponse(res, 500, "error", error.message); } });
-
安装:npm install jsonwebtoken
-
生成 token:
const sendResponse = require("./response.js"); const jwt = require("jsonwebtoken"); const SECRET_KEY = "zhou-secret-key-123456"; // 秘钥 const EXPIRES_IN = "24h"; // 过期时间 1天 /** * 生成 token * @param {Object} payload - 要包含在 token 中的数据 * @returns {String} 生成的 token */ const generateToken = (payload) => { return jwt.sign(payload, SECRET_KEY, { expiresIn: EXPIRES_IN }); }; module.exports = { generateToken };
-
使用:
const { generateToken } = require("../utils/token.js"); // 生成token router.post("/login", async (req, res) => { let { username, password } = req.body; try { const result = await db.query("select * from users where username =? and password =?", [username, password]); if (result.length > 0) { // 生成token let userid = result[0].userid; let username = result[0].username; const token = generateToken({ userid, username }); // 将token存入数据库 await db.query("update users set token =? where username =?", [token, username]); // 返回数据 result[0].token = token; sendResponse(res, 200, "success", "登录成功", result[0]); } else { sendResponse(res, 401, "error", "登录失败"); } } catch (error) { sendResponse(res, 500, "error", error.message); } });
-
封装验证接口 token 是否过期或者没有:
/** * 接口需要token验证 * @param {*} req 请求对象 * @param {*} res 响应对象 * @param {*} next 下一步 * @returns * Authorization: token */ function verifyToken(req, res, next) { const token = req.headers["authorization"]; if (!token) return sendResponse(res, 401, "error", "token过期"); // 验证 Token jwt.verify(token, SECRET_KEY, (err, user) => { if (err) return sendResponse(res, 401, "error", "token过期"); next(); }); } module.exports = { verifyToken };
-
使用:
const { verifyToken } = require("../utils/token.js"); // 验证token // 获取用户列表 router.get("/getUserList", verifyToken, async (req, res) => { try { const result = await db.query("select * from users"); sendResponse(res, 200, "success", "请求成功", result); } catch (error) { sendResponse(res, 500, "error", error.message); } });
-
安装:npm install uuid
-
使用:
const { v4: uuidv4 } = require("uuid"); // 生成uuid const uuid = uuidv4();
-
安装:npm install gm-crypt
-
参数解密(在封装的验证数据进行解密):
const validate = (validations) => { return async (req, res, next) => { // 是否加密 let isEncryption = req.headers.isencryption; // 解密post if (req.method == "POST" && isEncryption == "true" && req.body) { req.body = decrypt(req.body.toString()); console.log("请求:", req.body); } // 解密get if (req.method == "GET" && isEncryption == "true" && req.url.split("?")[1]) { req.query = decrypt(req.url.split("?")[1]); console.log("请求:", req.query); } // 执行验证规则 for (const validation of validations) { const result = await validation.run(req); if (result.errors.length) break; } // 检查验证结果 const errors = validationResult(req); if (!errors.isEmpty()) return sendResponse(res, 400, "error", errors.array()[0].msg); next(); }; };
-
返回加密(在封装的返回数据进行加密):
const sendResponse = (res, statusCode, status, message, data = null) => { // 是否加密 let isEncryption = res.req.headers.isencryption; let response = { status, code: statusCode, message, data }; console.log("响应:", response); // 加密 if (isEncryption == "true") response = encrypt(JSON.stringify(response)); res.status(statusCode).json(response); };
-
注意:
- 前端需要设置请求头 isEncryption(可以自己任意定义判断是否加密)
- 前端需要设置请求头 Content-Type 为 'text/plain'
- 后端在 app.json 需要配置解析文本中间件:app.use(express.raw({ type: "text/plain" }));
- 加密解密需要自己封装