【Node.js】-实战:一个简单的仓储管理的原材入库模块

今天,我们着手做一个仓储管理,原材入库的模块,以实际的项目来进一步了解node.js,学以致用,反补理论知识。

工程结构

创建一个仓储管理的原材入库模块,使用Node.js作为后端服务,可以采用以下工程结构:

warehouse-management/
├── node_modules/           # 依赖的npm包
├── src/                    # 源代码目录
│   ├── controllers/        # 控制器目录
│   │   └── material.js     # 原材入库控制器
│   ├── models/             # 数据模型目录
│   │   └── material.js     # 原材入库模型
│   ├── routes/             # 路由目录
│   │   └── material.js     # 原材入库路由
│   ├── services/           # 服务目录
│   │   └── material.js     # 原材入库服务(如数据库操作)
│   ├── utils/              # 工具目录
│   │   └── ...             # 工具函数或类
│   ├── app.js              # 主应用文件
│   └── config/             # 配置目录
│       └── database.js     # 数据库配置文件
├── package.json            # 项目依赖和配置
├── .gitignore              # Git忽略文件
├── README.md               # 项目说明文档
└── ...                     # 其他可能需要的文件,如日志配置、测试文件等

以下是每个目录和文件的简单说明:

node_modules/

存放项目依赖的npm包。

src/

源代码目录,包含项目的所有核心代码。

controllers/

存放控制器文件,这些文件负责处理HTTP请求并返回响应。material.js 将处理与原材入库相关的请求。

models/

存放数据模型文件,这些文件定义了与数据库表对应的对象结构。material.js 将定义原材入库相关的数据模型。

routes/

存放路由文件,这些文件定义了URL路径与控制器方法的映射关系。material.js 将定义原材入库相关的路由。

services/

存放服务文件,这些文件包含与业务逻辑相关的代码,例如数据库操作、文件操作等。material.js 将包含与原材入库相关的数据库操作逻辑。

utils/

存放工具函数或类,这些函数或类在整个项目中可能都会被使用到。

app.js

主应用文件,用于初始化应用,设置中间件,加载路由等。

config/

存放配置文件,例如数据库配置、应用环境配置等。database.js 将包含数据库连接配置。

package.json

项目依赖和配置文件,包含项目名称、版本、描述、脚本命令、依赖项等信息。

.gitignore

Git忽略文件,指定哪些文件和目录不应被Git跟踪。

README.md

项目说明文档,包含项目的安装、使用、配置等说明。

其他文件

可能还包括日志文件配置、测试文件等,在这里我们先不配置,后期有需要再加。

大家注意,前期设计一个工程的时候要综合考虑投产比,并不一定是最全的就是最好的,最合适的才是最好的

工程代码

以下是基于上述工程结构,每个目录和文件中可能包含的代码:

src/controllers/material.js

javascript 复制代码
const MaterialService = require('../services/material');

class MaterialController {
  async createMaterial(req, res) {
    try {
      const material = await MaterialService.createMaterial(req.body);
      res.status(201).json(material);
    } catch (error) {
      res.status(500).json({ message: 'Error creating material' });
    }
  }

  // 可以添加其他与材料入库相关的控制器方法
}

module.exports = new MaterialController();

src/models/material.js

javascript 复制代码
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = require('../config/database');

const Material = sequelize.define('material', {
  materialCode: {
    type: DataTypes.STRING,
    allowNull: false,
    unique: true
  },
  description: {
    type: DataTypes.STRING,
    allowNull: false
  },
  quantity: {
    type: DataTypes.INTEGER,
    allowNull: false,
    defaultValue: 0
  },
  // 可以添加其他字段
}, {
  timestamps: true
});

module.exports = Material;

src/routes/material.js

javascript 复制代码
const express = require('express');
const router = express.Router();
const MaterialController = require('../controllers/material');

router.post('/materials', MaterialController.createMaterial);

// 可以添加其他与材料入库相关的路由

module.exports = router;

src/services/material.js

javascript 复制代码
const Material = require('../models/material');

