使用 Node、Express 和 MongoDB 构建一个项目工程

news2025/4/27 9:41:54

本文将详细介绍如何使用 Node.js + Express + MongoDB 构建一个完整的 RESTful API 后端项目,涵盖:

  • 项目初始化

  • Express 服务器搭建

  • MongoDB 数据库连接

  • REST API 设计(CRUD 操作)

  • 错误处理与中间件

  • 源码结构与完整代码

  • 部署建议

一,Express 服务器搭建

1. 环境准备

1.1 安装必要工具

  • Node.js(建议 LTS 版本)

  • MongoDB(本地或 Atlas 云数据库)

  • 代码编辑器(如 VS Code)

  • Postman(API 测试)

1.2 初始化项目

mkdir node-express-mongodb-backend
cd node-express-mongodb-backend
npm init -y

2. 创建项目

express node-express-mongodb-backend

  • express:Web 框架

  • mongoose:MongoDB 对象建模

  • body-parser:解析请求体

  • cors:跨域支持

  • dotenv:环境变量管理

  • nodemon:开发热重载

3.更新项目依赖

npm install

{

  "name": "node-express-mongodb-backend",

  "version": "0.0.0",

  "private": true,

  "scripts": {

    "start": "node ./bin/www"

  },

  "dependencies": {

    "cookie-parser": "~1.4.4",

    "debug": "~2.6.9",

    "express": "~4.16.1",

    "http-errors": "~1.6.3",

    "jade": "~1.11.0",

    "morgan": "~1.9.1"

  }

}

4. 项目结构

NODE-EXPRESS-MONGODB-BACKEND/
├── bin/                            # 启动脚本
├── node_modules/         # 依赖库(npm install 生成)
├── public/                       # 静态资源(CSS/JS/图片)
├── routes/                      # 路由定义
├── views/                       # 前端模板(Jade/Pug)
├── app.js                        # 主应用入口文件
├── package.json            # 项目配置和依赖
└── package-lock.json     # 依赖版本锁定

5. 配置项目启动信息

// app.listen(端口号,服务器启动成功时调用的函数);
app.listen(3001,function(){
    console.log('服务器启动成功,端口号为3001');
});

删除app.js最后一行代码,替换成上述代码。端口占用可以修改端口号!

6.启动项目

node app.js

启动完成在终端会输出:服务器启动成功!端口号为3001

7.下载nodemon插件

目的是:为了让以后代码修改后,服务器自动启动。我们需要下载nodemon插件!

npm i nodemon -g

8.  启动项目

nodemon app.js

注意要是端口占用,直接手动修改端口号,直到命令行输出成功启动!

[nodemon] restarting due to changes...
[nodemon] starting `node app.js`
后端服务器启动,端口3001
[nodemon] restarting due to changes...
[nodemon] starting `node app.js`
后端服务器启动,端口3011

9.app .js代码的注释 (方便理解代码!)

/**
 * (1)引入项目中需要的模块
 */
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
// 处理项目中日志,第三方写好插件
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

//通过express创建一个对象。项目对象
var app = express();

// 后端配置页面,我们目前不需要
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

/**
 * 加载项目运行插件
 */
//配置日志环境
app.use(logger('dev'));
//前端发送json数据,后端可以接受
app.use(express.json());
//后端来处理请求地址。
app.use(express.urlencoded({ extended: false }));
//处理请求传递cookie信息
app.use(cookieParser());
//指定项目中public为静态资源 ,这个文件夹里面资源前端直接访问
app.use(express.static(path.join(__dirname, 'public')));

//配置路由
app.use('/', indexRouter);
app.use('/users', usersRouter);

// 配置404的访问结果
app.use(function(req, res, next) {
 next(createError(404));
});

// 后端报错,错误信息在这里处理
app.use(function(err, req, res, next) {
// set locals, only providing error in development
 res.locals.message = err.message;
 res.locals.error = req.app.get('env') === 'development' ? err : {};

// render the error page
 res.status(err.status || 500);
 res.render('error');
});

// module.exports = app;
// 启动服务器,监听3001端口
app.listen(3011,()=>{
 console.log("后端服务器启动,端口3011");
})

二,MongoDB 数据库下载及连接

MongoDB是一个分布式文件存储的非关系型数据库,适用于高并发读写、海量数据存储和高可扩展性的场景。本文详细介绍了MongoDB的安装、启动、连接方法,包括Windows和Linux环境,以及常用命令、数据类型、特点、复制集、备份还原等。同时,讲解了MongoDB的可视化工具Compass的使用,以及如何通过mongoose在Node.js中进行数据操作。

