Node.js后端构建指南:MongoDB与Express的集成

安装express

安装 Express 并将其保存到依赖列表中:

$ cnpm install express --save

以上命令会将 Express 框架安装在当前目录的 node_modules 目录中, node_modules 目录下会自动创建 express 目录。以下几个重要的模块是需要与 express 框架一起安装的:

  • body-parser - node.js 中间件,用于处理 JSON, Raw, Text 和 URL 编码的数据。
  • cookie-parser - 这就是一个解析Cookie的工具。通过req.cookies可以取到传过来的cookie,并把它们转成对象。
  • multer - node.js 中间件,用于处理 enctype="multipart/form-data"(设置表单的MIME编码)的表单数据。

安装完后,我们可以查看下 express 使用的版本号:

$ cnpm list express
/data/www/node
└── express@4.15.2  -> /Users/tianqixin/www/node/node_modules/.4.15.2@express

express项目架构

Express项目的架构可以根据具体需求和规模的不同而有所不同,但通常遵循一些基本的组织原则。以下是一个常见的Express项目架构示例:

  1. 根目录结构
    • app.js  或  server.js :Express应用程序的入口文件,包含应用程序的配置和启动代码。
    • package.json :包含项目的依赖项和脚本配置。
    • node_modules/ :存放项目依赖的Node.js模块。
    • public/ :存放静态文件(如CSS、JavaScript、图片等)。
    • views/ :存放视图模板文件(如EJS、Pug等)。
  1. 路由结构
    • routes/ 目录:存放路由文件,可根据功能或模块划分子路由文件。
    • app.js 中设置路由:在 app.js 中通过 app.useapp.get 等方法将路由文件引入并设置路由路径。
  1. 中间件
    • middlewares/ 目录:存放自定义中间件函数。
    • app.js 中使用中间件:在 app.js 中通过 app.use 方法使用中间件。
  1. 控制器
    • controllers/ 目录:存放路由处理函数,负责处理请求并返回响应。
    • 与路由文件分离:控制器文件应与路由文件分离,遵循单一职责原则。
  1. 模型
    • models/ 目录:存放数据模型定义和数据库操作。
    • 与控制器分离:模型文件应与控制器文件分离,负责数据操作和业务逻辑。
  1. 配置
    • config/ 目录:存放配置文件,如数据库配置、环境变量等。
    • 环境变量:使用 .env 文件存放敏感信息,并通过 dotenv 模块加载。
  1. 错误处理
    • 错误处理中间件:编写统一的错误处理中间件,处理应用程序中发生的错误。
  1. 测试
    • tests/ 目录:存放单元测试和集成测试文件,使用测试框架进行测试。

以上是一个基本的Express项目架构示例,你可以根据具体项目需求和规模进行调整和扩展。

创建一个express示例


var express = require('express');
var app = express();
 
app.get('/', function (req, res) {
   res.send('Hello World');
})
 
var server = app.listen(8081, function () {
 
  var host = server.address().address
  var port = server.address().port
 
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
 
})

请求和响应

Express 应用使用回调函数的参数: requestresponse 对象来处理请求和响应的数据。

app.get('/', function (req, res) {
  // --
})
app.post('/',(req,res)=>{})

requestresponse 对象的具体介绍:

Request 对象 - request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性。常见属性有:

  1. req.app:当callback为外部文件时,用req.app访问express的实例
  2. req.baseUrl:获取路由当前安装的URL路径
  3. req.body / req.cookies:获得「请求主体」/ Cookies
  4. req.fresh / req.stale:判断请求是否还「新鲜」
  5. req.hostname / req.ip:获取主机名和IP地址
  6. req.originalUrl:获取原始请求URL
  7. req.params:获取路由的parameters
  8. req.path:获取请求路径
  9. req.protocol:获取协议类型
  10. req.query:获取URL的查询参数串
  11. req.route:获取当前匹配的路由
  12. req.subdomains:获取子域名
  13. req.accepts():检查可接受的请求的文档类型
  14. req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages:返回指定字符集的第一个可接受字符编码
  15. req.get():获取指定的HTTP请求头
  16. req.is():判断请求头Content-Type的MIME类型

