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

本文将详细介绍如何使用 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 developmentres.locals.message = err.message;res.locals.error = req.app.get('env') === 'development' ? err : {};// render the error pageres.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"], //默认加密采用HS256credentialsRequired: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.mzph.cn/pingmian/78504.shtml

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

相关文章

如何实现Spring Boot应用程序的安全性:全面指南

在现代 Web 开发中,安全性是 Spring Boot 应用程序的核心需求,尤其是在微服务、云原生和公开 API 场景中。Spring Boot 结合 Spring Security 提供了一套强大的工具,用于保护应用程序免受常见威胁,如未经授权的访问、数据泄露、跨…

无人机避障——Mid360+Fast-lio感知建图+Ego-planner运动规划(胎教级教程)

电脑配置:Xavier-nx、ubuntu 18.04、ros melodic 激光雷达:Livox_Mid-360 结果展示:左边Mid360+Fast-lio感知建图,右边Ego-planner运动规划 1、读取雷达数据并显示 无人机避障——感知篇(采用Livox-Mid360激光雷达获取点云数据显示)-CSDN博客 看看雷达数据话题imu以及…

数据库证书可以选OCP认证吗?

直接回答:国内OCP认证持有者的年薪普遍在15万到40万元之间,具体收入与经验、地区和行业强相关。OCP认证能大幅提升求职竞争力,但薪资天花板仍由个人能力决定。 一、薪资范围和核心影响因素 OCP认证是Oracle数据库领域的中高级“技术通行证”…

MySQL 从入门到精通:第二篇 - 数据类型、约束与索引

1. MySQL数据类型详解 数值类型 整数类型 -- 常用整数类型及范围 CREATE TABLE integer_types (tiny_col TINYINT, -- 1字节,有符号(-128~127),无符号(0~255)small_col SMALLINT, -- 2字节,有符号(-32768~32767),无符号(0~65535)medium_col MEDIUMINT,

Arduino 入门学习笔记(二):开发环境搭建

Arduino 入门学习笔记(二):开发环境搭建 B站学习链接:link 1. Arduino IDE2软件介绍 Arduino IDE,Arduino Integrated Development Environment,即Arduino集成开发环境。 Arduino IDE具有程序编辑、调试…

ChatGPT、deepseek、豆包、Kimi、通义千问、腾讯元宝、文心一言、智谱清言代码能力对比

均使用测试时的最强模型 均是一次对话,对话内容一样 均开启深度思考 能联网的都联网了,但是作用不大,因为蓝桥杯刚考完,洛谷题目刚上传没多久 问题一测试了两遍 从问题三开始不再测试智谱清言(它思考时间太长了,前两个…

OCR之身份证识别

前言 OCR身份证识别是光学字符识别技术在身份证领域的应用。通过扫描或拍照获取身份证图像,利用图像处理、深度学习等技术,自动提取姓名、性别、民族、出生日期、地址、身份证号等信息,可大幅提升信息录入效率,广泛应用于政务、金…

线性代数—向量与矩阵的范数(Norm)

参考链接: 范数(Norm)——定义、原理、分类、作用与应用 - 知乎 带你秒懂向量与矩阵的范数(Norm)_矩阵norm-CSDN博客 什么是范数(norm)?以及L1,L2范数的简单介绍_l1 norm-CSDN博客 范数(Norm…

Java高频面试之并发编程-08

hello啊,各位观众姥爷们!!!本baby今天来报道了!哈哈哈哈哈嗝🐶 面试官:说说sleep和wait的区别? 1. 核心区别总结 特性sleep()wait()所属类Thread 类的静态方法Object 类的实例方法…

Spring-Ai-McpSever从外到内

MCP是什么 Model Context Protocol (MCP) 是一个开放协议,它使 LLM 应用与外部数据源和工具之间的无缝集成成为可能。无论你是构建 AI 驱动的 IDE、改善 chat 交互,还是构建自定义的 AI 工作流,MCP 提供了一种标准化的方式,将 LL…

ubuntu22.04 命令行修改静态ip

传统interfaces文件配置(适用于旧版)即便我们已经在桌面上配置了固定ip 这里也可以修改 ‌编辑配置文件‌ 修改/etc/network/interfaces(需安装net-tools): # interfaces(5) file used by ifup(8) and ifdown(8) # In…

计算机网络学习笔记 4-6章

第 4 章 网络层 【考纲内容】 (一)网络层的功能 异构网络互连;路由与转发;SDN 基本概念;拥塞控制 (二)路由算法 静态路由与动态路由;距离 - 向量路由算法&#xff1…

力扣hot100_子串_python版本

一、560. 和为 K 的子数组 思路:这就是一道典型的前缀和的题代码: class Solution:def subarraySum(self, nums: List[int], k: int) -> int:presum [0] * (len(nums) 1)for i, x in enumerate(nums):presum[i 1] presum[i] x # 前缀和序列需要n1个ans 0…

猿人学web端爬虫攻防大赛赛题第15题——备周则意怠-常见则不疑

解题步骤 1、观察抓的包 2、有个m参数,一看就是经过处理的,我们得知道m是如何组成的。看Initiator模块。 3、还是看request函数,往上一看就看到了m的赋值操作。 打断点,触发。 4、看下window.m()的定义 5、比较好理解的&#x…

rag增强检索-基于关键词检索的混合检索模式

1. 为什么在 RAG 里要用关键词检索? 向量检索(embedding-based retrieval)是找语义相近的内容,但有时候不够准确。比如用户问了具体人名、产品型号、年份,这类关键词强指向性的信息,用向量检索可能匹配不到最相关内容。**关键词检索(keyword-based retrieval)**可以直接…

纯真社区IP库离线版发布更新

纯真社区IP库离线版发布更新 发布者:技术分享 2005年,随着中国互联网的蓬勃发展,纯真IP库诞生了。作为全球网络空间地理测绘技术的领先者,纯真开源项目为中国互联网行业提供了高质量的网络空间IP库数据。纯真IP库目前已经覆盖超…

GitOps进化:深入探讨 Argo CD 及其对持续部署的影响

什么是 GitOps? 虽然软件开发生命周期的大部分已经实现自动化,但基础设施仍然在很大程度上依赖于人工,需要专业团队的参与。随着当今基础设施需求的不断增长,实施基础设施自动化变得越来越重要。现代基础设施需要具备弹性&#x…

通过示例学习:连续 XOR

通过示例学习:连续 XOR 如果我们想在 PyTorch 中构建神经网络,可以使用 (with) 指定所有参数(权重矩阵、偏差向量),让 PyTorch 计算梯度,然后调整参数。但是,如果我们有很…

百度Create大会深度解读:AI Agent与多模态模型如何重塑未来?

目录 百度Create大会亮点全解析:从数字人到Agent生态布局 数字人商业化:从"拟人"到"高说服力"的进化 Agent生态:从"心响"App看百度的Agent战略布局 "心响"App的技术架构与创新点 多模态大模型&a…

django filter 日期大于当前日期的

在Django中,如果你想要过滤出日期大于当前日期的记录,你可以使用Django的QuerySet API中的__gt(大于)操作符。这里是如何做到这一点的步骤: 确定你的模型:首先,确保你有一个模型(Mo…