1.下载安装MongoDB

MongoDB官网:Download MongoDB Community Server | MongoDB

最后安装时将这个勾选去掉!!!

2.下载安装安装图形化界面软件Navicat

下载地址:https://dn.navicat.com.cn/download/navicat17_premium_lite_cs_x64.exe

3.Nodejs获取mongodb数据库的数据

(1)安装mongoose插件

npm i mongoose

(2)在项目种创建utils文件夹,里面创建db.js文件

const mongoose = require("mongoose");

const connectDB = async () => {
  try {
    await mongoose.connect("mongodb://127.0.0.1:27017/unmannedAerialVehiclePipelineInspection");
    console.log("MongoDB连接成功");
  } catch (error) {
    console.log("连接数据库失败:", error);
    process.exit(1); // 退出进程
  }
};

connectDB();

(3)找到app.js文件,引入db.js

// 处理项目中日志,第三方写好插件
var logger = require('morgan');

//路由请求之前,连接数据库
require("./utils/db")

(4) 启动MongoDB连接

提供一些方式:

首先在环境变量-用户变量中,新增 path  --->  D:\MongoDB\bin

方法一:配置文件方式启动服务
  1. 在MongoDB安装路径下,在bin同级新建conf文件夹;
  2. 在该文件中,用文件文档建立 mongod.conf文件
storage:
    #The directory where the mongod instance stores its data.Default Value is "\data\db" on Windows.
    dbPath: D:\MongoDB\data\db

dbPath的路径根据自己的路径来写!

方法二: Window 下安装 Mongodb 并设置为开机自启
  1. 在MongoDB文件下新建data 然后新建db    顺序是这样:D:\MongoDB\data\db
  2. MongoDB下新建文件夹 log(存放日志文件),并且在里面新建文件 mongodb.log
  3. 在MongoDB文件建立mongod.conf文本文档,内容如下:

systemLog:
    destination: file
    path: D:\MongoDB\log\mongod.log
    logAppend: true
storage:
    dbPath: D:\MongoDB\data\db
net:
    bindIp: 127.0.0.1
    port: 27017

      4.在D:\MongoDB\bin 路径下,启动cmd命令框,输入命令!

sc.exe create MongoDB binPath=D:\MongoDB\bin\mongod.exe\" --service --config=\"D:\MongoDB\mongod.cfg\"" DisplayName= "MongoDB" start= "auto"

      5. 启动完成后在任务管理器中可以看得

启动不成功!请参考以下文章!【亲身实践已解决】Windows无法启动MongoDB Server,错误:1053:服务没有及时响应启动或控制请求_错误1053 服务没有及时响应启动或控制请求-CSDN博客

三,后端MVC架构

项目根目录下文件

        routes文件夹--->users.js

        controllers文件夹--->UserController.js

        models文件夹--->UserModel_DB.js

四,Node后端身份验证

1.搭建身份认证环境   

(1)需要下载依赖引入jwt ;解决:生成token凭证

npm i jsonwebtoken express-jwt

# express-jwt这个中间件,目的就算为了验证token

(2)生成token

(3)UserController里面加入代码

const UserModel_DB = require("../models/UserModel_DB");
const Response = require("../utils/Response");
const Jwt = require("jsonwebtoken");
const { getEncAes128 } = require("../utils/crypto");

