安装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项目架构示例:
- 根目录结构:
-
app.js
或server.js
:Express应用程序的入口文件,包含应用程序的配置和启动代码。package.json
:包含项目的依赖项和脚本配置。node_modules/
:存放项目依赖的Node.js模块。public/
:存放静态文件(如CSS、JavaScript、图片等)。views/
:存放视图模板文件(如EJS、Pug等)。
- 路由结构:
-
routes/
目录:存放路由文件,可根据功能或模块划分子路由文件。app.js
中设置路由:在app.js
中通过app.use
或app.get
等方法将路由文件引入并设置路由路径。
- 中间件:
-
middlewares/
目录:存放自定义中间件函数。app.js
中使用中间件:在app.js
中通过app.use
方法使用中间件。
- 控制器:
-
controllers/
目录:存放路由处理函数,负责处理请求并返回响应。- 与路由文件分离:控制器文件应与路由文件分离,遵循单一职责原则。
- 模型:
-
models/
目录:存放数据模型定义和数据库操作。- 与控制器分离:模型文件应与控制器文件分离,负责数据操作和业务逻辑。
- 配置:
-
config/
目录:存放配置文件,如数据库配置、环境变量等。- 环境变量:使用
.env
文件存放敏感信息,并通过dotenv
模块加载。
- 错误处理:
-
- 错误处理中间件:编写统一的错误处理中间件,处理应用程序中发生的错误。
- 测试:
-
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 应用使用回调函数的参数: request 和 response 对象来处理请求和响应的数据。
app.get('/', function (req, res) {
// --
})
app.post('/',(req,res)=>{})
request 和 response 对象的具体介绍:
Request 对象 - request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性。常见属性有:
- req.app:当callback为外部文件时,用req.app访问express的实例
- req.baseUrl:获取路由当前安装的URL路径
- req.body / req.cookies:获得「请求主体」/ Cookies
- req.fresh / req.stale:判断请求是否还「新鲜」
- req.hostname / req.ip:获取主机名和IP地址
- req.originalUrl:获取原始请求URL
- req.params:获取路由的parameters
- req.path:获取请求路径
- req.protocol:获取协议类型
- req.query:获取URL的查询参数串
- req.route:获取当前匹配的路由
- req.subdomains:获取子域名
- req.accepts():检查可接受的请求的文档类型
- req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages:返回指定字符集的第一个可接受字符编码
- req.get():获取指定的HTTP请求头
- req.is():判断请求头Content-Type的MIME类型
Response 对象 - response 对象表示 HTTP 响应,即在接收到请求时向客户端发送的 HTTP 响应数据。常见属性有:
- res.app:同req.app一样
- res.append():追加指定HTTP头
- res.set()在res.append()后将重置之前设置的头
- res.cookie(name,value [,option]):设置Cookie
- opition: domain / expires / httpOnly / maxAge / path / secure / signed
- res.clearCookie():清除Cookie
- res.download():传送指定路径的文件
- res.get():返回指定的HTTP头
- res.json():传送JSON响应
- res.jsonp():传送JSONP响应
- res.location():只设置响应的Location HTTP头,不设置状态码或者close response
- res.redirect():设置响应的Location HTTP头,并且设置状态码302
- res.render(view,[locals],callback):渲染一个view,同时向callback传递渲染后的字符串,如果在渲染过程中有错误发生next(err)将会被自动调用。callback将会被传入一个可能发生的错误以及渲染后的页面,这样就不会自动输出了。
- res.send():传送HTTP响应
- res.sendFile(path [,options] [,fn]):传送指定路径的文件 -会自动根据文件extension设定Content-Type
- res.set():设置HTTP头,传入object可以一次设置多个头
- res.status():设置HTTP状态码
- 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的基本步骤:
- 安装MongoDB数据库:您可以从MongoDB的官方网站(https://www.mongodb.com/)下载适合您操作系统的安装程序,并按照安装指南进行安装。
- 启动MongoDB服务:安装完成后,启动MongoDB服务。在命令行中输入
mongod
(或sudo mongod
)来启动MongoDB服务。 - 连接到MongoDB数据库:在另一个命令行窗口中输入
mongo
命令来连接到MongoDB数据库。
修改这3个能够远程访问
检验:ip:27017
- 使用MongoDB Shell:通过MongoDB Shell,您可以执行各种数据库操作,如创建数据库、创建集合、插入文档、查询文档等。以下是一些常用的MongoDB Shell命令:
-
- 创建数据库:
use database_name
- 创建集合:
db.createCollection('collection_name')
- 插入文档:
db.collection_name.insertOne({ key: value })
- 查询文档:
db.collection_name.find()
- 创建数据库:
- 使用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数据库进行交互。让我来解释一下这两个概念的含义:
- 定义模式(Schema):模式是用来定义MongoDB文档结构的一种方式,类似于表结构的定义。在Mongoose中,您可以通过定义模式来规定文档中包含的字段、字段类型、默认值等信息。模式定义了文档的结构,类似于一个数据模板,确保文档符合特定的结构和规范。
例如,您可以定义一个用户模式(User Schema),包含姓名(name)和年龄(age)两个字段:
const userSchema = new Schema({
name: String,
age: Number
});
- 定义模型(Model):模型是基于模式创建的构造函数,用于对数据库进行操作。在Mongoose中,您可以通过定义模型来创建具体的文档实例,以便对数据库进行增删改查操作。模型是模式的实例化,它允许您在应用程序中使用模式定义的字段和规范。
通过使用上面定义的用户模式,您可以创建一个用户模型(User Model):
const User = mongoose.model('User', userSchema);
现在,您可以使用User模型来创建新的用户文档、查询用户数据、更新用户信息等操作。
通过定义模式和模型,您可以规范化数据结构、提供数据验证、简化数据库操作等。这些概念帮助您在Node.js应用程序中更好地与MongoDB数据库进行交互,并更有效地管理数据。
在路由中使用
要在Express应用程序的路由中使用Mongoose模型(即在路由处理程序中与MongoDB数据库进行交互),可以按照以下步骤进行操作:
- 引入Mongoose模型:首先,在您的Express应用程序中,确保已经引入了Mongoose模型。通常,您会在单独的文件中定义模型,并在需要的地方引入该模型。
const User = require('./models/user'); // 假设User模型定义在models/user.js文件中
- 在路由处理程序中使用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模型方法:
- save():将文档保存到数据库中。
- find():查找匹配条件的文档。
- findOne():查找匹配条件的第一个文档。
- findById():根据文档ID查找文档。
- findOneAndUpdate():查找并更新匹配条件的第一个文档。
- updateOne():更新匹配条件的第一个文档。
- updateMany():更新匹配条件的所有文档。
- deleteOne():删除匹配条件的第一个文档。
- deleteMany():删除匹配条件的所有文档。
- countDocuments():统计匹配条件的文档数量。
- aggregate():执行聚合操作,如分组、筛选等。
- 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);