class MaterialService {
  async createMaterial(materialData) {
    const material = await Material.create(materialData);
    return material;
  }

  // 可以添加其他与材料入库相关的服务方法
}

module.exports = new MaterialService();

src/app.js

javascript 复制代码
const express = require('express');
const bodyParser = require('body-parser');
const materialRoutes = require('./routes/material');

const app = express();

app.use(bodyParser.json());
app.use('/api', materialRoutes);

// 可以添加其他中间件和路由

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

src/config/database.js

javascript 复制代码
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'mysql', // 根据你的数据库类型选择 'mysql' | 'mariadb' | 'postgres' | 'mssql' 等
  logging: false // 在生产环境中,你可能想要禁用日志或将其记录到文件
});

module.exports = sequelize;

package.json

json 复制代码
{
  "name": "warehouse-management",
  "version": "1.0.0",
  "description": "Warehouse Management System - Material Inbound Module",
  "main": "src/app.js",
  "scripts": {
    "start": "node src/app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {
    "body-parser": "^1.19.0",
    "express": "^4.17.1",
    "sequelize": "^6.3.5" // 根据你的数据库类型安装相应的驱动,例如 'mysql2'
  },
  "devDependencies": {
    // 开发时需要的依赖项,例如测试工具等
  }
}

.gitignore

node_modules/
.env

README.md

Warehouse Management - Material Inbound Module

This is a module for managing the inbound materials in a warehouse

system.

注意事项

在上面的工程结构和代码中,有几个需要特别注意的注意事项:

目录和文件结构

  1. 模块化:确保每个目录和文件都遵循单一职责原则,即每个模块只做一件事情。这有助于代码的可维护性和可读性。

  2. 命名规范:文件名和目录名应该使用小写字母,多个单词之间可以使用短横线分隔。避免使用空格或特殊字符。

  3. 配置文件 :配置文件(如database.js)应该包含敏感信息(如数据库用户名和密码)的占位符,并在实际部署时通过环境变量或安全的方式提供这些值。

代码质量

  1. 错误处理 :确保所有的异步操作都有适当的错误处理逻辑。在上面的代码中,我们使用了try...catch块来捕获并处理可能发生的错误。

  2. 输入验证:在控制器层,应该验证所有来自客户端的输入数据,以确保其有效性和安全性。这可以通过使用中间件或直接在控制器方法中完成。

  3. 日志记录 :虽然示例代码中没有显式展示日志记录,但在实际开发中,记录重要的操作和错误信息是很有必要的。可以使用专门的日志库(如winstonpino)来实现。

安全性

  1. 防止SQL注入:使用ORM(对象关系映射)工具(如Sequelize)可以大大减少SQL注入的风险,因为它会自动处理查询的转义。但是,仍然需要小心处理用户输入,避免直接在SQL查询中拼接字符串。

  2. 保护敏感信息:不要在代码中硬编码敏感信息,如数据库凭据、API密钥等。这些信息应该通过环境变量或配置文件(确保配置文件不被公开)来提供。

  3. 中间件:使用中间件可以方便地处理跨多个路由的通用任务,如身份验证、授权、日志记录等。确保正确配置和使用中间件。

可扩展性和可维护性

  1. 代码注释:为代码添加适当的注释,解释每个函数、类和模块的作用和用法。这有助于其他开发者理解和维护代码。

  2. 测试:编写单元测试和功能测试以确保代码的正确性。这有助于在代码变更时快速发现并修复问题。

  3. 文档:为项目编写文档,包括API文档、系统使用说明等。这有助于其他开发者或用户了解和使用你的系统。

环境配置

  1. 环境变量:使用环境变量来配置不同环境(如开发、测试、生产)的设置。这可以避免在代码中直接包含这些配置,从而提高代码的可移植性和安全性。

  2. .gitignore :确保.gitignore文件正确配置,以避免将敏感信息或不必要的文件提交到版本控制系统中。

遵循这些注意事项将有助于创建一个健壮、可维护和安全的仓库管理系统模块。

敏感数据-数据库使用环境变量

