Node.js(五)

一、Express路由

1、路由的概念

1、路由就是映射关系

2、根据不同的用户URL请求,返回不同的内容

3、本质:URL请求地址与服务器资源之间的对应关系

Node.js(五)

2、Express中的路由

  1. Express 中,路由指的是客户端的请求服务器处理函数之间的映射关系

  2. Express 中的路由分 3 部分组成,分别是请求的类型请求的 URL 地址处理函数

Node.js(五)

    3.Express 中的路由的例子

Node.js(五)

 3、路由的匹配过程

  1. 每当一个请求到达服务器之后,需要先经过路由的匹配,只有匹配成功之后,才会调用对应的处理函数

  2. 在匹配时,会按照路由的顺序进行匹配,如果请求类型请求的 URL 同时匹配成功,则 Express 会将这次请求,转交给对应的 function 函数进行处理

Node.js(五)

3、路由匹配的注意点

  • 按照定义的先后顺序进行匹配

  • 请求类型请求的URL同时匹配成功,才会调用对应的处理函数

4、Express路由最简单的用法

  1. 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、注册路由模块

  1. 导入路由模块

  2. 使用 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、为路由模块添加前缀

  1. 类似于托管静态资源写法,为静态资源统一挂载访问前缀一样

  2. 注意,添加了路由前缀后,访问的路由的时候,也应该加上前缀

案例代码:

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、中间件的概念

  1. 什么是中间件

    所谓的中间件(Middleware ),特指业务流程的中间处理环节

  2. 现实生活中的例子

    在处理污水的时候,一般都要经过三个处理环节,从而保证处理过后的废水,达到排放标准

    处理污水的这三个中间处理环节,就可以叫做中间件

Node.js(五)

2、Express中间件的调用流程

当一个请求到达Express的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理

Node.js(五)

 3、Express中间件的格式

Express的中间件,本质上就是一个function处理函数,Express中间件的格式如下:

Node.js(五)

注意:中间件函数的形参列表中,必须包括next函数。而路由处理函数中只包含req和res 

4、next函数的作用

next函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由

Node.js(五)

 二、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)

通过这种特性,我们可以直接在中间件函数上进行我们想要影响到下方路由的操作

Node.js(五)

 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实例上的中间件,叫做应用级别的中间件

Node.js(五)

 1.2、路由级别的中间件

绑定到express.Router()实例上的中间件,叫做路由级别的中间件

用法和应用级别的中间件没有任何的区别,只不过,应用级别中间件时绑定到app实例上,路由级别的中间件绑定到router实例上

Node.js(五)

 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以上的版本可以使用)

Node.js(五)

 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官方内置,而是由第三方开发出来的中间件,叫做第三方中间件。

上一篇:golang 反向代理reverseproxy源码分析


下一篇:WebSocket