class usercontroller {
  /**
   * 所有用户
   */
  async alluser(req, res, next) {
    try {
      const data = await UserModel_DB.find();
      res.send(Response.success({ msg: "全部用户", data }));
    } catch (error) {
      console.log(error);
      res.send(Response.error({ msg: "数据传输失败" }));
    }
  }
  /**
   * 登录
   */
  async login(req, res, next) {
    try {
      const { username, password } = req.body;
      // 传递了一个对象,按照传递对象去数据筛选
      // 将password进行同样加密,将结果放在数据库中寻找
      const newPassword = getMD5(password);
      const data = await UserModel_DB.find({
        username: username,
        password: newPassword,
      });
      console.log(data);
      if (data.length) {
        //生成身份凭证
        //第一个参数生成保存用户自己信息,
        //第二个参数screct密钥
        //设置过期时间,以s作为单位
        const token = jwt.sign({ username }, "shuangxiangbabai", {
          expiresIn: 60 * 60,
        });

        res.send(Response.success({ data: "Bearer " + token }));
      } else {
        res.send(Response.error());
      }
    } catch (error) {
      console.log(error);
      res.send(Response.error({ msg: "服务器报错" }));
    }
  }
  /**
   * 注册
   */
  async register(req, res, next) {
    const { username, password, age, phone, avatar, gender } = req.body;
    if (username && password && age && phone && avatar && gender) {
      const result = getEncAes128(password);
      const data = await UserModel_DB.create({
        username,
        password: result,
        age,
        phone,
        avatar,
        gender,
      });
      if (data) {
        res.send(Response.success({ msg: "注册成功", data }));
      } else {
        res.send(Response.error({ msg: "注册失败" }));
      }
    } else {
      res.send(Response.error({ msg: "数据传输失败" }));
    }
  }
  /**
   * 修改密码
   */
  async fixpsd(req, res, next) {
    try {
      const { id, newpassword } = req.body;
      const result = getEncAes128(newpassword);
      const data = await UserModel_DB.updateOne(
        { _id: id },
        { password: result }
      );
      if (data.acknowledged) {
        res.send(Response.success({ msg: "修改成功", data }));
      } else {
        res.send(Response.error({ msg: "修改失败" }));
      }
    } catch (error) {
      console.log(error);
      res.send(Response.error({ msg: "数据传输失败" }));
    }
  }
  /**
   * 根据token验证用户
   */
  async UserInfo(req, res, next) {
    const token = req.get("Authorization");
    const obj = Jwt.verify(token.split(" ")[1], "baoyebabai");
    console.log(obj.username);
    const data = await UserModel_DB.find({ username: obj.username });
    console.log(data);
    res.send({ data });
  }
}

module.exports = new usercontroller();

2.服务端验证token

(1) 在utils文件夹下面创建jwt.js文件

// 引入的一个函数
const {expressjwt} = require("express-jwt")

//在进行token认证
const jwtAuth = expressjwt({
 secret:"shuangxiangbabai", //加密的密钥
 algorithms:["HS256"], //默认加密采用HS256
 credentialsRequired:true //true:不管请求有没有携带token,都需要验证,false:请求没有带token不验证
})

module.exports = jwtAuth

(2)需要在app.js中引入jwt.js文件并加载中间件

//引入jwt认证代码
const jwtAuth = require("./utils/jwt")

//指定项目中public为静态资源 ,这个文件夹里面资源前端直接访问
app.use(express.static(path.join(__dirname, 'public')));

//先验证token
app.use(jwtAuth)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2343947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++11】右值引用和移动语义:万字总结

📝前言: 这篇文章我们来讲讲右值引用和移动语义 🎬个人简介:努力学习ing 📋个人专栏:C学习笔记 🎀CSDN主页 愚润求学 🌄其他专栏:C语言入门基础,python入门基…

Python基于Django的全国二手房可视化分析系统【附源码】

博主介绍:✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇&…

VulnHub-DC-2靶机渗透教程

VulnHub-DC-2靶机渗透教程 1.靶机部署 [Onepanda] Mik1ysomething 靶机下载:https://download.vulnhub.com/dc/DC-2.zip 直接使用VMware导入打开就行 2.信息收集 2.1 获取靶机ip(arp-scan/nmap) arp-scan -l ​ nmap 192.168.135.0/24 2.2 详细信息扫描(nmap)…

n8n 中文系列教程_10. 解析n8n中的AI节点:从基础使用到高级Agent开发

在自动化工作流中集成AI能力已成为提升效率的关键。n8n通过内置的LangChain节点,让开发者无需复杂代码即可快速接入GPT-4、Claude等大模型,实现文本处理、智能决策等高级功能。本文将深入解析n8n的AI节点体系,从基础的Basic LLM Chain到强大的…

计算机网络 | 应用层(1)--应用层协议原理

💓个人主页:mooridy 💓专栏地址:《计算机网络:自定向下方法》 大纲式阅读笔记 关注我🌹,和我一起学习更多计算机的知识 🔝🔝🔝 目录 1. 应用层协议原理 1.1 …

MuJoCo 关节角速度记录与可视化,监控机械臂运动状态

视频讲解: MuJoCo 关节角速度记录与可视化,监控机械臂运动状态 代码仓库:GitHub - LitchiCheng/mujoco-learning 关节空间的轨迹优化,实际上是对于角速度起到加减速规划的控制,故一般来说具有该效果的速度变化会显得丝…

LVGL模拟器:NXP GUIDER+VSCODE

1. 下载安装包 NXP GUIDER:GUI Guider | NXP 半导体 CMAKE:Download CMake MINGW:https://github.com/niXman/mingw-builds-binaries/releases SDL2:https://github.com/libsdl-org/SDL/releases/tag/release-2.30.8 VSCODE&…

