【Express】中间件

在Express中,中间件是处理HTTP请求的函数。它可以访问请求对象(req)、响应对象(res)和应用程序的请求-响应周期。中间件函数可以执行以下操作:

  1. 执行任何代码。
  2. 修改请求和响应对象。
  3. 终止请求-响应周期。
  4. 调用下一个中间件函数。

在这里插入图片描述

在Express中,中间件可以通过以下方式定义和使用:

  1. 使用app.use()方法:app.use()方法用于将中间件函数绑定到应用程序的每个请求。它可以在任何路由之前执行,并且对所有请求都生效。

  2. 使用路由特定的中间件:可以将中间件函数作为参数传递给特定的路由方法,如app.get()app.post()等。这些中间件函数只对该路由起作用。

  3. 使用路径特定的中间件:可以在中间件函数前指定一个路径作为参数,这样只有请求的路径匹配该路径时,对应的中间件才会被执行。

执行顺序取决于它们在代码中的位置。中间件函数按照它们在代码中的顺序依次执行,直到遇到next()方法。next()方法将控制权传递给下一个中间件函数。如果在中间件函数中不调用next(),请求-响应周期将被终止,不会传递给下一个中间件函数或路由处理程序。

中间件在Express中非常强大,它可以用于许多不同的任务,包括身份验证、日志记录、错误处理等。可以使用内置的中间件函数,也可以编写自定义的中间件函数来满足特定的需求。

1. 应用级中间件

// index.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
  res.send('这是首页')
  console.log('这是首页')
})

const cb1 = function (req, res, next) {
  console.log('中间件验证token')
  next()
}
// 没有挂载路径的中间件(全局中间件),通过该路由的每个请求都会执行该中间件
app.use(cb1)

const cb2 = function (req, res) {
  res.send('查询数据库,返回数据')
  console.log('查询数据库,返回数据')
}

// 路由中间件
app.get('/example', [cb2])
app.get('/user',(req,res)=> {
  res.send('user页面')
  console.log('user页面')
})
app.listen(3000, () => {
  console.log('Example app listening on port 3000!');
});

依次访问 / , /example , /user 路径,返回值为:

在这里插入图片描述

可见在访问 example 和 user 页面之前都会先执行 cb1 方法。

当然,也可以指定中间件执行的路径,比如 app.use('/user',cb1) 此时只在 user 页面会执行 cb1 方法。

2. 路由级中间件

路由级中间件和应用级中间件一样,只是它绑定的对象为 express.Router()。 express.Router() 目的是中间件和路由的分离的实例。可以将其视为简略版 express(),只能执行中间件和路由功能。

// index.js
// 写法一:
const express = require('express');
const app = express();
const router = express.Router();

router.use((req, res, next) => {
  console.log('Time: ', Date.now())
  next()
})
router.get('/', (req, res) => {
  res.send('Home page')
})
router.get('/about', (req, res) => {
  res.send('About page')
})
app.use('/', router);

app.listen(3000, () => {
  console.log('Example app listening on port 3000!');
});

app.use()route.use()都是用于向应用程序或特定路由添加中间件的方法。

  1. app.use(): app.use()方法用于将一个中间件函数绑定到应用程序的每个请求。它在任何路由之前,在请求到达服务器时执行。仅当路由路径未指定时,它将被视为全局中间件。

  2. route.use(): route.use()方法用于在特定的路由上添加中间件。在router上的每个请求上执行。router.get()方法定义了一个特定路由的路由处理程序。

// 写法二:
const express = require('express');
const app = express();
const fs = require('fs')
const path = require('path')
// 声明中间件函数
function recordMiddleware(req, res, next) {
  if (req.query.code === '521') {
    next()
  } else {
    res.send('no coding')
  }
}
app.get('/home', recordMiddleware, (req, res) => {
  res.send('前台首页')
})
app.get('/admin', recordMiddleware, (req, res) => {
  res.send('后台首页')
})
app.listen(3000, () => {
  console.log('server is running')
})

3. 错误中间件

// 错误中间件放在各个中间件的最后
app.use((req,res,next)=> {
  res.status(404).send('Not Found')
})

全局拦截错误,并将错误信息返回给前端。

//处理错误中间件
app.use((req, res, next) => {
    // status 1 - 失败 0 - 成功
    res.cc = (err, code = 1) => {
        res.send({
            code,
            message: err instanceof Error ? err.message : err
        })
    }
    next()
})
// 一般会在数据库断开是执行失败
if (err) return res.cc(err)
if (results.length !== 1) return res.cc('未查询到数据,登录失败')
// 对前端传过来的密码进行对比校验
const compareResult = bcrypt.compareSync(password, results[0].password)
if (!compareResult) {
    return res.cc('密码错误,登录失败')
}
// 对账号是否冻结做判定
if (results[0].status === 1) {
    return res.cc('账号已被冻结')
}

4. 内置的中间件(静态资源中间件)

express.static 是 Express 唯一内置的中间件。它基于 serve-static,负责在 Express 应用中提托管静态资源。每个应用可有多个静态目录。

// 设置静态资源,便于直接访问
// 比如:http://localhost:3000/css/style.css
app.use(express.static(__dirname + '/public'))

注意:

  1. index.html 为默认访问的资源,即直接访问 / ,也可以访问到 index.html
  2. 如果静态资源和路由规则同时匹配,谁先匹配谁就响应

5. 第三方中间件

安装所需功能的 node 模块,并在应用中加载,可以在应用级加载,也可以在路由级加载。

下面的例子安装并加载了一个解析 cookie 的中间件: cookie-parser

$ npm install cookie-parser
var express = require('express')
var app = express()
var cookieParser = require('cookie-parser')

// 加载用于解析 cookie 的中间件
app.use(cookieParser())

还有一个常用的是 body-parser 处理请求体:

const bodyParser = require('body-parser')

//处理 querystring 格式的请求体
let urlParser = bodyParser.urlencoded({extended:false})); 
//处理 JSON 格式的请求体
let jsonParser = bodyParser.json()

app.post('/login', urlParser, (request,response)=>{
 //获取请求体数据
//console.log(request.body);
 //用户名
console.log(request.body.username);
 //密码
console.log(request.body.userpass); 
response.send('获取请求体数据');
 });

// [Object: null prototype] { username: 'admin', userpass: '123456' }

// 或者也可以使用 express.json() 中间件
// app.use(express.json()) // 支持解析请求体中的 json 数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秀秀_heo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值