Express核心之中间件

Express核心之中间件

前言

Express的官方描述是:一个基于Node.js平台的快速,开放,极简的web框架。这句话中有两个关键词:web

  1. 基于Node。说明Express的初衷就是为了拓展Node的功能,从而提升开发效率。
  2. web框架。说明Express主要是为了更加方便处理HTTP请求和响应。

总而言之,Express其实就是在Node内置的HTTP模块上构建了一层抽象,理论上全部Express可以实现的功能, 均可以经过Node来实现。相比于Node,Express具备的优点:数据库

  • 更加方便地处理HTTP请求与响应(对 request 和 response 对象方法进行了拓展。)
  • 更加方便地链接数据库
  • 更加方便的路由(路由语法糖)
  • 更加方便地渲染模板(容许动态渲染和改变 HTML 内容,而且使用其余语言编写 HTML)

中间件

中间件(Middleware) 是一个函数,它能够访问请求对象(request), 响应对象(response), 和 web 应用中处于请求-响应循环流程中的 next的变量。接下来咱们先编写一个简单的express应用,看看究竟中间件是什么?express

const express = require('express');
const app = express();  const fn = (req, res, next) => {  console.log("hello,world"); }; app.use(fn) const port = 3000; app.listen(port,() => {  console.log(`应用运行在${port}端口`); }) 复制代码

当咱们访问localhost:3000时就会发现,打印出了函数fn中的hello,world。这里的函数fn就是一个中间件,app.use(fn)就是运行这个中间件,实现他的功能。事实上,整个Express的功能就是由中间件组成,中间件具备的功能包括:编程

  1. 执行任何代码。若是没有主动停止,会一直执行全部的中间件。
  2. 调用堆栈中的下一个中间件。若是没有终结请求-响应循环,则必须调用 next() 方法将控制权交给下一个中间件。不然当前程序会被挂起
  3. 终结请求-响应循环。终结请求-响应循环后,以后的中间件再也不执行。

咱们经过代码看一下中间件的这些功能:cookie

const express = require('express');
const app = express(); // 第一个中间件 app.use((req, res, next) => {  console.log("中间件1");  next();// 若是没有next则会被挂起 }) // 第二个中间件 app.use((req, res, next) => {  console.log("中间件2"); //继续执行第二个中间件  next(); }) // 第三个中间件 app.use((req, res, next) => {  console.log("中间件3");  res.send('hello'); // 终结请求-响应循环 }) // 第四个中间件 app.use((req, res, next) => {  console.log("中间件4"); // 中介后的中间件再也不执行 }); const port = 3000; app.listen(port,() => {  console.log(`应用运行在${port}端口`); }) 复制代码

最终的输出结果为:中间件1,中间件2,中间件3。从上面的代码中咱们能够知道,若是没有停止请求-响应循环,会执行全部的中间件;若是不是最后一个停止的中间件,必须执行next()。 咱们看一下express中间件的模型: 从上面的编程模型,咱们能够看出每个中间件就是插入到请求开始和响应结束中间的东西,这也是中间件名字的由来。session

中间件的优势——模块化

中间件的最大优势就是模块化,每个中间件是一个独立的函数,实现一个特定的功能,而后经过app.sue将这个函数整合起来。抽离出来就是一个单独的模块。好比,咱们要实现一个功能,获取当前请求的url,那么咱们就能够将这个功能,封装成一个中间件。app

//实现获取url的模块,封装成中间件
const fn = (req, res, next) => {  const url = req.url;  console.log(url);  next(); };  app.use(fn);  const port = 3000; app.listen(port,() => {  console.log(`应用运行在${port}端口`); }) 复制代码

中间件的分类

Express中的中间件,根据做用范围大体能够分为应用级中间件和路由级中间件。事实上中间件的分类并无特别明显的区别。框架

  • 应用级中间件 app.use()以及它的一些语法糖中使用的中间件
  • 路由级中间件 router.use(),以及它的一些语法糖中使用的中间件

应用级中间件

应用级中间件主要是经过app.use(),以及它的一些语法糖中应用的中间件。编辑器