Response 对象 - response 对象表示 HTTP 响应,即在接收到请求时向客户端发送的 HTTP 响应数据。常见属性有:

  1. res.app:同req.app一样
  2. res.append():追加指定HTTP头
  3. res.set()在res.append()后将重置之前设置的头
  4. res.cookie(name,value [,option]):设置Cookie
  5. opition: domain / expires / httpOnly / maxAge / path / secure / signed
  6. res.clearCookie():清除Cookie
  7. res.download():传送指定路径的文件
  8. res.get():返回指定的HTTP头
  9. res.json():传送JSON响应
  10. res.jsonp():传送JSONP响应
  11. res.location():只设置响应的Location HTTP头,不设置状态码或者close response
  12. res.redirect():设置响应的Location HTTP头,并且设置状态码302
  13. res.render(view,[locals],callback):渲染一个view,同时向callback传递渲染后的字符串,如果在渲染过程中有错误发生next(err)将会被自动调用。callback将会被传入一个可能发生的错误以及渲染后的页面,这样就不会自动输出了。
  14. res.send():传送HTTP响应
  15. res.sendFile(path [,options] [,fn]):传送指定路径的文件 -会自动根据文件extension设定Content-Type
  16. res.set():设置HTTP头,传入object可以一次设置多个头
  17. res.status():设置HTTP状态码
  18. res.type():设置Content-Type的MIME类型

路由

我们已经了解了 HTTP 请求的基本应用,而路由决定了由谁(指定脚本)去响应客户端请求。

在HTTP请求中,我们可以通过路由提取出请求的URL以及GET/POST参数。

接下来我们扩展 Hello World,添加一些功能来处理更多类型的 HTTP 请求。

创建 express_demo2.js 文件,代码如下所示:

var express = require('express');
var app = express();
 
//  主页输出 "Hello World"
app.get('/', function (req, res) {
   console.log("主页 GET 请求");
   res.send('Hello GET');
})
 
 
//  POST 请求
app.post('/', function (req, res) {
   console.log("主页 POST 请求");
   res.send('Hello POST');
})
 
//  /del_user 页面响应
app.get('/del_user', function (req, res) {
   console.log("/del_user 响应 DELETE 请求");
   res.send('删除页面');
})
 
//  /list_user 页面 GET 请求
app.get('/list_user', function (req, res) {
   console.log("/list_user GET 请求");
   res.send('用户列表页面');
})
 
// 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求
app.get('/ab*cd', function(req, res) {   
   console.log("/ab*cd GET 请求");
   res.send('正则匹配');
})
 
 
var server = app.listen(8081, function () {
 
  var host = server.address().address
  var port = server.address().port
 
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
 
})

app.use

在Express中, `app.use` 函数用于将中间件函数绑定到应用程序的特定路径。中间件函数可以访问请求对象(req)、响应对象(res)和应用程序中的下一个中间件函数(next)。通过使用 `app.use` ,可以在请求到达特定路径之前或之后执行一些操作,例如记录日志、验证用户身份、处理请求等。

const express = require('express');
const app = express();

// 自定义的日志记录中间件函数
const logMiddleware = (req, res, next) => {
  console.log(`[${new Date().toLocaleString()}] - ${req.method} ${req.url}`);
  next();
};

// 将日志记录中间件绑定到应用程序的根路径
app.use(logMiddleware);

// 路由处理程序
app.get('/', (req, res) => {
  res.send('Hello World!');
});

// 启动服务器
app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

托管静态资源

app.use(express.static('./public'));

url里面不需要带有public

http://localhost:8081/public.jpg

有两个资源,按照引入顺序

app.use('/public',express.static('./public'));

中间件

全局生效中间件

var express = require('express');
var app = express();
const ww=function(req,res,next){
    console.log(18948);
    next()
}
app.use(ww)
app.get('/',(req,res)=>{
    console.log('over');
})
var server = app.listen(8081, function () {
 
  var host = server.address().address
  var port = server.address().port
 
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
 
})

局部生效中间件

var express = require('express');
var app = express();
const ww=function(req,res,next){
    req.a=1598
    next()
}
app.get('/',ww,(req,res)=>{
    res.send('over',req.a);
})
app.get('/55',(req,res)=>{
    res.send('over1',req.a);
})
var server = app.listen(8081, function () {
 
  var host = server.address().address
  var port = server.address().port
 
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
 
})

错误全局中间件

var express = require('express');
var app = express();
app.get('/',(req,res)=>{
    throw new Error('服务器错误')
    res.send('home')
})
app.use(function(err,req,res,next) {
    res.send('Error'+err.message)
})
var server = app.listen(8081, function () {
 
  var host = server.address().address
  var port = server.address().port
 
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
 
})

目的

防止整个项目崩溃

位置

必须放在所以的路由之后

内置中间件

注意事项

解析表单

html:

