32 KiB
32 KiB
Node Core Framework 使用说明
📋 概述
node-core-framework.js 是一个基于 Koa2 + Sequelize + MySQL 的企业级 Node.js 后端框架,提供了完整的 MVC 架构、数据库管理、API 文档生成、权限验证等功能。
🚀 快速开始
1. 环境要求
- Node.js: >= 16.0.0
- MySQL: >= 5.7
- Redis: >= 5.0 (可选,用于缓存)
2. 安装依赖
# 安装核心依赖
npm install koa koa-body koa-router koa-static koa2-cors koa2-swagger-ui
npm install sequelize mysql2 redis jsonwebtoken dayjs swagger-jsdoc
3. 基础使用
// app.js
const Framework = require('./dist/node-core-framework.js');
// 配置文件
const config = {
// 数据库配置
db: {
username: "your_username",
password: "your_password",
database: "your_database",
host: "localhost",
port: 3306,
dialect: "mysql",
timezone: '+08:00'
},
// Redis配置(可选)
redis: {
host: 'localhost',
port: 6379,
password: '',
db: 0
},
// 日志路径
logPath: './logs',
// 基础URL
baseUrl: 'http://localhost:3001',
// API路径配置
apiPaths: [
{
path: './controllers',
prefix: '/api',
authType: 'applet'
}
],
// 模型路径
modelPaths: './models',
// 允许的URL(无需认证)
allowUrls: [
'/api/users/login',
'/api/health',
'/api/docs'
],
// 授权文件路径
license: {
licensePath: './license.lic'
}
};
// 启动应用
async function startApp() {
try {
// 创建框架实例
const framework = await Framework.init(config);
// 启动服务器
const server = await framework.start(3001);
console.log('🎉 应用启动成功!');
console.log(`📚 API 文档: http://localhost:3001/api/docs`);
// 使用日志服务
const logsService = Framework.getServices().logsService;
logsService.log('应用启动成功', { port: 3001, time: new Date() });
} catch (error) {
console.error('❌ 启动失败:', error);
// 记录启动错误
const logsService = Framework.getServices().logsService;
logsService.error('应用启动失败', error);
}
}
startApp();
🏗️ 框架架构
核心组件
- Framework: 主框架类,负责整体协调
- ModelManager: 数据库模型管理器
- ServiceManager: 服务层管理器
- RequestManager: 请求处理器管理器
- RegistrationService: 授权验证服务
目录结构
project/
├── dist/
│ └── node-core-framework.js # 打包后的框架文件
├── controllers/ # 控制器目录
│ ├── user_controller.js
│ ├── article_controller.js
│ └── admin/
│ ├── sys_user.js # 系统用户管理
│ └── sys_log.js # 日志管理接口
├── models/ # 数据模型目录
│ ├── user.js
│ └── article.js
├── config.js # 配置文件
├── app.js # 应用入口
└── logs/ # 日志目录
├── log_2024.01.15.log # 普通日志文件
├── logError_2024.01.15.log # 错误日志文件
└── log_2024.01.15_1.log # 分割后的日志文件
📝 详细配置说明
数据库配置
const config = {
db: {
username: "root", // 数据库用户名
password: "password", // 数据库密码
database: "myapp", // 数据库名
host: "localhost", // 数据库主机
port: 3306, // 数据库端口
dialect: "mysql", // 数据库类型
timezone: '+08:00', // 时区
pool: { // 连接池配置
max: 10, // 最大连接数
min: 0, // 最小连接数
acquire: 30000, // 获取连接超时时间
idle: 10000 // 连接空闲时间
},
logging: true // 是否打印SQL日志
}
};
API路径配置
const config = {
apiPaths: [
{
path: './controllers', // 控制器目录路径
prefix: '/api', // API前缀
authType: 'applet' // 认证类型:applet | admin
},
{
path: './controllers_admin', // 管理端控制器
prefix: '/admin_api', // 管理端API前缀
authType: 'admin'
}
]
};
权限配置
const config = {
// 允许的URL(无需认证)
allowUrls: [
'/api/users/login', // 登录接口
'/api/users/register', // 注册接口
'/api/health', // 健康检查
'/api/docs', // API文档
'/api/swagger.json' // Swagger配置
],
// 授权文件路径
license: {
licensePath: './license.lic'
}
};
🎯 控制器开发
基础控制器结构
// controllers/user_controller.js
const { models } = require('../database/db');
module.exports = {
/**
* @swagger
* /api/users:
* get:
* summary: 获取用户列表
* description: 分页获取用户列表
* tags:
* - 用户管理
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* default: 1
* description: 页码
* - in: query
* name: pageSize
* schema:
* type: integer
* default: 20
* description: 每页数量
* responses:
* 200:
* description: 获取成功
*/
"GET /users": async (ctx) => {
const { user: UserModel } = models;
// 获取分页参数
const { limit, offset } = ctx.getPageSize();
// 查询用户列表
const users = await UserModel.findAndCountAll({
attributes: ['id', 'username', 'email', 'status', 'create_time'],
limit,
offset,
order: [['create_time', 'DESC']]
});
// 返回成功响应
ctx.success(users, '获取用户列表成功');
},
/**
* @swagger
* /api/users:
* post:
* summary: 创建用户
* description: 创建新用户
* tags:
* - 用户管理
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - username
* - email
* - password
* properties:
* username:
* type: string
* description: 用户名
* email:
* type: string
* format: email
* description: 邮箱
* password:
* type: string
* description: 密码
* responses:
* 200:
* description: 创建成功
*/
"POST /users": async (ctx) => {
const { user: UserModel } = models;
const { username, email, password } = ctx.getBody();
// 参数验证
if (!username || !email || !password) {
return ctx.fail('用户名、邮箱和密码不能为空');
}
// 检查邮箱是否已存在
const existingUser = await UserModel.findOne({ where: { email } });
if (existingUser) {
return ctx.fail('邮箱已存在');
}
// 创建用户
const newUser = await UserModel.create({
username,
email,
password,
status: 1
});
ctx.success({
id: newUser.id,
username: newUser.username,
email: newUser.email
}, '用户创建成功');
}
};
控制器方法说明
请求方法格式
框架支持 GET 和 POST 两种请求方法,推荐统一使用 POST 请求:
-
"POST /users": POST 请求(推荐)- 参数通过请求体传递:
{ id: 123, username: "张三", pageOption: { page: 1, pageSize: 20 } } - 适用场景:所有接口(查询、创建、更新、删除等)
- 优点:参数传递统一、支持复杂数据结构、更安全
- 参数通过请求体传递:
-
"GET /users": GET 请求(不推荐)- 参数通过查询字符串传递:
?id=123&status=1 - 仅在简单查询场景下使用
- 参数通过查询字符串传递:
上下文方法
// 获取请求体数据
const body = ctx.getBody();
// 获取查询参数
const query = ctx.getQuery();
// 获取分页参数(从前端的 pageOption 中获取 page 和 pageSize)
// 前端发送格式:{ pageOption: { page: 1, pageSize: 20 } }
// 返回值:{ limit: 20, offset: 0 }
const { limit, offset } = ctx.getPageSize();
// 成功响应
ctx.success(data, message);
// 失败响应
ctx.fail(message, code);
🗄️ 数据模型开发
模型定义
// models/user.js
const Sequelize = require('sequelize');
module.exports = (db) => {
return db.define("user", {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
comment: "用户ID"
},
username: {
type: Sequelize.STRING(50),
allowNull: false,
comment: "用户名"
},
email: {
type: Sequelize.STRING(100),
allowNull: false,
unique: true,
comment: "邮箱"
},
password: {
type: Sequelize.STRING(255),
allowNull: false,
comment: "密码"
},
avatar: {
type: Sequelize.STRING(255),
comment: "头像URL"
},
status: {
type: Sequelize.INTEGER,
defaultValue: 1,
comment: "状态:0-禁用,1-启用"
}
});
};
模型关联
// 在启动文件中定义关联关系
const businessAssociations = (models) => {
// 用户和文章的一对多关系
if (models.user && models.article) {
models.user.hasMany(models.article, {
foreignKey: 'author_id',
as: 'articles',
constraints: false // 不创建外键约束
});
models.article.belongsTo(models.user, {
foreignKey: 'author_id',
as: 'author',
constraints: false
});
}
};
// 在框架初始化时传入
const framework = await Framework.init({
// ... 其他配置
businessAssociations: businessAssociations
});
🔐 权限验证
Token 验证
框架支持两种认证类型:
applet: 小程序端认证admin: 管理端认证
认证中间件
// 在控制器中获取当前用户
"POST /profile": async (ctx) => {
// 获取当前登录用户信息
const currentUser = ctx.state.user;
if (!currentUser) {
return ctx.fail('未登录', 401);
}
ctx.success(currentUser, '获取用户信息成功');
}
📊 API 文档
Swagger 配置
框架自动生成 API 文档,访问地址:http://localhost:3001/api/docs
自定义 Schema
const config = {
customSchemas: {
"User": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "用户ID"
},
"username": {
"type": "string",
"description": "用户名"
},
"email": {
"type": "string",
"format": "email",
"description": "邮箱"
}
}
}
}
};
🚀 部署配置
生产环境配置
const config = {
env: 'production',
db: {
// 生产数据库配置
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
host: process.env.DB_HOST,
port: process.env.DB_PORT,
dialect: "mysql",
logging: false // 生产环境关闭SQL日志
},
redis: {
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT,
password: process.env.REDIS_PASSWORD
},
server: {
port: process.env.PORT || 3001,
host: '0.0.0.0'
}
};
PM2 部署
// ecosystem.config.js
module.exports = {
apps: [{
name: 'myapp',
script: 'app.js',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3001
}
}]
};
# 启动应用
pm2 start ecosystem.config.js
# 查看状态
pm2 status
# 查看日志
pm2 logs myapp
🔧 常用功能
日志服务
框架内置了完整的日志服务,支持普通日志、错误日志和请求日志记录。
获取日志服务
// 在控制器中获取日志服务
const Framework = require('./dist/node-core-framework.js');
const logsService = Framework.getServices().logsService;
#### 基本日志记录
```javascript
// 普通日志
logsService.log('用户登录成功', { userId: 123, username: 'admin' });
logsService.log('数据更新完成', '用户信息已更新');
// 错误日志
try {
// 业务逻辑
throw new Error('数据库连接失败');
} catch (error) {
logsService.error('数据库操作失败', error);
}
// 上下文错误日志(包含请求信息)
logsService.ctxError(error, ctx);
日志文件管理
// 日志文件自动管理
// - 按日期分割:log_2024.01.15.log
// - 错误日志:logError_2024.01.15.log
// - 文件大小超过5MB自动分割:log_2024.01.15_1.log
// - 自动创建日志目录
日志API接口
框架提供了日志管理的API接口:
// 获取所有日志文件列表
GET /admin_api/sys_log/all
// 查看日志文件内容
GET /admin_api/sys_log/detail?title=log_2024.01.15.log
// 删除指定日志文件
GET /admin_api/sys_log/delete?title=log_2024.01.15.log
// 删除所有日志文件
GET /admin_api/sys_log/delete_all
日志配置
const config = {
// 日志目录配置
logPath: './logs', // 相对路径,基于项目根目录
// 其他配置...
};
// 日志目录结构
// project/
// ├── logs/
// │ ├── log_2024.01.15.log # 普通日志
// │ ├── logError_2024.01.15.log # 错误日志
// │ └── log_2024.01.15_1.log # 分割后的日志
实际使用示例
// controller/user.js
const Framework = require('../framework');
const logsService = Framework.getServices().logsService;
module.exports = {
"POST /login": async (ctx) => {
try {
const { username, password } = ctx.getBody();
// 记录登录尝试
logsService.log('用户登录尝试', { username, ip: ctx.ip });
// 验证用户
const user = await UserModel.findOne({ where: { username } });
if (!user) {
logsService.log('登录失败:用户不存在', { username });
return ctx.fail('用户名或密码错误');
}
// 验证密码
const isValid = await bcrypt.compare(password, user.password);
if (!isValid) {
logsService.log('登录失败:密码错误', { username });
return ctx.fail('用户名或密码错误');
}
// 登录成功
logsService.log('用户登录成功', {
userId: user.id,
username: user.username,
ip: ctx.ip
});
ctx.success({ token: generateToken(user) }, '登录成功');
} catch (error) {
// 记录系统错误
logsService.ctxError(error, ctx);
ctx.fail('登录失败,请稍后重试');
}
}
};
Token服务
框架内置了JWT Token服务,支持Token生成、验证、解析和微信数据解密。
获取Token服务
// 在控制器中获取Token服务
const Framework = require('./dist/node-core-framework.js');
const tokenService = Framework.getServices().tokenService;
// 或者通过框架实例获取
const framework = await Framework.init(config);
const tokenService = Framework.getServices().tokenService;
基本Token操作
// 创建Token
const userInfo = { id: 123, username: 'admin', role: 'admin' };
const token = tokenService.create(userInfo);
// 解析Token(获取用户信息)
const userData = tokenService.parse(token);
console.log(userData); // { id: 123, username: 'admin', role: 'admin' }
// 验证Token(检查是否有效)
const isValid = tokenService.verify(token);
console.log(isValid); // true 或 false
微信数据解密
// 解密微信小程序数据
const encryptedData = 'encrypted_data_from_wechat';
const sessionKey = 'session_key_from_wechat';
const iv = 'iv_from_wechat';
const decryptedData = tokenService.decryptWxData(encryptedData, sessionKey, iv);
console.log(decryptedData); // 解密后的用户信息
MD5加密
// MD5加密
const password = '123456';
const encryptedPassword = tokenService.getMd5(password);
console.log(encryptedPassword); // e10adc3949ba59abbe56e057f20f883e
实际使用示例
// controller/auth.js
const Framework = require('../framework');
const tokenService = Framework.getServices().tokenService;
module.exports = {
"POST /login": async (ctx) => {
try {
const { username, password } = ctx.getBody();
// 验证用户
const user = await UserModel.findOne({ where: { username } });
if (!user) {
return ctx.fail('用户不存在');
}
// 验证密码
const isValidPassword = await bcrypt.compare(password, user.password);
if (!isValidPassword) {
return ctx.fail('密码错误');
}
// 生成Token
const userInfo = {
id: user.id,
username: user.username,
role: user.role
};
const token = tokenService.create(userInfo);
ctx.success({ token, user: userInfo }, '登录成功');
} catch (error) {
ctx.fail('登录失败');
}
},
"POST /verify": async (ctx) => {
const { token } = ctx.getBody();
if (!token) {
return ctx.fail('缺少Token');
}
const userData = tokenService.parse(token);
if (!userData) {
return ctx.fail('Token无效');
}
ctx.success(userData, 'Token验证成功');
}
};
Redis服务
框架内置了Redis缓存服务,支持数据缓存、分布式锁等功能。
获取Redis服务
// 在控制器中获取Redis服务
const Framework = require('./dist/node-core-framework.js');
const redisService = Framework.getServices().redisService;
// 或者通过框架实例获取
const framework = await Framework.init(config);
const redisService = Framework.getServices().redisService;
基本缓存操作
// 设置缓存(默认12小时过期)
await redisService.set('user:123', JSON.stringify({ name: '张三', age: 25 }));
// 设置缓存(自定义过期时间,单位:秒)
await redisService.set('session:abc', 'session_data', 3600); // 1小时
// 获取缓存
const userData = await redisService.get('user:123');
console.log(JSON.parse(userData)); // { name: '张三', age: 25 }
// 删除缓存
await redisService.del('user:123');
原子操作
// 原子设置(仅当key不存在时设置)
const success = await redisService.setIfAbsent('lock:order:123', 'locked', 300);
if (success) {
console.log('获取锁成功');
// 执行业务逻辑
await redisService.del('lock:order:123'); // 释放锁
} else {
console.log('获取锁失败,资源被占用');
}
连接状态管理
// 检查Redis连接状态
const isConnected = redisService.isConnected();
console.log('Redis连接状态:', isConnected);
// 手动重连
redisService.reconnect();
// 关闭连接
redisService.close();
实际使用示例
// controller/cache.js
const Framework = require('../framework');
const redisService = Framework.getServices().redisService;
module.exports = {
"POST /cache/user/detail": async (ctx) => {
const { id } = ctx.getBody(); // 从请求体获取 id
if (!id) {
return ctx.fail('用户ID不能为空');
}
const cacheKey = `user:${id}`;
try {
// 先尝试从缓存获取
let userData = await redisService.get(cacheKey);
if (userData) {
// 缓存命中
console.log('从缓存获取用户数据');
return ctx.success(JSON.parse(userData));
}
// 缓存未命中,从数据库获取
const user = await UserModel.findByPk(id);
if (!user) {
return ctx.fail('用户不存在');
}
// 存入缓存(1小时过期)
await redisService.set(cacheKey, JSON.stringify(user.toJSON()), 3600);
ctx.success(user);
} catch (error) {
ctx.fail('获取用户信息失败');
}
},
"POST /cache/clear": async (ctx) => {
const { pattern } = ctx.getBody();
// 清除指定模式的缓存
// 注意:这里需要根据实际需求实现模式匹配删除
await redisService.del(pattern);
ctx.success(null, '缓存清除成功');
}
};
Swagger服务
框架内置了Swagger API文档服务,支持自动生成API文档和Schema。
获取Swagger服务
// 在控制器中获取Swagger服务
const Framework = require('./dist/node-core-framework.js');
const swaggerService = Framework.getServices().createSwaggerService();
// 或者通过框架实例获取
const framework = await Framework.init(config);
const swaggerService = Framework.getServices().createSwaggerService();
生成API文档
// 生成Swagger规范
const swaggerSpec = swaggerService.generateSpecs(req, res);
// 获取Swagger配置
const swaggerConfig = swaggerService.generateSwaggerConfig(req, res);
// 获取Swagger选项
const swaggerOptions = swaggerService.getSwaggerOptions();
安全配置管理
// 获取当前安全配置
const securityConfig = swaggerService.getCurrentSecurityConfig(req, res);
// 更新安全配置
const newConfig = [
{ 'admin-token': [] },
{ 'applet-token': [] }
];
const result = swaggerService.updateSecurityConfig(req, res, newConfig);
// 清除安全配置
swaggerService.clearSecurityConfigCookie(res);
实际使用示例
// controller/docs.js
const Framework = require('../framework');
module.exports = {
"POST /api-docs": async (ctx) => {
const swaggerService = Framework.getServices().createSwaggerService();
// 生成Swagger规范
const swaggerSpec = swaggerService.generateSpecs(ctx.request, ctx.response);
ctx.response.type = 'application/json';
ctx.response.body = swaggerSpec;
},
"POST /swagger-ui": async (ctx) => {
// 返回Swagger UI页面
const swaggerUIManager = Framework.getSwaggerUIManager();
const html = swaggerUIManager.getSwaggerUIHTML();
ctx.response.type = 'text/html';
ctx.response.body = html;
}
};
平台项目服务
框架内置了平台项目服务,支持与外部平台的交互。
获取平台项目服务
// 在控制器中获取平台项目服务
const Framework = require('./dist/node-core-framework.js');
const platformService = Framework.getServices().platformProjectService;
// 或者通过框架实例获取
const framework = await Framework.init(config);
const platformService = Framework.getServices().platformProjectService;
基本平台操作
// 获取所有模型
const models = await platformService.modelAll();
// 生成表单
const formData = await platformService.formGenerate({ id: 'form_id' });
// 创建表单
const createResult = await platformService.createForm({
name: '用户表单',
fields: ['name', 'email', 'phone']
});
// 更新表单
const updateResult = await platformService.updateForm({
id: 'form_id',
name: '更新后的表单'
});
// 删除表单
const deleteResult = await platformService.delteForm({ id: 'form_id' });
// 重新生成模型
const modelResult = await platformService.modelGenerate({ id: 'model_id' });
文件下载
// 下载平台文件
const downloadResult = await platformService.downloadPlatformFile('/path/to/file');
实际使用示例
// controller/platform.js
const Framework = require('../framework');
const platformService = Framework.getServices().platformProjectService;
module.exports = {
"POST /platform/models": async (ctx) => {
try {
const models = await platformService.modelAll();
ctx.success(models);
} catch (error) {
ctx.fail('获取模型列表失败');
}
},
"POST /platform/form": async (ctx) => {
try {
const formData = ctx.getBody();
const result = await platformService.createForm(formData);
ctx.success(result, '表单创建成功');
} catch (error) {
ctx.fail('表单创建失败');
}
}
};
HTTP服务
框架内置了HTTP请求服务,支持各种HTTP请求方法。
获取HTTP服务
// 直接引入HTTP服务
const { postPlatformUrl, downloadPlatformFile, post, get } = require('./services/http');
基本HTTP操作
// GET请求
const getData = await get('https://api.example.com/users', { page: 1, limit: 10 });
// POST请求
const postData = await post('https://api.example.com/users', {
name: '张三',
email: 'zhangsan@example.com'
});
// POST表单数据
const formData = await postFormData('https://api.example.com/upload', {
file: 'file_content',
name: 'filename.jpg'
});
平台API调用
// 调用平台API
const platformData = await postPlatformUrl('/form/generate', { id: 'form_id' });
// 下载平台文件
await downloadPlatformFile('/path/to/file', './local/path/file');
实际使用示例
// controller/external.js
const { post, get } = require('../services/http');
module.exports = {
"POST /external/users": async (ctx) => {
try {
// 调用外部API
const users = await get('https://jsonplaceholder.typicode.com/users');
ctx.success(users);
} catch (error) {
ctx.fail('获取外部数据失败');
}
},
"POST /external/sync": async (ctx) => {
try {
const { data } = ctx.getBody();
// 同步数据到外部系统
const result = await post('https://api.external.com/sync', data);
ctx.success(result, '数据同步成功');
} catch (error) {
ctx.fail('数据同步失败');
}
}
};
分页查询
框架提供了 ctx.getPageSize() 方法来获取分页参数。
前端发送格式:
// 方式1: 通过 POST 请求体发送
{
pageOption: {
page: 1, // 页码,从1开始
pageSize: 20 // 每页数量
}
}
// 方式2: 通过 GET 查询参数发送
// GET /api/users?pageOption[page]=1&pageOption[pageSize]=20
后端使用示例:
"POST /users/list": async (ctx) => {
// ctx.getPageSize() 从前端的 pageOption 中获取 page 和 pageSize
// 返回值:{ limit: 20, offset: 0 }
// limit: 每页数量 (pageSize)
// offset: 跳过的记录数 ((page - 1) * pageSize)
const { limit, offset } = ctx.getPageSize();
const { username, status } = ctx.getBody(); // 从请求体获取查询条件
// 构建查询条件
const where = {};
if (username) {
where.username = { [Op.like]: `%${username}%` };
}
if (status !== undefined) {
where.status = status;
}
const users = await UserModel.findAndCountAll({
where,
limit,
offset,
order: [['create_time', 'DESC']]
});
ctx.success(users, '获取用户列表成功');
}
文件上传
"POST /upload": async (ctx) => {
const file = ctx.request.files.file;
if (!file) {
return ctx.fail('请选择文件');
}
// 处理文件上传逻辑
const fileName = `${Date.now()}_${file.name}`;
const filePath = `./upload/${fileName}`;
// 保存文件
const fs = require('fs');
fs.writeFileSync(filePath, file.buffer);
ctx.success({
fileName,
filePath,
size: file.size
}, '文件上传成功');
}
错误处理
// 全局错误处理
framework.app.on('error', (err, ctx) => {
console.error('服务器错误:', err);
// 记录错误日志
const logger = require('./services/logs');
logger.error('服务器错误', {
error: err.message,
stack: err.stack,
url: ctx.url,
method: ctx.method
});
});
📝 最佳实践
1. 控制器设计
// 好的实践:统一使用 POST 请求,清晰的路由命名
module.exports = {
"POST /users/list": getUserList, // 获取用户列表
"POST /users/detail": getUserDetail, // 获取用户详情
"POST /users/create": createUser, // 创建用户
"POST /users/update": updateUser, // 更新用户
"POST /users/delete": deleteUser // 删除用户
};
// 查询列表示例:支持分页和条件查询
async function getUserList(ctx) {
const { limit, offset } = ctx.getPageSize(); // 从 pageOption 获取分页参数
const { username, status } = ctx.getBody(); // 从请求体获取查询条件
// 构建查询条件
const where = {};
if (username) {
where.username = { [Op.like]: `%${username}%` };
}
if (status !== undefined) {
where.status = status;
}
const users = await UserModel.findAndCountAll({
where,
limit,
offset,
order: [['create_time', 'DESC']]
});
ctx.success(users, '获取用户列表成功');
}
// 查询详情示例
async function getUserDetail(ctx) {
const { id } = ctx.getBody(); // 从请求体获取 id
if (!id) {
return ctx.fail('用户ID不能为空');
}
const user = await UserModel.findByPk(id);
if (!user) {
return ctx.fail('用户不存在');
}
ctx.success(user, '获取成功');
}
// 创建示例
async function createUser(ctx) {
const { username, email, password } = ctx.getBody();
if (!username || !email || !password) {
return ctx.fail('用户名、邮箱和密码不能为空');
}
const newUser = await UserModel.create({ username, email, password });
ctx.success(newUser, '创建成功');
}
// 更新示例
async function updateUser(ctx) {
const { id, username, email } = ctx.getBody();
if (!id) {
return ctx.fail('用户ID不能为空');
}
await UserModel.update({ username, email }, { where: { id } });
ctx.success(null, '更新成功');
}
// 删除示例
async function deleteUser(ctx) {
const { id } = ctx.getBody();
if (!id) {
return ctx.fail('用户ID不能为空');
}
await UserModel.destroy({ where: { id } });
ctx.success(null, '删除成功');
}
2. 数据验证
// 好的实践:参数验证
"POST /users": async (ctx) => {
const { username, email, password } = ctx.getBody();
// 参数验证
if (!username || !email || !password) {
return ctx.fail('用户名、邮箱和密码不能为空');
}
// 邮箱格式验证
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
return ctx.fail('邮箱格式不正确');
}
// 业务逻辑...
}
3. 错误处理
// 好的实践:统一的错误处理
"POST /users": async (ctx) => {
try {
const { username, email, password } = ctx.getBody();
// 验证参数
validateUserInput({ username, email, password });
// 检查用户是否存在
await checkUserExists(email);
// 创建用户
const user = await createUser({ username, email, password });
ctx.success(user, '用户创建成功');
} catch (error) {
// 统一错误处理
if (error.code === 'VALIDATION_ERROR') {
return ctx.fail(error.message, 400);
}
if (error.code === 'USER_EXISTS') {
return ctx.fail(error.message, 409);
}
// 未知错误
console.error('创建用户失败:', error);
ctx.fail('服务器内部错误', 500);
}
}
❓ 常见问题
Q1: 数据库连接失败
解决方案:
- 检查数据库服务是否启动
- 验证配置文件中的数据库连接信息
- 确认数据库用户权限
Q2: 端口被占用
解决方案:
# 查看端口占用
netstat -ano | findstr :3001
# 终止进程
taskkill /PID <进程ID> /F
Q3: 模块找不到
解决方案:
# 重新安装依赖
npm install
# 清除缓存
npm cache clean --force
Q4: 权限验证失败
解决方案:
- 检查请求头中的 token
- 确认 token 格式正确
- 验证 token 是否过期
📚 更多资源
🎉 恭喜!你已经掌握了 Node Core Framework 的基本使用方法!
如有问题,请查看项目文档或提交 Issue。