Contents
  1. 1. express简介
    1. 1.1. 什么是express
    2. 1.2. express安装
  2. 2. express中间件
    1. 2.1. 什么是中间件
    2. 2.2. 中间件的功能
    3. 2.3. 应用级中间件
    4. 2.4. 路由级中间件
    5. 2.5. 错误处理中间件
    6. 2.6. 内置中间件
    7. 2.7. 第三方中间件
  3. 3. 跳过中间件

最近在开发一个简单的购书平台,后端采用node.js+express+mongoDB+mogoose来向前端输出数据(api),而前端则采用vue.js以及相关vue插件(比如vue-resource和vue-router等)来实现逻辑和UI。

等这个小Demo完成之后,我会再从头捋一遍,并且整理下这个过程中遇到的技术难点。而今天,就简单总结以下对express框架中间件的学习和理解。

express简介

什么是express

express是基于node.js的一个web开发框架,它提供了丰富的http方法和任意排列组合的中间件,让我们可以方便地创建健壮、友好的API。

express安装

我们可以通过以下两条命令,在我们的项目中安装express:

1
2
$ npm init
$ npm install express --save //安装express并且将依赖写入package.json

这样我们只是局部安装了express,项目的目录结构还未能初始化,我们需要手动建立。

现在,我们有了express-generator这个工具,它可以帮我们快速创建一个应用的骨架

1
2
3
4
5
6
7
8
9
// 全局安装express-generator
$ npm install express-generator -g
// 创建一个命名为myapp的应用
$ express myapp
$ cd myapp
// 安装所有依赖
$ npm install
// 启动项目,supervisor会监听项目代码变化,并且自动帮我们重启项目
$ supervisor app.js

express中间件

从本质上来说,Express就是在调用各种中间件。

什么是中间件

中间件(Middleware)是一个函数,它可以访问请求对象(req)、响应对象(res),和web应用中处于请求-响应循环流程中的中间件,一般被命名为next变量。

中间件函数的形式如下;

1
function (req, res, next)

给某个路径应用中间件函数的典型场景如下:

1
2
3
4
app.use('/api', function (req, res, next)) {
console.log(req.baseUrl);
next();
});

中间件的功能


  1. 执行任何代码
  2. 修改请求和响应对象
  3. 终结请求-响应循环
  4. 调用堆栈中的下一个中间件

应用级中间件

应用级中间件绑定到app对象上,使用app.use()app.METHOD()来加载。其中,METHOD是需要处理的http请求的方法,如GET、POST、PUT、DELETE等,全部小写


我们先来看app.use()。

express中通过use方法来注册中间件。

而use方法允许将请求网址写在第一个参数。这代表,之后请求路径匹配这个参数,后面的中间件才会生效

当然也可以不写网址,那么只要该中间件在请求-响应流程中,那么该中间件总会被执行


再来看一下app.METHOD()形式的路由方法。

它的基本使用模式如下:

1
2
3
// 其中callback的行为类似中间件
// 其唯一的区别就是这些回调函数可以调用next('route')方法而略过其他路由回调函数
app.METHOD(path, [callback...], callback);

app.all()是一个特殊的路由方法,没有任何HTTP方法与其对应,它的作用是对于一个路径上的所有请求加载中间件

1
2
3
4
5
// 只要请求路径为/secret,无论是GET、POST或是其他请求,都执行中间件函数
app.all('/secret', function (req, res, next) {
console.log('secret...');
next();
});

下面是一个基本的使用场景:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var app = express();
// 没有挂载路径的中间件,应用的每个请求都会执行该中间件
app.use(function (req, res, next) {
console.log('Request Type:', req.method);
next();
});
// 挂载至/user/:id的中间件,任何指向/user/:id的请求都会执行它
app.use('/user/:id', function (req, res, next) {
res.send('hello...'); // 此次请求-响应的循环结束,后面的中间件不会执行
});
// 一个中间件栈,对指向/home的GET请求作出处理
app.get('/home', function(req, res, next) {
console.log('Request URL:', req.originalUrl);
next(); // 调用中间件栈中的下一个中间件
}, function (req, res, next) {
res.end('end...'); // 此次请求-响应的循环结束,后面中间件不会执行
});
// 只有上面路径没有匹配到,才执行这个中间件
// 参数中的*表示对所有路径有效
app.get('*', function(req, res, next) {
response.writeHead(404, { "Content-Type": "text/plain" });
response.end("404 error!");
});

