一、Express路由
1、路由的概念
1、路由就是映射关系
2、根据不同的用户URL请求,返回不同的内容
3、本质:URL请求地址与服务器资源之间的对应关系
2、Express中的路由
在
Express
中,路由指的是客户端的请求与服务器处理函数之间的映射关系Express 中的路由分 3 部分组成,分别是请求的类型、请求的 URL 地址、处理函数
3.Express 中的路由的例子
3、路由的匹配过程
每当一个请求到达服务器之后,需要先经过路由的匹配,只有匹配成功之后,才会调用对应的处理函数
在匹配时,会按照路由的顺序进行匹配,如果请求类型和请求的 URL 同时匹配成功,则
Express
会将这次请求,转交给对应的 function 函数进行处理
3、路由匹配的注意点
按照定义的先后顺序进行匹配
请求类型和请求的URL同时匹配成功,才会调用对应的处理函数
4、Express路由最简单的用法
在
Express
中使用路由最简单的方式,就是把路由挂载到app
上
案例代码
const express = require('express')
// 创建 web 服务器,命名为 app
const app = express()
// 挂载路由
app.get('/', (req, res) => {
res.send('Hello, World')
})
app.post('/', (req, res) => {
res.send('Hello, Tom')
})
app.listen(3000, () => {
console.log('running……')
})
5、模块化路由
为了方便对路由进行模块化的管理,
Express
不建议将路由直接挂载到app
上,而是推荐将路由抽离为单独的模块,将路由抽离为单独模块的步骤如下
创建路由模块对应的
.js
文件调用
express.Router()
函数创建路由对象向路由对象上挂载具体的路由
使用
module.exports
向外共享路由对象使用
app.use()
函数注册路由模块
案例代码:
// 1. 导入 express
const express = require('express')
// 2. 创建路由对象
const router = express.Router()
// 3. 挂载获取用户列表的路由
router.get('/user/list', (req, res) => {
res.send('用户列表')
})
// 4. 挂载添加用户列表的路由
router.post('/user/add', (req, res) => {
res.send('添加用户')
})
// 5. 向外导出路由对象
module.exports = router
6、注册路由模块
导入路由模块
使用
app.use()
注册路由模块
案例代码:
const express = require('express')
const app = express()
// 导入路由模块
const userRouter = require('./002-router')
// 使用 app.use() 注册路由模块
app.use(userRouter)
app.listen(3000, () => {
console.log('running……')
})
7、为路由模块添加前缀
类似于托管静态资源写法,为静态资源统一挂载访问前缀一样
注意,添加了路由前缀后,访问的路由的时候,也应该加上前缀
案例代码:
const express = require('express')
const app = express()
// 导入路由模块
const userRouter = require('./002-router')
// 使用 app.use() 注册路由模块
// 给路由模块添加统一得到访问前缀 /api
app.use('/api', userRouter)
app.listen(3000, () => {
console.log('running……')
})
二、中间件
1、中间件的概念
什么是中间件
所谓的中间件(
Middleware
),特指业务流程的中间处理环节现实生活中的例子
在处理污水的时候,一般都要经过三个处理环节,从而保证处理过后的废水,达到排放标准
处理污水的这三个中间处理环节,就可以叫做中间件
2、Express中间件的调用流程
当一个请求到达Express的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理
3、Express中间件的格式
Express的中间件,本质上就是一个function处理函数,Express中间件的格式如下:
注意:中间件函数的形参列表中,必须包括next函数。而路由处理函数中只包含req和res
4、next函数的作用
next函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由
二、express中间件
1、定义中间件函数
通过一下方式,定义一个最简单的中间件函数
const express = require('express')
const app = express()
// 定义一个最简单的中间件函数
const mw = function(req, res, next){
console.log('这是最简单的中间件函数')
// 把流转关系,转交给下一个中间件或者路由
next()
}
app.listen(80, () => {
console.log('running……')
})
2、全局生效的中间件
客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件。通过调用app.use(中间件函数),即可定义一个全局生效的中间件:
const express = require('express')
const app = express()
// 定义一个最简单的中间件函数
const kw = (req, res, next) => {
console.log('这是最简单的中间件函数')
// 把流转关系,转交给下一个中间件或者路由
next()
}
// 全局生效的中间件(处理所有的请求)
app.use(kw)
app.get('/', (req, res) => {
console.log('调用了 / 这个路由')
res.send('Home page')
})
app.get('/user', (req, res) => {
console.log('调用了 /user 这个路由')
res.send('User page')
})
app.listen(3000, () => {
console.log('running……')
})
3、定义全局中间件的简化形式
直接将我们的全局中间件挂载到app.use()上面
const express = require('express')
const app = express()
// 定义全局中间件的简化形式
app.use((req, res, next) => {
console.log('定义全局中间件的简化形式')
next()
})
app.get('/', (req, res) => {
console.log('调用了 / 这个路由')
res.send('Home page')
})
app.get('/user', (req, res) => {
console.log('调用了 /user 这个路由')
res.send('User page')
})
app.listen(3000, () => {
console.log('running……')
})
4、中间件的作用
在多个中间件之间,他们是共享同一份的res和req对象的(前提必须是中间件调用了next)
通过这种特性,我们可以直接在中间件函数上进行我们想要影响到下方路由的操作
5、定义多个全局中间件
可以使用app.use()连续的监听定义多个全局中间件,客户端向服务器发起请求时。服务器会根据中间件的定义先前在后依次执行
const express = require('express')
const app = express()
// 第一个全局中间件
app.use((req, res, next) => {
console.log('调用了第一个全局的中间件')
next()
})
// 第二个全局中间件
app.use((req, res, next) => {
console.log('调用了第二个全局的中间件')
next()
})
// 定义路由
// 请求这两个路由,会依次触发上述两个全局中间件
app.get('/user', (req, res) => {
res.send('User Page')
})
app.listen(3000, () => {
console.log('running……')
})
6、局部生效的中间件
不使用app.use监听的中间件,而是直接写在路由路径参数之后的,叫做局部生效的中间件
const express = require('express')
const app = express()
// 定义中间件函数 mv1
const mv1 = (req, res, next) => {
console.log('这是中间件函数')
next()
}
// mv1 这个中间件只在 "当前路由中生效",这种用法属于 "局部生效的中间件"
app.get('/', mv1, (req, res) => {
res.send('Home Page')
})
app.get('/user', (req, res) => {
res.send('User Page')
})
app.listen(3000, () => {
console.log('running……')
})
7、中间件的五个使用注意事项
1、一定要在路由之前注册中间件
2、客户端发送过来的请求,可以连续调用多个中间件进行处理
3、执行完中间件的业务代码之后,不要忘记调用next()函数
4、为了防止代码逻辑混乱,调用next()函数后不要再写额外的代码
5、连续调用多个中间件时,多个中间件之间,共享req和res对象
三、中间件的分类
1、中间件的分类
Express官方把常见的中间件分成了五大类:
~应用级别的中间件
~路由级别的中间件
~错误级别的中间件
~Express内置的中间件
~第三方的中间件
1.1、应用级别的中间件
通过app.use()或app.get()&post()绑定到app实例上的中间件,叫做应用级别的中间件
1.2、路由级别的中间件
绑定到express.Router()实例上的中间件,叫做路由级别的中间件
用法和应用级别的中间件没有任何的区别,只不过,应用级别中间件时绑定到app实例上,路由级别的中间件绑定到router实例上
1.3、错误级别的中间件
错误级别的中间件的作用:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题
格式:错误级别的中间件的function处理函数中,必须有4个形参。形参分别是(err,req,res,next)
注意:错误级别的中间件,必须注册在所有路由之后
const express = require('express')
const app = express()
// 1. 路由
app.get('/', (req, res) => {
// 1.1 抛出一个自定义的错误
throw new Error('服务器内部发生了错误')
res.send('Home Page.')
})
// 2. 错误级别的中间件
// 注意:错误级别的中间件,必须注册在所有路由之后
app.use((err, req, res, next) => {
// 2.1 在服务器打印错误消息
console.log('发生了错误:' + err.message)
// 2.2 向客户端响应错误相关的内容
res.send(err.message)
})
app.listen(3000, () => {
console.log('running……')
})
1.4、Express内置的中间件
自Express4.16.0版本开始,Express内置了三个常用的中间件,极大的提高了Express项目开发效率和体验
1、express.static快速托管静态资源的内置中间件,例如:HTMl文件、图片、cssu样式等(注意整个方法适用于express任何的版本,就是没有版本兼容性的问题)
2、exprss.json解析JSON格式的请求体数据(有兼容性,仅在4.16.0以上的版本中可以使用)
3、express.urlencoded解析URL-encoded格式的请求体数据(有兼容性,仅在4.16.0以上的版本可以使用)
1.5、express.json中间件的使用
express.json()中间件,解析表单中的JSON格式的数据
const express = require('express')
const app = express()
// 注意:除了错误级别的中间件,其他的中间件,必须在路由之前进行配置
// 通过 express.json() 这个中间件,解析表单中的 JSON 格式的数据
app.use(express.json())
app.post('/user', (req, res) => {
// 在服务器,可以使用 req.body 这个属性,来接收客户端发送过来的请求体数据
// 默认情况下,如果不配置解析表单数据中间件,则 req.body 默认等于 undefined
console.log(req.body)
res.send('ok')
})
app.listen(3000, () => {
console.log('running……')
})
1.6、express.urlencoded中间件的使用
express.urlencoded解析URL-encoded格式的请求体数据
const express = require('express')
const app = express()
// 通过 express.urlencoded() 这个中间件,来解析表单中的 url-encoded 格式的数据
app.use(express.urlencoded({ extended: false }))
app.post('/book', (req, res) => {
console.log(req.body)
res.send(req.body)
})
app.listen(3000, () => {
console.log('running……')
})
1.7第三方的中间件
非Express官方内置,而是由第三方开发出来的中间件,叫做第三方中间件。