Express这些中间件还没掌握的话赶紧学习起来啦!【持续更新中】

1、导读

学了Express框架有一段时间了,感觉Express本身就是一个极其简单的框架。一个完整的web开发框架其实都是由各种路由还有大量的中间件构成的,从本质上来说,一个Express的应用其实就是在调用各种中间件。

所以,掌握好一些常用的中间件我觉得是很有必要的,这可以很好的提高你的开发效率。因此写下这篇文章,文章主要会从Express自身的一些中间件再到一些第三方的中间进行讲解。首先让我们来了解下什么是中间件?

2、什么是中间件

中间件就是一堆方法,可以接收客户端发来的请求、可以对请求做出响应,也可以将请求继续交给下一个中间件继续处理。

2.1中间件的构成

中间件主要由两部分构成,中间件方法以及请求处理函数。
中间件方法由Express提供,负责拦截请求,请求处理函数由开发人员提供,负责处理请求。

app.get('请求路径', '处理函数')   // 接收并处理get请求
app.post('请求路径', '处理函数')  // 接收并处理post请求

2.2中间件的处理方式

我们可以针对同一个请求设置多个中间件,对同一个请求进行多次处理。
默认情况下,请求会从上到下依次匹配中间件,一旦匹配成功,终止匹配。
可以调用next方法将请求的控制权交给下一个中间件,直到遇到结束请求的中间件。
注意:

1.如果在post,get请求过程中的回调函数没有next()参数,那么就会匹配上第一个路由,而不会往下匹配了。如果想往下匹配的话,处理函数的参数中就需要写next,在处理函数中调用next().
2.如果当前中间件函数没有结束请求/响应循环,那么它必须调用 next(),以将控制权传递给下一个中间件函数。否则,请求将保持挂起状态。

app.get('/request', (req, res, next) => {
     req.name = "张三";
     next();
 });
 app.get('/request', (req, res) => {
     res.send(req.name);
 });

3.应用层级中间件

3.1app.METHOD()

使用 app.use() 和 app.METHOD() 函数将应用层中间件绑定到应用程序对象的实例,其中 METHOD 是中间件函数处理的请求的小写 HTTP 方法(例如 GET、PUT 或 POST)。

app.get('/request', (req, res) => {
     req.name = "张三";
 });

3.2 app.use()

app.use 匹配所有的请求方式(GET,PUT,POST…),可以直接传入请求处理函数,代表接收所有的请求。

app.use((req, res, next) => {
     console.log(req.url);
     next();
 });

app.use 第一个参数也可以传入请求地址,代表不论什么请求方式,只要是这个请求地址就接收这个请求。

 app.use('/admin', (req, res, next) => {
     console.log(req.url);
     next();
 });

4.路由器层中间件

路由器层中间件的工作方式与应用层中间件基本相同,差异之处在于它绑定到 express.Router() 的实例。他的好处在于对路由处理进行解耦
index.js

const express = require('express')
const userRouter = require('./user')
const router = express.Router()
router.use('/user', userRouter)

user.js