《USB技术应用与开发》第四讲:实现USB鼠标

一、标准鼠标分析 1.1简介 1.2页面显示 其中页面显示的“”不用管它,因为鼠标作为物理抓包,里面有时候会抓到一些错误,不一定是真正的通讯错误,很可能是本身线路接触质量不好等原因才打印出来的“”。 1.3按下鼠标左键 &#x…

一、鸿蒙编译篇

一、下载源码和编译 https://blog.csdn.net/xusiwei1236/article/details/142675221 https://blog.csdn.net/xiaolizibie/article/details/146375750 https://forums.openharmony.cn/forum.php?modviewthread&tid897 repo init -u https://gitee.com/openharmony/mani…

得物业务参数配置中心架构综述

一、背景 现状与痛点 在目前互联网飞速发展的今天,企业对用人的要求越来越高,尤其是后端的开发同学大部分精力都要投入在对复杂需求的处理,以及代码架构,稳定性的工作中,在对比下,简单且重复的CRUD就显得…

【算法】单词搜索、最短距离

单词搜索 这道题主要考察了深度优先遍历(DFS)算法。 我们通过几个简单例子来分析一些细节问题: 1. 要搜索的单词串:abc 搜索的过程中必须按照字母顺序,首先从矩阵中的第一个元素开始搜索,遇到字母a则开始深度优先遍历&#xff0…

Python函数基础:简介,函数的定义,函数的调用和传入参数,函数的返回值

目录 函数简介 函数定义,调用,传入参数,返回值 函数的定义 函数的调用和传入参数 函数的返回值 函数简介 函数简介:函数是组织好,可重复使用,用来实现特定功能(特定需求)的代码…

基于FFmpeg命令行的实时图像处理与RTSP推流解决方案

前言 在一些项目开发过程中需要将实时处理的图像再实时的将结果展示出来,此时如果再使用一张一张图片显示的方式展示给开发者,那么图像窗口的反复开关将会出现窗口闪烁的问题,实际上无法体现出动态画面的效果。因此,需要使用码流…

【随笔】地理探测器原理与运用

文章目录 一、作者与下载1.1 软件作者1.2 软件下载 二、原理简述2.1 空间分异性与地理探测器的提出2.2 地理探测器的数学模型2.21 分异及因子探测2.22 交互作用探测2.23 风险区与生态探测 三、使用:excel 一、作者与下载 1.1 软件作者 作者: DOI: 10.…

从零开始使用SSH链接目标主机(包括Github添加SSH验证,主机连接远程机SSH验证)

添加ssh密钥(当前机生成和远程机承认) 以下是从头开始生成自定义名称的SSH密钥的完整步骤(以GitHub为例,适用于任何SSH服务): 1. 生成自定义名称的SSH密钥对 # 生成密钥对(-t 指定算法,-f 指定路径和名称…

Maxscale实现Mysql的读写分离

介绍: Maxscale是mariadb开发的一个MySQL数据中间件,配置简单,能够实现读写分离,并且能根据主从状态实现写库的自动切换,对多个服务器实现负载均衡。 实验环境: 基于gtid的主从同步的基础上进行配置 中…

Spring Boot 启动生命周期详解

Spring Boot 启动生命周期详解 1. 启动阶段划分 Spring Boot 启动过程分为 4个核心阶段,每个阶段涉及不同的核心类和执行逻辑: 阶段 1:预初始化(Pre-initialization) 目标:准备启动器和环境配置关键类&am…

数据湖DataLake和传统数据仓库Datawarehouse的主要区别是什么?优缺点是什么?

数据湖和传统数据仓库的主要区别 以下是数据湖和传统数据仓库的主要区别,以表格形式展示: 特性数据湖传统数据仓库数据类型支持结构化、半结构化及非结构化数据主要处理结构化数据架构设计扁平化架构,所有数据存储在一个大的“池”中多层架…

解决conda虚拟环境安装包却依旧安装到base环境下

最近跑项目装包装到几度崩溃,包一直没有安装到正确位置,为此写下这篇文章记录一下,也希望能帮到有需要的人。(此文章开发环境为anaconda和window) 方法一 先conda deactivate,看到(base)消失…

字节跳动开源数字人模型latentsync1.5,性能、质量进一步优化~

项目背景 LatentSync1.5 是由 ByteDance 开发的一款先进的 AI 模型,专门针对视频唇同步(lip synchronization)任务设计,旨在实现音频与视频唇部动作的高质量、自然匹配。随着 AI 技术的快速发展,视频生成和编辑的需求…