目录
1. express路由
1.1 什么是路由
在express中,路由指的是客户端请求与服务器处理函数之间的映射关系。
express中的路由分为3部分,分别是请求类型,请求URL地址,处理函数,格式如下:
app.METHOD(URL, FUNCTION)
// 如下例子
app.get('/user', (req, res) => {
console.log('get require');
})
1.2 express路由使用示例
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('get require');
})
app.post('/', (req, res) => {
res.send('post require');
})
app.listen('80', () => {
console.log('express server is running at https://127.0.0.1');
})
1.3 路由的匹配过程
每当一个请求到达服务器之后,需要经过路由匹配,匹配成功后,才会调用对应的处理函数。
在匹配时,会按照路由的顺序进行匹配,如果请求类型和请求的URL同时匹配成功,则express会将这次请求,转交给对应的function函数进行处理。
注意:
1. 按照定义的先后顺序进行匹配
2. 请求类型和请求的URL同时匹配成功才会调用对应的处理函数
2. 模块化路由
2.1 模块化路由的步骤
为了方便对路由进行模块化的管理,express不建议将路由直接挂载到app上,而是推荐将路由抽离为单独的模块。
步骤如下:
1. 创建路由模块对应的js文件
2. 调用express.Router()函数创建路由对象
3. 向路由对象上挂载具体的路由
4. 使用module.exports向外共享路由对象
5. 使用app.use()函数注册路由模块
2.2 模块化路由示例
1. 创建路由模块
// 1. 导入express模块
const express = require('express');
// 2. 创建路由对象
const router = express.Router();
// 3. 挂载获取用户列表路由
router.get('/user/list', (req, res) => {
res.send('get user list');
})
// 4. 挂载添加用户信息路由
router.post('/user/add', (req, res) => {
res.send('post user info')
})
// 5. 导出路由模块
module.exports = router;
2. 注册路由模块
测试get、post请求:
3. 请求路径中挂载统一前缀
于静态资源托管统一挂载前缀的形式类似:
app.use('/xxx', router);
示例:
添加路径前缀,修改后:
用原来但请求路径,请求出错:
需要有对应前缀 /acb 才能请求成功:
3. express中间件的概念
3.1 中间件的概念
当一个请求到达express服务器后,可以连续调用多个中间件对这次请求进行预处理。
3.2 中间件的格式
1. express中间件本质上是一个函数,这个函数的格式如下:
中间件函数的特点就是第三个参数是个函数next
2. next函数的作用:
next的作用就是保持中间件的流转,让本次函数的处理结果交给下一个中间件
4. 中间件函数
4.1 定义中间件函数
1. 定义基本的中间件
// 这里所定义的mw,就是指向一个中间件函数
const mw = function(req, res, next) {
// 中间件的处理
// ......
// 必须调用next函数,把流转关系交给下一个中间件
next();
}
2. 注册全局生效的中间件
客户端发起的任何请求,到达服务器后,都会触发的中间件,叫做全局生效的中间件。通过钓鱼app.use(中间件函数),即可定义一个全局生效的中间件,示例代码如下:
const express = require('express');
const app = express();
const mw = function(req, res, next) {
console.log('这是一个最简单的中间件');
next();
}
// 注册全局生效的中间件
app.use(mw);
4.2 中间件的作用
多个中间件之间,共享一份req和res,基于这样的特性,我们可以在上游的中间件中,统一为req或res对象添加自定义的属性或方法,供下游的中间件或路由进行使用。
const express = require('express');
const app = express();
const mw = funtion(req, res, next) {
const time = Date.now();
// 为req添加属性
req.startTime = time;
next();
}
app.use(mw);
app.get('/', (req, res) => {
// 中间件添加的属性下游中间件或路由可以直接使用
res.send('get require success '+req.startTime);
})
app.post('/', (req, res) => {
// 中间件添加的属性下游中间件或路由可以直接使用
res.send('get require success '+req.startTime);
})
app.listen('80', () =>{
console.log('server running');
})
4.3 定义多个中间件
const express = require('express');
const app = express();
const mw1 = funtion(req, res, next) {
console.log('调用第一个中间件')
next();
}
const mw2 = funtion(req, res, next) {
console.log('调用第二个中间件')
next();
}
app.use(mw1);
app.use(mw2);
app.get('/', (req, res) => {
res.send('Home page. get')
})
app.post('/', (req, res) => {
res.send('Home page. post')
})
app.listen('80', () =>{
console.log('server running');
})
客户端发get/post请求,会按顺序调用第一个中间件,第二个中间件。
4.4 局部生效中间件
不使用app.use()定义的中间件,叫做局部生效的中间件,示例代码如下:
const mw1 = function(req, res, next){
console.log('局部生效中间件1');
next();
}
const mw2 = function(req, res, next){
console.log('局部生效中间件2');
next();
}
app.get('/user', mw1, (req,res)=>{
res.send('调用了局部生效中间件')
})
// 调用多个局部中间件,可以按顺序传入局部中间件函数、
app.get('/user/more', mw1, mw2, (req,res)=>{
res.send('调用了局部生效中间件')
})
// 也可以用数组传入
// app.get('/user/more', [mw1,mw2], (req,res)=>{
// res.send('调用了局部生效中间件')
// })
// 局部中间件不会影响下面这个路由
app.post('/user', (req, res)=>{
res.send('没有调用了局部生效中间件')
})
4.5 中间件注意事项
- 一定要在路由之前注册中间件
- 客户端发送过来的请求,可以连续调用多个中间件进行处理
- 执行完中间件的业务代码后,不要忘记调用next()函数
- 为了防止代码逻辑混乱,调用next()函数后不要再写额外的代码
- 连续调用多个中间件时,多个中间件之间,共享req、res对象
5. 中间件的分类
5.1 中间件的分类
- 应用级别的中间件:通过app.use()或app.get()或app.post(),绑定到app实例上的中间件
- 路由级别的中间件:绑定到express.Router实例上的中间件
- 错误级别中间件:专门来捕获项目中的异常和错误的中间件,防止项目崩溃
- express内置中间件:express.static、express.json、express.urlencoded等等
- 第三方的中间件:第三方开发的中间件
5.2 错误级别的中间件
格式:错误级别中间件的function处理函数中,必须有4个形参,形参从前到后分别是(err, req, res,next)
app.get('/', (req, res)=>{
throw new Error('error !');
res.send('xxx');
})
const mwErr = funtion(err, req, res, next){
console.log('error!');
res.send('server error!');
}
app.use(mwErr);
注意:错误级别中间件必须注册在所有路由之后
5.3 express内置中间件
从express4.16.0版本开始,express内置了3个常用的中间件,极大提高了express项目开发的效率和体验:
- express.static:快速托管静态资源的内置中间件、例如:HTML文件、图片、CSS样式等
- express.json:解析JSON格式的请求体数据
- express.urlencoded:解析URL-encoded格式的请求体数据
配置express.json、express.urlencoded中间件:
app.use(express.json());
app.use(express.urlencoded({extend:false}));//固定写法
app.post('/user/info',(req, res)=>{
// 可以打印post请求携带的请求体数据 ,包括json格式和url-encoded格式
console.log(req.body);
res.send('ok');
})
5.4 第三方中间件
const parser = require('body-parser');// 引入第三方中间件
app.use(parser({extend:false}));//固定写法
app.post('/user/info',(req, res)=>{
// 可以打印post请求携带的请求体数据 ,解析url-encoded数据格式
console.log(req.body);
res.send('ok');
})
6. 自定义中间件
6.1 自定义中间件步骤
6.2 示例代码