<html>
<body>
<form action="http://127.0.0.1:8081/process_post" method="POST">
First Name: <input type="text" name="first_name">  <br>
 
Last Name: <input type="text" name="last_name">
<input type="submit" value="Submit">
</form>
</body>
</html>

node:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
 

app.use(express.json())
 
app.get('/index.html', function (req, res) {
   res.send(req.body)
})

 
var server = app.listen(8081, function () {
 
  var host = server.address().address
  var port = server.address().port
 
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
 
})

文件上传

以下我们创建一个用于上传文件的表单,使用 POST 方法,表单 enctype 属性设置为 multipart/form-data。

html:

<html>
<head>
<title>文件上传表单</title>
</head>
<body>
<h3>文件上传:</h3>
选择一个文件上传: <br />
<form action="/file_upload" method="post" enctype="multipart/form-data">
<input type="file" name="image" size="50" />
<br />
<input type="submit" value="上传文件" />
</form>
</body>
</html>

node:

var express = require('express');
var app = express();
var fs = require("fs");

var bodyParser = require('body-parser');
var multer  = require('multer');

app.use('/public', express.static('public'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(multer({ dest: '/tmp/'}).array('image'));

app.get('/index.html', function (req, res) {
  res.sendFile( __dirname + "/" + "index.html" );
})

app.post('/file_upload', function (req, res) {

  console.log(req.files[0]);  // 上传的文件信息

  var des_file = __dirname + "/" + req.files[0].originalname;
  fs.readFile( req.files[0].path, function (err, data) {
    fs.writeFile(des_file, data, function (err) {
      if( err ){
        console.log( err );
      }else{
        response = {
          message:'File uploaded successfully', 
          filename:req.files[0].originalname
        };
      }
      console.log( response );
      res.end( JSON.stringify( response ) );
    });
  });
})

var server = app.listen(8081, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("应用实例,访问地址为 http://%s:%s", host, port)

})

项目

路由模块化

router.js

const express=require('express');
// 创建路由对象
const router =express.Router()


router.get('/',(req,res)=>{
    res.send('hello world')
})
module.exports=router;

server.js

var express = require('express');
const router = require('./router.js');
var app = express();
 
app.use('/public',express.static('public'));
app.use(router)
var server = app.listen(8081, function () {
 
  var host = server.address().address
  var port = server.address().port
 
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
 
})

url添加统一地址

app.use('/user',router)

连接MongoDB

要使用MongoDB,您需要安装MongoDB数据库,并且可以使用MongoDB的官方驱动程序或者第三方库(如Mongoose)来与数据库进行交互。以下是使用MongoDB的基本步骤:

  1. 安装MongoDB数据库:您可以从MongoDB的官方网站(https://www.mongodb.com/)下载适合您操作系统的安装程序,并按照安装指南进行安装。
  2. 启动MongoDB服务:安装完成后,启动MongoDB服务。在命令行中输入  mongod (或  sudo mongod )来启动MongoDB服务。
  3. 连接到MongoDB数据库:在另一个命令行窗口中输入  mongo  命令来连接到MongoDB数据库。

修改这3个能够远程访问

检验:ip:27017

  1. 使用MongoDB Shell:通过MongoDB Shell,您可以执行各种数据库操作,如创建数据库、创建集合、插入文档、查询文档等。以下是一些常用的MongoDB Shell命令:
    • 创建数据库: use database_name
    • 创建集合: db.createCollection('collection_name')
    • 插入文档: db.collection_name.insertOne({ key: value })
    • 查询文档: db.collection_name.find()
  1. 使用Node.js与MongoDB交互:如果您想在Node.js应用程序中使用MongoDB,可以使用MongoDB的官方Node.js驱动程序或者像Mongoose这样的库。以下是使用Mongoose库的简单示例:
const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/mydatabase', { useNewUrlParser: true, useUnifiedTopology: true });

const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
  console.log("Connected to MongoDB");
});

// 定义模式和模型
const Schema = mongoose.Schema;
const userSchema = new Schema({
  name: String,
  age: Number
});
const User = mongoose.model('User', userSchema);

// 创建文档
const newUser = new User({ name: 'Alice', age: 30 });
newUser.save(function (err) {
  if (err) return console.error(err);
  console.log("User saved successfully!");
});

定义模式和模型(类似于ts的interface定义)