敏感数据不能直接放在代码层的配置文件中,因为这样谁都可以看到了,是一个巨大的安全风险,要使用环境变量来配置不同环境,并在database.js中使用它们,你可以按照以下步骤操作:

1. 设置环境变量

首先,在你的系统上设置环境变量。这通常可以在操作系统的环境设置中进行,或者你可以在你的命令行界面中使用export命令(在Unix/Linux/macOS中)或set命令(在Windows中)。

例如,在Unix/Linux/macOS的bash shell中,你可以这样做:

bash 复制代码
export DATABASE_URL="mysql://username:password@localhost:3306/database_name"

在Windows的cmd中,你可以这样做:

cmd 复制代码
set DATABASE_URL=mysql://username:password@localhost:3306/database_name

或者,在Windows的PowerShell中:

powershell 复制代码
$env:DATABASE_URL="mysql://username:password@localhost:3306/database_name"

2. 在database.js中读取环境变量

在你的Node.js项目中,你可以使用process.env对象来访问环境变量。在你的database.js文件中,你可以这样做:

javascript 复制代码
const { Sequelize } = require('sequelize');

const sequelize = new Sequelize(
  process.env.DATABASE_URL, // 使用环境变量中的数据库连接字符串
  {
    dialectOptions: {
      // 在这里,你可以添加特定于数据库方言的选项,例如对于PostgreSQL的ssl选项
    },
    logging: console.log, // 或者设置为false来禁用日志,或者使用一个日志库
    // 其他Sequelize配置选项...
  }
);

module.exports = sequelize;

确保你的数据库连接字符串是正确格式的,并且与你所使用的数据库相匹配。上面的例子是一个通用的MySQL连接字符串格式。

3. 使用.env文件(可选)

为了更方便地管理环境变量,你可以使用.env文件来存储这些变量,特别是在开发环境中。然后,你可以使用dotenv库来加载这些变量。

首先,安装dotenv

bash 复制代码
npm install dotenv

然后,在你的项目根目录下创建一个.env文件,并添加你的环境变量:

DATABASE_URL=mysql://username:password@localhost:3306/database_name

在你的database.js(或任何启动脚本)文件的顶部,引入并使用dotenv

javascript 复制代码
require('dotenv').config();

// 现在你可以像之前一样使用process.env.DATABASE_URL了

请注意,.env文件应该不被版本控制系统(如Git)跟踪,所以确保在.gitignore文件中添加.env

4. 为不同环境配置不同的变量

对于不同的环境(开发、测试、生产),你可以创建不同的.env文件(例如.env.development.env.test.env.production),并在你的启动脚本中根据当前的环境加载相应的文件。

或者,你可以直接在命令行中设置不同的环境变量,并在你的CI/CD流程或部署脚本中管理它们。

确保在生产环境中,敏感信息(如数据库凭据)不会被硬编码在代码中,并且不会被公开或泄露。使用环境变量和.env文件是一种安全的做法,因为这些文件通常不会被包含在代码库中。

相关推荐
垣宇7 小时前
Vite 和 Webpack 的区别和选择
前端·webpack·node.js
爱吃南瓜的北瓜7 小时前
npm install 卡在“sill idealTree buildDeps“
前端·npm·node.js
翻滚吧键盘7 小时前
npm使用了代理,但是代理软件已经关闭导致创建失败
前端·npm·node.js
浪九天8 小时前
node.js的版本管理
node.js
浪九天10 小时前
node.js的常用指令
node.js
浪九天12 小时前
Vue 不同大版本与 Node.js 版本匹配的详细参数
前端·vue.js·node.js
小纯洁w1 天前
Webpack 的 require.context 和 Vite 的 import.meta.glob 的详细介绍和使用
前端·webpack·node.js
熬夜不洗澡1 天前
Node.js中不支持require和import两种导入模块的混用
node.js
bubusa~>_<1 天前
解决npm install 出现error,比如:ERR_SSL_CIPHER_OPERATION_FAILED
前端·npm·node.js
天下皆白_唯我独黑1 天前
npm 安装扩展遇到证书失效解决方案
前端·npm·node.js