【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 分钟前
已解决npm ERR! request to https://registry.npm.taobao.org/@vant%2farea-data failed
前端·npm·node.js
又写了一天BUG3 小时前
npm install安装缓慢及npm更换源
前端·npm·node.js
danplus5 小时前
node发送邮件:如何实现Node.js发信功能?
服务器·node.js·外贸开发信·邮件群发·蜂邮edm邮件营销·邮件接口·营销邮件
青稞儿5 小时前
面试题高频之token无感刷新(vue3+node.js)
vue.js·node.js
一个很帅的帅哥17 小时前
实现浏览器的下拉加载功能(类似知乎)
开发语言·javascript·mysql·mongodb·node.js·vue·express
Bang邦21 小时前
使用nvm管理Node.js多版本
前端·node.js·node多版本管理
新知图书21 小时前
Node.js快速入门
node.js
FakeOccupational1 天前
nodejs 007:错误npm error Error: EPERM: operation not permitted, symlink
前端·npm·node.js
亦舒.1 天前
JSDelivr & NPM CDN 国内加速节点
前端·npm·node.js
代码搬运媛1 天前
code eintegrity npm err sha512
前端·npm·node.js