const express = require('express')
const router = express.Router()
router.post('/login', function(req, res) {}
module.exports = router

然后当我们想使用user.js下面/login路由的话,我们就必须得通过 /user/login路由进行访问,直接/login是访问不到的。这也对路由也有了一个层级的关系。

5.错误处理中间件

在程序执行的过程中,会不可避免的会出现一些无法预料的错误,比如文件读取失败,数据库连接失败。而错误处理中间件是一个集中处理错误的地方。
注意:

错误处理中间件始终采用四个自变量。必须提供四个自变量,以将函数标识为错误处理中间件函数。即使无需使用 next 对象,也必须指定该对象以保持特征符的有效性。否则,next 对象将被解释为常规中间件,从而无法处理错误。

 app.use((err, req, res, next) => {
     res.status(500).send('服务器发生未知错误');
 })

当我们在前面的中间件遇到错误的时候,我们可以通过调用next()方法将错误信息通过参数的形式传递给next()方法,即可触发错误处理中间件。

 app.get("/", (req, res, next) => {
     fs.readFile("/file.txt", (err, data) => {
         if (err) {
            next(err);
         }
     });
});

6.内置中间件

Express 中唯一内置的中间件函数是 express.static(root, [options])。它负责提供 Express 应用程序的静态资源,例如img、CSS、JavaScript 文件等。
root 自变量指定从其中提供静态资源的根目录。而对于每个应用程序,可以有多个静态目录

app.use('/static',express.static('public'));
app.use('/aaa',express.static('imges'));

表示现在 你就可以通过带有“/static ”前缀的地址来访问public目录下面的文件了
比如我们可以通过以下进行访问:

  • http://localhost:3000/static/abc.jpg
  • http://localhost:3000/aaa/bcd.jpg

7.第三方中间件

post请求解析

相关地址:https://github.com/expressjs/body-parser/
https://www.cnblogs.com/chyingp/p/nodejs-learning-express-body-parser.html
body-parser是一个HTTP请求体解析的中间件,使用这个模块可以解析JSON、Raw、文本、URL-encoded格式的请求体,是经常使用的一个中间件。
基本使用方法:

  1. 安装
npm i -S body-parser
  1. 使用
const bodyParser = require('body-parser')

// 创建 express 应用
const app = express()
//对body-parser进行配置
// 使node后台支持了application/x-www-form-urlencoded请求体
app.use(bodyParser.urlencoded({ extended: true //扩展模式 }))
// 使node后台支持了application/json请求体
app.use(bodyParser.json())

设置完毕之后,会在req对象上面新增一个req.body的一个对象,我们就可以通过直接使用req.body.属性名 获取到对应到值了。

跨域中间件 cors

当你遇到了跨域的问题,最简单的解决办法就是安装一个cors中间件了。这样就不会遇到跨域问题~
相关地址:https://github.com/expressjs/cors
基本使用方法:

  1. 安装
npm i -S cors
  1. 使用
const cors = require('cors')

app.use(cors())

上面的使用方法说明了所有网站都可以进行访问,当然我们可以执行只有某些网站才可以进行访问。

var corsOptions = {
  origin: 'http://www.baidu.com', //只有百度可以访问
  optionsSuccessStatus: 200 
}

app.get('/products/:id', cors(corsOptions), function (req, res, next) {
  res.json({msg: '只有百度可以访问'})
})

mysql数据库查询

相关地址:https://github.com/mysqljs/mysql
基本使用方法:

  1. 安装mysql库
npm i -S mysql
  1. 配置
    创建 db 目录,新建两个文件: index.js,config.js
    config.js 源码如下:
module.exports = {
  host: 'localhost',
  user: 'root',
  password: '12345678',
  database: 'book'
}
  1. 连接
    连接数据库需要提供使用 mysql 库的 createConnection 方法,在 index.js 中创建如下方法:
function connect() {
  return mysql.createConnection({
    host,
    user,
    password,
    database,
    multipleStatements: true
  })
}

multipleStatements:允许每条 mysql 语句有多条查询.使用它时要非常注意,因为它很容易引起 sql 注入(默认:false)

  1. 查询(查询需要调用 connection 对象的 query 方法)
function querySql(sql) {
  const conn = connect()
  return new Promise((resolve, reject) => {
    try {
      conn.query(sql, (err, results) => {
        if (err) {
          reject(err)
        } else {
          resolve(results)
        }
      })
    } catch (e) {
      reject(e)
    } finally {
      conn.end()
    }
  })
}

conn 对象使用完毕后需要调用 end 进行关闭,否则会导致内存泄露

5.调用方法

db.querySql('select * from book').then(result => {
  console.log(result)
})

MD5加密 crypto

相关地址:http://nodejs.cn/api/crypto.html
基本使用方法:

  1. 安装 crypto 库:
npm i -S crypto
  1. 创建 md5 方法:
const crypto = require('crypto')

function md5(s) {
  // 注意参数需要为 String 类型,否则会出错
  return crypto.createHash('md5')
    .update(String(s)).digest('hex');
}

看别人说MD5加密好像可以破解,采用MD5+Salt加密可以更加安全。

express-validator 表单验证

express-validator 是一个功能强大的表单验证器,它是 validator.js 的中间件。
它验证请求的body, params, query, headers 和 cookies ,并且如果任何配置的验证规则失败,返回一个错误的响应;
相关地址:https://github.com/express-validator/express-validator
https://www.kutu66.com//GitHub/article_76137
基本使用方法:

  1. 安装
npm install express-validator
  1. 验证
    在请求当中的第二个参数添加一个数组,数组为校验规则,然后使用body方法进行校验。
const { body, validationResult } = require('express-validator')
const boom = require('boom')

router.post(
  '/login',
  [
  	//  body 方法判断参数类型是否为字符串,并指定出错时的提示信息
    body('username').isString().withMessage('username类型不正确'),
    body('password').isString().withMessage('password类型不正确')
  ],
  function(req, res, next) {
  	//使用 const err = validationResult(req) 获取错误信息,err.errors 是一个数组,包含所有错误信息,如果 err.errors 为空则表示校验成功,没有参数错误
    const err = validationResult(req)
    // 判断是否有错误
    if (!err.isEmpty()) {
      //存在错误。msg为错误消息,然后这里将其穿个下个错误中间件处理。
      // const msg = err.error
      const [{ msg }] = err.errors   // 数组加对象的双重解构
      next(boom.badRequest(msg))
    } else {
      const username = req.body.username
      const password = md5(`${req.body.password}${PWD_SALT}`)

      login(username, password).then(user => {
        if (!user || user.length === 0) {
          new Result('登录失败').fail(res)
        } else {
          new Result('登录成功').success(res)
        }
      })
    }
  })

JWT 解析 express-jwt

有使用JWT的认证,当然也需要JWT的解析啦,关于JWT的使用可以看我另外一篇文章:
Node 生成 JWT Token的使用方法
相关地址:https://github.com/auth0/express-jwt
基本使用方法:

  1. 安装
npm i -S express-jwt
  1. 可以选择创建一个用于JWT解析的文件
// 用于验证指定http请求的JsonWebTokens的有效性
const expressJwt = require('express-jwt')
const { PRIVATE_KEY } = require('../utils/constant')

const jwtAuth = expressJwt({
  secret: PRIVATE_KEY, //  签名的密钥 或 PublicKey
  credentialsRequired: true, // 设置为false就不进行校验了,游客也可以访问
}).unless({
  path: [
    '/',
    '/user/login',
    //jwt的白名单,在该名单内说明不会进行校验
  ],
})

module.exports = jwtAuth
  1. 在需要用到的地方使用该中间件
const jwtAuth = require('./jwt')

// 注册路由
const router = express.Router()

// 对所有路由进行 jwt 认证
router.use(jwtAuth)

文件上传 multer

multer 用于处理 multipart/form-data 类型的表单数据,它主要用于上传文件。
相关链接:https://github.com/expressjs/multer

基本使用方法:

  1. 安装
npm install -S multer 
  1. 使用
    Multer在解析完请求体后,会向Request对象中添加一个body对象和一个file或files对象(上传多个文件时使用files对象 )。其中,body对象中包含所提交表单中的文本字段(如果有),而file(或files)对象中包含通过表单上传的文件。
const express = require('express')
const { UPLOAD_PATH } = require('../utils/constant')
// 文件上传
const multer = require('multer')
const router = express.Router()

router.post(
  '/upload',
  // dest为上传的目标目录,single表示上传单个文件,同时req对象中添加该文件。
  multer({ dest: `${UPLOAD_PATH}/book` }).single('file'),
  function (req, res) {
    // req.file为一个数组
    if (!req.file || req.file.length === 0) {
      // 如果不存在,上传失败
      return
    } else {
      // 上传成功
    }
  }
)

module.exports = router

多文件的上传可以使用以下方法:

router.post('/', multer({
    //设置文件存储路径
    dest: 'upload'
}).array('file', 10), function (req, res, next) {  //这里10表示最大支持的文件上传数目
    let files = req.files;  //获取文件的上传信息
    if (files.length === 0) {
      // 上传失败
      return
  	  } else {
    	// 上传成功
      }
    }
});

如果您也正在学习前端的路上,记得关注该博主,学习更多关于前端的知识~

博主主页 Poetic Code

评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值