const express = require('express');
const app = express(); // 应用级中间件 app.use((req, res, next) => {  const url = req.url;  next(); });  // 应用级中间件 app.get('/user',(req,res) => {  res.send('应用级中间件'); }) const port = 3000; app.listen(port,() => {  console.log(`应用运行在${port}端口`); }) 复制代码

上面的代码中,咱们调用了两个中间件,一个是app.use()直接调用的中间件,另一个是app.use的语法糖app.get()执行的中间件,为何说app.get()是app.use()的语法糖,由于app.get可以实现的方法使用app.use都可以实现。咱们试着将上面app.get的中间件用app.use实现。模块化

app.use((req,res,next) => {
 console.log(req.path)  if(req.method === "GET" && req.path == '/users'){  res.send('使用app.use实现的中间件');  } }) // 功能上等价于 app.get('/user',(req,res) => {  res.send('应用级中间件'); }) 复制代码

路由级中间件

const express = require('express');
const app = express();  // 定义一个路由 const user = express.Router(); user.use("/", (req, res) => {  res.send("user.use"); }); user.get("/user", (req, res) => {  res.send("路由级别中间件"); }); user.get("/blog", (req, res) => {  res.send("路由级中间件"); });  const port = 3000; app.listen(port,() => {  console.log(`应用运行在${port}端口`); })  复制代码

路由级中间件是经过使用express内置的Router生成一个小应用,这个应用跟app具备相同的功能,只不过它主要的功能是用来实现路由。 这种路由功能能够很方便地帮助咱们进行路由模块化开发。咱们能够将相关的路由弄到同一个模块当中。好比上面的user和blog路由能够抽成 user子路由模块和blog子路由模块。示例以下:

const express = require('express');
const app = express();  const user = require('./routes/user.js'); const blog = require('./routes/blog.js'); // 抽离子路由 app.use('/user',user); app.use('/blog',blog); const port = 3000; app.listen(port,() => {  console.log(`应用运行在${port}端口`); }) 复制代码

以后只要路径是/user的都会交给user这个子路由去处理。子路由user.js中代码以下:

const express = require('express');
 const router = express.Router(); router.get('/',(req,res) => {  res.send('这里是user路由'); }) module.exports = router; 复制代码

开发中间件

在上面的讲述中,咱们知道中间件是一个函数,它是嵌入到一个请求和响应循环中的一个独立的功能块。函数的参数是req,res,next。所以编写一个中间件就显得很简单了。至关于编写一个函数,参数为req,res,next。

// 定义
const getUrl = (req,res,next) => {  console.log(req.url);  next(); } // 使用 app.use(getUrl) 复制代码

从上面的代码咱们能够看出,开发一个中间件就是编写一个函数。可是有时候为了可以配置一些参数,咱们一般是返回一个函数,好比这样:

const getUrl2 = (options) => {
 return () => {  console.log(`${options.pre}+req.url`);  next();  } } app.use(getUrl2({pre:'url:'})) 复制代码

这样的话,就须要app.use(getUrl())这样执行了。这就是为何咱们常常看到app.use(bodyParser())这样的使用方法了。实际上返回的仍是一个函数,只是为了方便配置参数罢了。

经常使用中间件

最后咱们例举一些express经常使用的中间件

  • express.static express自带的中间件,用于访问静态文件
  • body-parser 第三方中间件,用于解析post数据
  • cookie-parser 第三方中间件,用于处理cookie
  • cookie-session 第三方中间件,用于处理session
  • bcrypt 第三方中间件,用于加密
  • passport 第三方中间件,用于鉴权
  • passport-jwt 第三方中间件,用于jwt鉴权

总结

到目前为止,咱们详细介绍了Express的核心中间件,从中间件的详细理解到中间件的分类和使用,以及中间件的编写,最后列举了一些常见的中间件。经过本文咱们基本上就可以掌握Express的核心功能了,其余的Express的API都是中间件的使用罢了。

本文使用 mdnice 排版

相关文章
相关标签/搜索