Express 相关知识
1. 什么是 Express?有什么用?
Express 是基于 Node.js 内置 http 模块扩展的一个 Web 开发框架。是一个 第三方包 ,可以极大提升开发效率。
2. Express 基本用法
在这里安装体验的是 express@4.17.1 版本
1. 快速搭建一个 Web 服务器
简易服务器代码
const express = require("express");
const app = express();
app.listen(80, () => {
console.log("server is running at http://localhost");
});
2. 监听客户端的 请求方法 和 请求路径
处理 post 请求:app.post(url, callback)
处理 get 请求:app.get(url, callback)
put, delete...更多方法语法相同
其中:
url 是地址。
callback 是处理函数,在匹配到对应的 请求方法 和 请求路径 后就会执行。
路由处理案例
const express = require("express");
const app = express();
// 1. 当客户端用 get 请求 http://localhost/getUser 这个地址时匹配
app.get("/getUser", (req, res) => {
// req 是请求对象, res 是响应对象
// res.send() 方法用于做出响应
res.send("get");
});
// 2. 当客户端用 post 请求 http://localhost/getUser 这个地址时匹配
app.post("/getUser", (req, res) => {
// res.send() 方法用于做出响应
res.send("post");
});
app.listen(80, () => {
console.log("server is running at http://localhost");
});
3. 获取 和 发送 参数
使用 res.query 和 res.params 来接收参数
参数处理案例
const express = require("express");
const app = express();
// 当客户端用 get 请求 http://localhost/getUser?id=1&name=tgx 时匹配
app.get("/getUser", (req, res) => {
// 1. req.query 默认是空对象,接收地址栏的 查询参数
// 此时 req.query 是个对象 { id: '1', name: 'tgx' }
res.send(`查询参数是:${req.query}`);
});
// 当客户端用 post 请求 http://localhost/getUser/5/tgx 时匹配
app.post("/getUser/:uid/:uname", (req, res) => {
// 2. res.params 默认是空对象,接收地址栏的 动态参数
// 此时 req.params 是个对象 { uid: '5', uname: 'tgx }
res.send(`动态参数是:${req.params}`);
});
app.listen(80, () => {
console.log("server is running at http://localhost");
});
4. 托管静态资源
使用 app.use(express.static('文件夹')) 来托管静态资源
可以多次使用该方法托管(但是如果存在同名资源,优先使用前方的目录)
具体案例
const express = require("express");
const app = express();
// 假设 demo 是个文件夹,里面有 index.html, index.css, index.js 三个文件
// 托管后 就可以直接访问 http://localhost/index.html
app.use(express.static("./demo"));
app.listen(80, () => {
console.log("server is running at http://localhost");
});
加了前缀的案例
const express = require("express");
const app = express();
// 假设 demo 是个文件夹,里面有 index.html, index.css, index.js 三个文件
// 托管后, 现在要加个前缀, 要访问 http://localhost/demo/index.html
app.use("/demo", express.static("./demo"));
app.listen(80, () => {
console.log("server is running at http://localhost");
});
3. Express 后端路由
概念
路由:指的是一种 对应关系
前端路由:指 hash 地址 与 组件 的对应关系
后端路由:指 请求方式、请求地址 与 处理函数 的对应关系
1. express 中路由的基本用法
express 中一个路由包含 3 个部分
请求方式
请求地址
处理函数
例如:app.get('/getUser', callback) 就是一个路由,其中:
get 是 请求方式
/getUser 是 请求地址
callback 是 处理函数(回调函数)
express 中的路由会从上到下依次匹配,完全匹配到 请求方法、请求地址 后才会执行 回调函数
2. express 中的模块化路由
项目中路由应该使用模块化管理,而不是 挂载到 实例 app 上
app.use() 方法,是用来注册中间件的
app.use() 方法,如果加了前缀注册路由,请求时,路由前也要加这个前缀,例如:
假设服务地址是 http://localhost
定义一个路由 router.get('/user/list', (req, res) => {})
注册这个路由 app.use(router),则访问 http://localhost/user/list
注册这个路由 app.use('/api', router),则访问 http://localhost/api/user/list
路由模块
// 使用 router.js 模块 来集中管理路由
const express = require("express");
// 创建 路由实例 用来管理路由
const router = express.Router();
// 挂载第一个路由
router.get("/user/list", (req, res) => {});
// 挂载第二个路由
router.post("/home", (req, res) => {});
// 挂载......
module.exports = router;
如何注册路由模块
const express = require("express");
const app = express();
// 引入并注册 路由模块
const router = require("./router.js");
app.use(router);
app.listen(80, () => {
console.log("server is running at http://localhost");
});
4. Express 中间件
概念
中间件:是指 业务处理的中间环节。后端在接收到前端的请求数据后,要经过一系列的 中间处理环节,最后再把数据返回给前端,而中间这些处理环节就是 中间件
1. 中间件具体是什么?
中间件的本质就是 处理函数,与路由处理函数相比,中间件会多出一个 next 参数,且中间件内部必须调用 next() 这个参数(放行函数)
2. 中间件的特性
所有 中间件 按顺序依次从上往下执行,直到最后一个中间件走完了,才会匹配到对应的 路由
所有 中间件 共享同一份 req 和 res
全局中间件:使用 app.use() 或 router.use() 单独注册 的中间件
局部中间件:这种中间件不需要 app.use() 单独注册,而是放在 路由地址 和 路由函数 之间
局部中间件用法
// 定义中间件
const mw1 = (req, res, next) => {
console.log("中间件 mw1");
next();
};
const mw2 = (req, res, next) => {
console.log("中间件 mw2");
next();
};
// 两种写法都可以:
// 1. 路由中直接插入,这个 mw1, mw2 就是 局部中间件
app.use("/user", mw1, mw2, (req, res) => {});
// 2. 路由中放入数组插入,这个 mw1, mw2 就是 局部中间件
app.use("/user", [mw1, mw2], (req, res) => {});
3. 中间件的分类
中间件分 5 类
应用级别 的中间件:绑在 app.use() 上
路由级别 的中间件:绑在 router.use() 上
错误级别 的中间件:放在所有 路由 之后
Express 内置 的中间件
第三方 中间件
3.1 应用级别 的中间件
指的是上文的写法,绑在 app.use() 上
3.2 路由级别 的中间件
指的是上文的写法,绑在 router.use() 上
3.3 错误级别 的中间件
放在所有 路由中间件 之后,用来防止某个错误导致服务器崩溃
错误级别 中间件
const express = require("express");
const app = express();
// 路由中间件
app.use("/", (req, res) => {});
// 错误中间件 必须 放在所有路由中间件之后,才能捕获错误
app.use((err, req, res, next) => {
console.log("发生了错误" + err.message);
res.send("服务器发生了错误" + err.message);
});
app.listen(80);
3.4 Express 内置 的中间件
自 Express 4.16.0 版本开始,Express 内置了 3 个常用的中间件,极大的提高了 Express 项目的开发效率和体验
express.static 快速托管静态资源的内置中间件,例如: HTML 文件、图片、CSS 样式等(无兼容性)
express.json 解析 JSON 格式的请求体数据(仅在 4.16.0+ 版本中可用)
express.urlencoded 解析 固定表单格式的请求体数据(仅在 4.16.0+ 版本中可用)
express.urlencoded 只能解析 application/x-www-form-urlencoded 格式的表单数据
express.json 中间件 示例
const express = require("express");
const app = express();
// 需要配置在所有路由之前
// 使用 内置中间件 express.json() 解析客户端发送的请求体,并挂载到 req.body 上
app.use(express.json());
// 第二个中间件
app.use((req, res, next) => {
// 默认 req.body 接收的 json 请求体是 undefined
// 经过 express.json 内置中间件 之后,就能在 req.body 拿到客户端发的 json 内容
console.log(req.body);
res.send("ok");
});
// 路由中间件
app.use("/", (req, res) => {});
app.listen(80);
express.urlencoded 中间件 示例
const express = require("express");
const app = express();
// 需要配置在所有路由之前
app.use(express.json()); // 处理 json 请求体
app.use(express.urlencoded({ extended: false })); // 处理 URL-encoded 格式请求体
// 第二个中间件
app.use((req, res, next) => {
// 经过 express.urlencoded 内置中间件 之后,
// 就能在 req.body 拿到客户端发的表单键值对 URL-encoded 格式内容
console.log(req.body);
res.send("ok");
});
// 路由中间件
app.use("/", (req, res) => {});
app.listen(80);
3.5 第三方 中间件
第三方 中间件 是指从 npm 仓库下载的中间件,也可以是自己写的 自定义 中间件。
这里用到了一个 querystring 模块,用来处理字符串,是 node.js 内置模块,与 fs, path 一样
自定的中间件 模块
// customBodyParser.js 文件
const qs = require("querystring");
// 自定义一个处理数据的中间件
const customBodyParser = (req, res, next) => {
// 1. 当客户端发送数据时触发 data 事件,监听并拼接客户端发来的数据
let str = "";
req.on("data", (chunk) => {
// 数据是分片发送的,可能需要多次接收
str += chunk;
});
// 2. 当数据发送完成时触发 end 事件
req.on("end", () => {
// qs.parse 方法 可以把字符串解析为对象
req.body = qs.parse(str);
});
next();
};
module.exports = customBodyParser;
如何使用自定的中间件
const express = require("express");
const customBodyParser = require("./customBodyParser.js");
const app = express();
// 注册自定义的中间件
app.use(customBodyParser);
app.post("/user", (req, res) => {
res.send(req.body);
});
app.listen(80, () => {
console.log("server is running at http://localhost");
});