路由级中间件

路由级中间件和应用级中间件一样,只是它绑定的对象为express.Router()

1
var router = express.Router();

路由级中间件使用router.use()或者router.VERB()加载。

上面的应用场景可以改写为以下的样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var app = express();
var router = express.Router();
// 没有挂载路径的中间件,通过该路由的所有请求都会执行该中间件
router.use(function (req, res, next) {
console.log('Request Type:', req.method);
next();
});
// 挂载至/user/:id的中间件,任何指向/user/:id的请求都会执行它
router.use('/user/:id', function (req, res, next) {
console.log('id:' + req.params.id);
res.send('hello...'); // 此次请求-响应的循环结束,后面的中间件不会执行
});
// 一个中间件栈,对指向/home的GET请求作出处理
router.get('/home', function(req, res, next) {
console.log('Request URL:', req.originalUrl);
next(); // 调用中间件栈中的下一个中间件
}, function (req, res, next) {
res.end('end...'); // 此次请求-响应的循环结束,后面中间件不会执行
});
// 只有上面路径没有匹配到,才执行这个中间件
router.get('*', function(req, res, next) {
response.writeHead(404, { "Content-Type": "text/plain" });
response.end("404 error!");
});
// 将路由挂载至应用
// 相当于为/api/home和/api/user/:id这两个请求路径,指定了回调函数
app.use('/api', router)

另外,router.route()方法可以接受访问路径作为参数,它等同于app.route(),它其实是express.Router()的缩写形式。

通过router.route()或者app.route(),我们可以链式地处理对一个路径的不同请求

1
2
3
4
5
6
7
app.route('/login')
.get(function(req, res) {
res.send('get login success...');
})
.post(function(req, res) {
res.send('post login success...');
});

错误处理中间件

错误处理中间件和其他中间件类似,不过必须使用4个参数,而不是3个。其使用场景如下:

1
2
3
4
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('error...');
});

内置中间件

express static()是Express唯一内置的中间件。它主要负责在Express应用中托管静态资源。

1
express.static(root, [options]);

其中参数root指提供静态资源的根目录
options为可选参数,详细可以参考这里

第三方中间件

第三方中间件需要我们手动安装对应的node模块,并且在应用中加载。
比如cookie-parser这个中间件:

1
$ npm install cookie-parser --save

然后在应用中使用:

1
2
3
4
5
6
var express = require('express');
var cookieParser = require('cookie-parser');
// 加载用于解析cookie的中间件
var app = express();
app.use(cookieParser());

这里可以查看经常用到的第三方中间件。

跳过中间件

如果想要在中间件栈中跳过某个中间件,我们可以调用next('route')方法将控制权交给下一个路由。

不过要注意的是,next(‘route’)只对使用app.VERB()或者router.VERB()加载的中间件有效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 一个中间件栈,处理指向 /user/:id 的 GET 请求
app.get('/user/:id', function (req, res, next) {
// 如果 user id 为 0, 跳到下一个路由
if (req.params.id == 0) next('route');
// 否则将控制权交给栈中下一个中间件
else next(); //
}, function (req, res, next) {
// 渲染常规页面
res.render('regular');
});
// 处理 /user/:id, 渲染一个特殊页面
app.get('/user/:id', function (req, res, next) {
res.render('special');
});

完。

Contents
  1. 1. express简介
    1. 1.1. 什么是express
    2. 1.2. express安装
  2. 2. express中间件
    1. 2.1. 什么是中间件
    2. 2.2. 中间件的功能
    3. 2.3. 应用级中间件
    4. 2.4. 路由级中间件
    5. 2.5. 错误处理中间件
    6. 2.6. 内置中间件
    7. 2.7. 第三方中间件
  3. 3. 跳过中间件