【Node】Express 框架
原文来自我的个人博客
1. Express 初体验
1.1 认识Web框架
上一章我们在使用 http
内置模块来搭建 Web
服务器的过程中,会感到很多问题,那就是原生 http 模块
在进行很多处理时会较为复杂,比如:
URL
判断Method
判断- 参数处理
- 逻辑代码处理等等
都需要我们自己来处理和封装,当所有的内容都放在一起时,常常会显得非常混乱。
而这些都是框架能帮我们解决的问题
目前在 Node
中比较流行的 Web
服务器框架是 express
和 koa
,express
要早于 koa
出现,并且在 Node
社区中迅速流行起来。
- 我们可以基于
express
快速、方便的开发自己的Web
服务器 - 并且可以通过一些实用工具和中间件来扩展自己功能
Express
整个框架的核心就是中间件,理解了中间件其他一切都非常简单!
1.2 Express 安装
express
的使用过程有两种方式:
-
通过
express
提供的脚手架express-generator
,直接创建一个应用的骨架 -
从
0
搭建自己的express
应用结构
1.2.1 脚手架的方式搭建
- 安装脚手架
npm install express-generator -g
- 创建项目
express express-generator-demo
- 安装依赖
npm install
- 启动项目
npm run start
- 在浏览器输入
localhost:3000
,访问成功,表示服务已启动
1.2.3 从 0
搭建
- 创建一个新的文件夹并安装
express
mkdir express-demo
cd express-demo
npm init
npm i express
- 在这个文件夹下创建文件
01_express的基本使用.js
const express = require("express");
// 创建服务器
const app = express();
// home 的 get 请求处理
app.get("/home", (req, res) => {
res.end("Hello Home");
});
// login 的 post 请求处理
app.post("/login", (req, res) => {
res.end("Hello Login");
});
// 开启监听
app.listen(8000, () => {
console.log("服务器启动成功~");
});
- 启动服务
node 01_express的基本使用.js
- 访问
http://localhost:8000/home
地址
2. Express 中间件
Express
是一个路由和中间件的 Web
框架,它本身的功能非常少,它的程序本质上是一系列中间件函数的调用
2.1 中间件是什么?
中间件本质是传递给 express
的一个回调函数,这个回调函数接受三个参数:
- 请求对象 (request 对象)
- 响应对象 (response 对象)
- next 函数(在 express 中定义的用于执行下一个中间件的函数)
2.2 中间件可以执行哪些任务?
- 执行任何代码
- 更改请求和响应对象
- 结束请求-相应周期
- 调用栈中的下一个中间件
如果当前中间件功能没有 结束请求-相应周期,则必须调用 next()
将控制权传递给下一个中间件功能,否则,请求将被挂起。
2.3 如何应用中间件
express
主要提供两种方式:app/router.use
;app/router.methods
(methods 指的是常用的请求方式,比如get
post
)
2.3.1. 注册最普通用的中间件
当 express
接收到客户端发送的网络请求时,在所有中间件中开始进行匹配。
当匹配到第一个符合要求的中间件时,那么就会执行这个中间件
后续的中间件是否执行,取决于上一个中间件有没有执行 next
- 通过
use
方法注册的中间件是最普通/简单的中间件 - 通过
use
注册的中间件,无论是什么请求方式都可以匹配上
const express = require("express");
// 创建服务器
const app = express();
//
app.use((req, res, next) => {
console.log("我是最普通的中间件1");
next();
});
app.use((req, res, next) => {
console.log("我是最普通的中间件2");
next();
});
// 开启监听
app.listen(8000, () => {
console.log("服务器启动成功~");
});
启动服务,访问 localhost:8000
下面的两个中间件会依次执行
2.3.2 注册路径匹配的中间件
路径匹配的中间件不会对请求方式进行限制
const express = require("express");
// 创建服务器
const app = express();
// 注册路径匹配中间件
app.use('/home',(req,res,next) => {
console.log('我是匹配到 /home 执行的中间件')
})
// 开启监听
app.listen(8000, () => {
console.log("服务器启动成功~");
});
启动服务,访问 http://localhost:8000/home
,只有访问 '/home' 路径才会执行上面的中间件
2.3.3 注册路径和请求方式中间件
如果相对路径和请求方式都做限制可以使用 app.method(path, middleware)
的方式
const express = require("express");
// 创建服务器
const app = express();
app.get('/home',(req,res,next) => {
console.log('我是匹配到 /home 的 get 请求时执行的中间件')
})
// 开启监听
app.listen(8000, () => {
console.log("服务器启动成功~");
});
只有当匹配到 /home
的 get
请求时才执行上面的中间件
2.3.4 注册多个中间件
当我们相对某个复杂的操作进行拆分的时候,就可以使用以下方式注册多个中间件
app.get(路径,中间件1,中间件2,中间件3)
const express = require("express");
// 创建服务器
const app = express();
app.get(
"/home",
(req, res, next) => {
console.log("我是匹配到 /home 的 get 请求时执行的中间件1");
next()
},
(req, res, next) => {
console.log("我是匹配到 /home 的 get 请求时执行的中间件2");
next()
},
(req, res, next) => {
console.log("我是匹配到 /home 的 get 请求时执行的中间件3");
next()
}
);
// 开启监听
app.listen(8000, () => {
console.log("服务器启动成功~");
});
2.4 内置 & 第三方中间件
并非所有的中间件都需要我们从零去编写:
express
有内置一些帮助我们完成对request
解析的中间件;registry
仓库中也有很多可以辅助我们开发的中间件;
2.4.1 body-parse
在客户端发送post请求时,会将数据放到body中:
- 客户端可以通过json的方式传递;
- 也可以通过form表单的方式传递
如果让我么你自己写中间件的话,通常需要做一些额外的逻辑判断
const express = require("express");
// 创建服务器
const app = express();
app.use((req,res,next) => {
if(req.headers['content-type'] === 'application/json') {
req.on('data', data => {
const userInfo = JSON.parse(data.toString())
req.body = userInfo
})
req.on('end', () => {
next()
})
} else {
}
})
// 开启监听
app.listen(8000, () => {
console.log("服务器启动成功~");
});
但是,事实上我们可以使用 expres
内置的中间件或者使用 body-parser
来完成
app.use(express.json())
就像上面,我们只需要一行代码即可搞定,非常方便
如果解析的是 application/x-www-form-urlencoded
,可以使用
app.use(express.urlencoded({extended: true}))
2.4.2 morgan
如果我们希望将请求日志记录下来,那么可以使用 express
官网开发的第三方库:morgan
因为是第三方库,所以需要先单独安装 morgan
npm i morgan
const fs = require("fs");
const express = require("express");
const morgan = require("morgan");
const loggerWriter = fs.createWriteStream("./log/access.log", {
flags: "a+",
});
// 创建服务器
const app = express();
app.use(morgan("combined", { stream: loggerWriter }));
// 开启监听
app.listen(8000, () => {
console.log("服务器启动成功~");
});
启动服务,接着在 ./log
目录下就会保存我们所有的请求日志了
2.4.3 multer
上传文件,我们可以使用 express
提供的 multer
来完成:
同样需要先安装 multer
:
npm i multer
const express = require("express");
const multer = require("multer");
const path = require("path");
// 创建服务器
const app = express();
const upload = multer({
storage: multer.diskStorage({
destination(req, file, cb) {
cb(null, "uploads/");
},
filename: (req, file, cb) => {
cb(null, Date.now() + "_" + path.extname(file.originalname));
},
}),
});
// 单文件上传
app.post("/upload", upload.single("file"), (req, res, next) => {
console.log(req.file);
res.end("文件上传成功");
});
// 多文件上擦混
app.post("/photos", upload.array("photos"), (req, res, next) => {
console.log(req.files);
res.end("文件上传成功");
});
// 开启监听
app.listen(8000, () => {
console.log("服务器启动成功~");
});
接着我们尝试通过 postman
上传一张图片
如果我们希望借助于 multer
帮助我们解析一些 form-data
中的普通数据,那么我们可以使用 any
app.use(upload.any())
app.use('login', (req,res,next) => {
console.log(req.body)
})
2.5 其他
2.5.1 query & params
客户端传递到服务器参数的方法常见的是 5
种:
- 方式一:通过
get
请求中的URL
的params
; - 方式二:通过
get
请求中的URL
的query
; - 方式三:通过
post
请求中的body
的json
格式(中间件中已经使用过); - 方式四:通过
post
请求中的body
的x-www-form-urlencoded
格式(中间件使用过); - 方式五:通过
post
请求中的form-data
格式(中间件中使用过);
关于传递参数 params
和 query
的使用也是非常简单的
请求地址:http://localhost:8000/login/abc/zhangsan
- 获取参数
app.use('/login/:id/:name',(req,res,next) => {
console.log(req.params)
res.json('请求成功')
})
请求地址:http://localhost:8000/login?username=zhangsan&password=123456
- 获取参数
app.use('/login',(req,res,next) => {
console.log(req.qeury)
res.json('请求成功')
})
2.5.2 服务端的错误处理
app.use((err, req, res, next) => {
const message = err.message;
switch (message) {
case "USER DOES NOT EXISTS":
res.status(400).json({ message });
}
res.status(500);
});
2.5.3 静态资源服务器
部署静态资源我们可以选择很多方式:
Node
也可以作为静态资源服务器,并且express
给我们提供了方便部署静态资源的方法;
const express = require("express");
const app = express()
app.use(express.static('./build'))
app.listen(8000, ()) => {
console.log('静态服务器启动成功')
})
转载自:https://juejin.cn/post/7204799176936374333