最近在开发一个简单的购书平台,后端采用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,项目的目录结构还未能初始化,我们需要手动建立。
现在,我们有了express-generator这个工具,它可以帮我们快速创建一个应用的骨架:
1 2 3 4 5 6 7 8 9
| $ npm install express-generator -g $ express myapp $ cd myapp $ npm install $ 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(); });
|
中间件的功能
- 执行任何代码
- 修改请求和响应对象
- 终结请求-响应循环
- 调用堆栈中的下一个中间件
应用级中间件
应用级中间件绑定到app对象上,使用app.use()和app.METHOD()来加载。其中,METHOD是需要处理的http请求的方法,如GET、POST、PUT、DELETE等,全部小写。
我们先来看app.use()。
express中通过use方法来注册中间件。
而use方法允许将请求网址写在第一个参数。这代表,之后请求路径匹配这个参数,后面的中间件才会生效。
当然也可以不写网址,那么只要该中间件在请求-响应流程中,那么该中间件总会被执行。
再来看一下app.METHOD()形式的路由方法。
它的基本使用模式如下:
1 2 3
| app.METHOD(path, [callback...], callback);
|
app.all()是一个特殊的路由方法,没有任何HTTP方法与其对应,它的作用是对于一个路径上的所有请求加载中间件。
1 2 3 4 5
| 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(); }); app.use('/user/:id', function (req, res, next) { res.send('hello...'); }); 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(); }); router.use('/user/:id', function (req, res, next) { console.log('id:' + req.params.id); res.send('hello...'); }); 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!"); }); 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'); 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
| app.get('/user/:id', function (req, res, next) { if (req.params.id == 0) next('route'); else next(); }, function (req, res, next) { res.render('regular'); }); app.get('/user/:id', function (req, res, next) { res.render('special'); });
|
完。