# thinkEp **Repository Path**: damingstore/think-ep ## Basic Information - **Project Name**: thinkEp - **Description**: thinkEp是使用javascript编写的后端服务架构,主要使用node服务express框架进行封装,采用分层的思想进行封装,层次分明,架构清晰。是一个与主流后端语言架构更为接近的架构形式。 主要使用到以下技术: express (node框架) body-parser (解析post请求参数) nodemon (热启动刷新) sequelize (数据库orm操作) ... - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 0 - **Created**: 2022-07-03 - **Last Updated**: 2026-07-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # thinkEp thinkEp 是一个基于 Node.js + Express 的后端服务基础架构,目标是提供接近传统后端框架的分层开发体验。当前项目已经按大项目标准补充了配置管理、异常处理、统一响应、JWT 权限、Sequelize 模型关系、数据库迁移、访问日志、慢请求日志和请求 traceId。 ## 技术栈 - Express:HTTP 服务与中间件 - Sequelize + mysql2:ORM、模型关系、数据库访问 - Joi:参数验证 - jsonwebtoken:JWT 签发与校验 - log4js:文件日志、访问日志、慢请求日志、日志轮转 - express-session / redis:会话与缓存能力 - nodemailer:邮件发送 - formidable:文件上传 - qr-image / svg-captcha:二维码与验证码 ## 快速启动 ```bash npm install cp .env.example .env node server.js ``` 开发环境也可以使用: ```bash npm start ``` 数据库迁移: ```bash npm run db:migrate npm run db:migrate:down ``` ## 环境配置 配置优先从 `.env` 或部署平台密钥读取,敏感信息不要硬编码到 `config/*.js`。 当前提供: - `.env.example`:通用样例 - `.env.development.example`:开发环境样例 - `.env.test.example`:测试环境样例 - `.env.production.example`:生产环境样例 主要配置分组: - `[app]`:应用名称、环境、端口、debug、请求 ID header - `[database]`:数据库连接、连接池、时区、日志 - `[jwt]`:JWT secret、算法、issuer、audience、过期时间 - `[session]`:session secret 与 cookie 配置 - `[cache]`:统一缓存驱动、key 前缀、默认 TTL - `[security]`:CORS 配置 - `[log]`:日志目录、级别、访问日志、慢请求、轮转策略 - `[redis]`:Redis 连接 - `[email]`:邮件服务配置 部署平台也可以使用扁平环境变量,例如 `JWT_SECRET`、`DATABASE_PASSWORD`。 ## 目录结构 ```text think-ep/ ├── app/ # 业务模块 │ ├── index/ │ │ ├── controller/ │ │ ├── dao/ │ │ ├── middleware/ │ │ ├── service/ │ │ └── validate/ │ └── test/ │ ├── controller/ │ ├── dao/ │ ├── middleware/ │ ├── service/ │ └── validate/ ├── config/ # 配置文件 ├── core/ # 框架核心封装,不参与具体业务逻辑 │ ├── basic/ # BaseDao/BaseService/BaseValidate │ ├── caches/ │ ├── database/ # MigrationRunner │ ├── exceptions/ # 统一异常 │ ├── lib/ │ ├── logs/ │ └── services/ # 通用服务 ├── database/migrations/ # 数据库迁移 ├── model/ # Sequelize 模型与关系 ├── public/ # 静态资源 ├── route/ # 路由文件,启动时自动加载 ├── runtime/logs/ # 运行日志 ├── scripts/ # 脚本 ├── server.js # 入口 └── README.md ``` ## 分层规范 `core` 只做基础能力封装,不写业务逻辑。业务代码放在 `app/{module}` 下。 推荐调用链: ```text route -> middleware -> validate -> controller -> service -> dao -> model ``` - `controller`:只处理请求参数、调用 service、返回响应 - `service`:编排业务逻辑,可调用 dao、缓存、第三方服务 - `dao`:封装数据库查询 - `validate`:参数验证 - `middleware`:认证、权限、模块级前置处理 - `model`:Sequelize 模型定义 `app` 下文件使用大驼峰命名,例如 `TestController.js`、`TestService.js`、`IndexDao.js`。 ## 统一缓存 统一缓存入口位于 `core/caches/CacheHelper.js`,启动时会挂载到 `global.Cache`。业务代码优先使用 `global.Cache`,不直接依赖 Redis 或内存驱动。 ```js await global.Cache.set('user:1', { id: 1, name: 'test' }, 3600); const user = await global.Cache.get('user:1'); await global.Cache.del('user:1'); const config = await global.Cache.remember('site:config', 600, async () => { return await loadConfigFromDb(); }); ``` 在独立脚本或未经过 `core/run.js` 初始化的场景,也可以直接引入: ```js const CacheHelper = require('./core/caches/CacheHelper'); ``` 支持方法,均可通过 `global.Cache` 调用: - `global.Cache.set(key, value, ttl, nx)`:设置缓存,`ttl` 单位秒,`nx=true` 表示 key 不存在时才写入 - `global.Cache.get(key, defaultValue)`:读取缓存 - `global.Cache.del/delete/forget(key)`:删除缓存 - `global.Cache.has(key)`:判断缓存是否存在 - `global.Cache.ttl(key)`:查看剩余过期时间 - `global.Cache.clear()`:清空当前缓存前缀下的数据 - `global.Cache.remember(key, ttl, callback)`:缓存存在时直接返回,不存在时执行回调并写入缓存 - `global.Cache.forever(key, value)`:永久缓存 缓存配置: ```ini [cache] type = memory prefix = think-ep:cache: default_ttl = 0 ``` 说明: - `type = memory`:使用进程内存缓存,适合开发、测试和单实例场景。 - `type = redis`:使用 Redis 缓存,适合生产、多实例部署。 - `session` 配置只用于 Express session,不作为统一缓存驱动。 ## 统一响应 项目已统一普通 JSON 响应出口,挂载位置在 `core/run.js`: ```js app.use(ResponseService) ``` Controller 中统一使用: ```js return res.success(data) return res.fail('请求失败') return res.reply(serviceResult) ``` 响应格式: ```json { "status": 200, "code": 0, "msg": "请求成功", "data": {}, "requestId": "trace-id" } ``` 说明: - 旧的 `res.resSuccess`、`res.resFail` 不再作为标准接口使用。 - 业务成功使用 `code = 0`。 - 业务失败使用 `InteriorCodeService` 中的业务码。 - HTTP 状态码和业务码分离。 - 文件流、图片流等二进制响应不强制包 JSON。 ## 错误码与异常 业务码统一维护在 `core/services/InteriorCodeService.js`。 常用业务码: - `REQUEST_OK = 0`:请求成功 - `REQUEST_FAIL = 1`:请求失败 - `INVALID_PARAMS = 1005`:参数错误 - `DATA_NOT_FOUND = 1007`:数据不存在 - `DB_ERROR = 1008`:数据库异常 - `PERMISSION_DENIED = 1013`:权限不足 - `CONFIG_ERROR = 1014`:配置错误 - `SYSTEM_ERROR = 9999`:系统错误 异常统一由 `core/exceptions/CustomExceptionHandle.js` 处理,返回结构与普通响应保持一致,并包含 `requestId`。debug 模式下会在 `meta` 中返回错误名和堆栈。 ## 认证与权限 JWT 配置在 `config/jwt.js`,敏感密钥必须来自 `.env` 或部署平台密钥。 `app/test/middleware/AuthMiddleware.js` 已升级为真正的 JWT 校验: - 解析 Bearer token - 校验签名、issuer、audience、过期时间 - 将用户信息挂载到 `req.user` - 支持角色权限判断 - 支持权限点判断 ## 数据库模型与迁移 模型位于 `model/`,关系统一维护在 `model/associations.js`。 当前包含: - `user` - `blog` - `chapter` - `type` - `tag` - `blogTag` - `comment` 迁移入口: ```bash npm run db:migrate npm run db:migrate:down ``` 迁移文件位于 `database/migrations/`,迁移状态由 `MigrationRunner` 记录,避免生产环境直接依赖 `sequelize.sync()`。 ## 日志与监控 当前日志能力: - 错误日志 - 请求访问日志 - 慢请求日志 - traceId/requestId 聚合 - 敏感字段脱敏 - 按天滚动日志 - 日志保留天数配置 - 可选 gzip 压缩 - 可配置忽略路径,例如 `/favicon.ico,/health` 日志配置: ```ini [log] dir = runtime/logs level = info console = true close = false max_files = 30 compress = false access = true slow = true slow_threshold = 1000 ignore_paths = /favicon.ico,/health ``` 日志文件分类: - `access.*.log` - `slow.*.log` - `error.*.log` - `info.*.log` - `debug.*.log` - `fatal.*.log` ## 路由示例 ```js const router = require('express').Router(); const AsyncHandler = require('../core/exceptions/AsyncHandler'); const TestController = require('../app/test/controller/TestController'); const AuthMiddleware = require('../app/test/middleware/AuthMiddleware'); const TestValidate = require('../app/test/validate/TestValidate'); router.get('/test/get', AsyncHandler([ AuthMiddleware.auth, TestValidate.add, TestController.testGet, ])); module.exports = router; ``` ## 开发约定 - `core` 不参与业务逻辑。 - `controller` 不写复杂业务,只负责调用 service 和响应。 - `service` 可以返回普通数据,也可以返回 `BaseService.success/fail` 的标准结果。 - 业务错误优先抛自定义异常,由异常中间件统一处理。 - 不在代码中硬编码密钥、账号、密码。 - Linux 环境大小写敏感,文件引用必须与真实文件名一致。 - 新增接口默认返回统一 JSON 结构。 ## 后续优化方向 - 补充单元测试与接口测试。 - 增加健康检查和指标上报接口。 - 完善生产级 Redis 缓存封装。 - 补充 RBAC 权限模型与数据库表。 - 引入 API 文档生成。 - 完善 CI 中的 Linux 启动校验、迁移校验和 lint。