在使用Mongoose这样的库时,定义模式和模型是非常重要的步骤,用于帮助您在Node.js应用程序中与MongoDB数据库进行交互。让我来解释一下这两个概念的含义:

  1. 定义模式(Schema):模式是用来定义MongoDB文档结构的一种方式,类似于表结构的定义。在Mongoose中,您可以通过定义模式来规定文档中包含的字段、字段类型、默认值等信息。模式定义了文档的结构,类似于一个数据模板,确保文档符合特定的结构和规范。
    例如,您可以定义一个用户模式(User Schema),包含姓名(name)和年龄(age)两个字段:
const userSchema = new Schema({
name: String,
age: Number
}); 
  1. 定义模型(Model):模型是基于模式创建的构造函数,用于对数据库进行操作。在Mongoose中,您可以通过定义模型来创建具体的文档实例,以便对数据库进行增删改查操作。模型是模式的实例化,它允许您在应用程序中使用模式定义的字段和规范。
    通过使用上面定义的用户模式,您可以创建一个用户模型(User Model):
const User = mongoose.model('User', userSchema);

现在,您可以使用User模型来创建新的用户文档、查询用户数据、更新用户信息等操作。

通过定义模式和模型,您可以规范化数据结构、提供数据验证、简化数据库操作等。这些概念帮助您在Node.js应用程序中更好地与MongoDB数据库进行交互,并更有效地管理数据。

在路由中使用

要在Express应用程序的路由中使用Mongoose模型(即在路由处理程序中与MongoDB数据库进行交互),可以按照以下步骤进行操作:

  1. 引入Mongoose模型:首先,在您的Express应用程序中,确保已经引入了Mongoose模型。通常,您会在单独的文件中定义模型,并在需要的地方引入该模型。
const User = require('./models/user'); // 假设User模型定义在models/user.js文件中
  1. 在路由处理程序中使用Mongoose模型:在您的路由处理程序中,您可以通过Mongoose模型执行数据库操作,如查询、插入、更新、删除等操作。以下是一个简单的示例
const express = require('express');
const router = express.Router();
const User = require('../models/user');

// GET请求,获取所有用户
router.get('/users', async (req, res) => {
  try {
    const users = await User.find();
    res.json(users);
  } catch (err) {
    res.status(500).json({ message: err.message });
  }
});

// POST请求,创建新用户
router.post('/users', async (req, res) => {
  const user = new User({
    name: req.body.name,
    age: req.body.age
  });

  try {
    // 尝试保存新用户到数据库
    const newUser = await user.save();
    
    // 如果保存成功,返回状态码201和新用户信息
    res.status(201).json(newUser);
  } catch (err) {
    // 如果保存失败,返回状态码400和错误信息
    res.status(400).json({ message: err.message });
  }
});

module.exports = router;

在上面的示例中,我们定义了两个路由处理程序,一个用于获取所有用户,另一个用于创建新用户。在处理程序中,我们通过引入的User模型来执行数据库操作,如查询所有用户(User.find())和创建新用户(user.save())。

在Mongoose中,模型(Model)对象(如 User )可以调用一些内置的方法来执行数据库操作。以下是一些常用的Mongoose模型方法:

  1. save():将文档保存到数据库中。
  2. find():查找匹配条件的文档。
  3. findOne():查找匹配条件的第一个文档。
  4. findById():根据文档ID查找文档。
  5. findOneAndUpdate():查找并更新匹配条件的第一个文档。
  6. updateOne():更新匹配条件的第一个文档。
  7. updateMany():更新匹配条件的所有文档。
  8. deleteOne():删除匹配条件的第一个文档。
  9. deleteMany():删除匹配条件的所有文档。
  10. countDocuments():统计匹配条件的文档数量。
  11. aggregate():执行聚合操作,如分组、筛选等。
  12. distinct():查找匹配条件的文档并返回指定字段的唯一值。

除了上述方法外,您还可以根据具体需求使用Mongoose提供的其他方法来执行更复杂的数据库操作。这些方法使得在Node.js应用程序中与MongoDB数据库交互变得更加方便和灵活。希望这些信息对您有帮助。如果您有任何进一步的问题,请随时告诉我。

通过这种方式,在Express应用程序的路由中使用Mongoose模型,您可以方便地与MongoDB数据库进行交互,执行各种数据库操作。

https配置

var express = require('express');
var path = require('path');
var http = require('http');
var https = require('https');
var fs = require('fs');

var app = express();

app.get('/', function(req, res, next) {
  res.send('hello world');
});

var httpServer = http.createServer(app);
httpServer.listen(9080);

const options = {
  key: fs.readFileSync('./server.key'),
  cert: fs.readFileSync('./server.crt')
};
var httpsServer = https.createServer(options, app);
httpsServer.listen(9443);

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值