了解下Express
路由
虽说第一项是路由。不过首先,还是应该安装一下express。 1
npm install express --save
app.METHOD(path, [callback...], callback) 其中app是express的一个实例, METHOD是一个HTTP请求方法, callback是当路径匹配时要执行的函数。
示例 1
2
3
4
5
6
7
8
9
10const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.send('hello world')
})
app.listen(3000, () => {
console.log('服务开始在3000端口')
})
路由方法
路由方法源自HTTP请求方法。
Express定义了以下与HTTP对应的方法:get, post, put, head, delete, options, trace, copy, lock, mkcol, move, purge, propfind, proppatch, unlock, report, mkactivity, checkout, merge, m-search, notify, subscribe, unsubscribe, patch, search和connect。 其中JS不合法的需要使用括号记法,比如:app['m-search'].('/', callback...)
app.all 也是method,它匹配的任何HTTP请求,句柄都会执行。 1
2
3
4app.all('/secret', (req, res, next) => {
console.log('handle the secret!')
next() // 处理写一个句柄,相当于promise中的promise.resolve()
})
路由路径
路由路径和请求方法一起定义了请求的端点,它可以是字符串、字符串模式或者正则表达式。根据精确度排序匹配率排序 字符串>字符串模式>正则表达式
1 | // 字符串 |
路由句柄
可以为请求处理提供多个回调函数,行为类似中间件。唯一的区别,这些回调函数可能通过next('route')方法而略过其他路由回调函数。可以利用该机制为路由定义前提条件,如果在现有路径继续执行没有意义,则可将控制权交给剩下的路径。
路由句柄有多种形式,可以是一个函数、一个函数数组,或者是两者混合,如下所示.
使用多个回调函数处理路由(记得指定 next 对象): 1
2
3
4
5
6app.get('/example/b', function (req, res, next) {
console.log('response will be sent by the next function ...');
next();
}, function (req, res) {
res.send('Hello from B!');
});
使用回调函数数组处理路由: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15var cb0 = function (req, res, next) {
console.log('CB0');
next();
}
var cb1 = function (req, res, next) {
console.log('CB1');
next();
}
var cb2 = function (req, res) {
res.send('Hello from C!');
}
app.get('/example/c', [cb0, cb1, cb2]);
响应方法
下表中响应对象(res)的方法向客户端返回响应,终结请求响应的循环。如果在路由句柄中一个方法也不调用,来自客户端的请求会一直挂起。
| 方法 | 描述 |
|---|---|
| res.download() | 提示下载文件。 |
| res.end() | 终结响应处理流程。 |
| res.json() | 发送一个 JSON 格式的响应。 |
| res.jsonp() | 发送一个支持 JSONP 的 JSON 格式的响应。 |
| res.redirect() | 重定向请求。 |
| res.render() | 渲染视图模板。 |
| res.send() | 发送各种类型的响应。 |
| res.sendFile | 以八位字节流的形式发送文件。 |
| res.sendStatus() | 设置响应状态代码,并将其以字符串形式作为响应体的一部分发送。 |
app.route()
可使用 app.route() 创建路由路径的链式路由句柄。由于路径在一个地方指定,这样做有助于创建模块化的路由,而且减少了代码冗余和拼写错误。 对于同一个路径不同method的链式路由句柄 1
2
3
4
5
6
7
8
9
10app.route('/book')
.get(function(req, res) {
res.send('Get a random book');
})
.post(function(req, res) {
res.send('Add a book');
})
.put(function(req, res) {
res.send('Update the book');
});
express.Router
可使用 express.Router 类创建模块化、可挂载的路由句柄。Router 实例是一个完整的中间件和路由系统,因此常称其为一个 “mini-app”。
在 app 目录下创建名为 birds.js 的文件,内容如下:
1 | var express = require('express'); |
然后在应用中加载路由模块: 1
2
3var birds = require('./birds');
...
app.use('/birds', birds);
中间件
Express框架实现功能就相当于在调用相关的中间件(Middleware),它可访问request和response 它的功能包括: * 执行任何代码。 * 修改请求和响应对象。 * 终结请求-响应循环。 * 调用堆栈中的下一个中间件。
如果当前中间件没有终结请求-响应循环,则必须调用 next() 方法将控制权交给下一个中间件,否则请求就会挂起。
Express 应用可使用如下几种中间件: * 应用级中间件 * 路由级中间件 * 错误处理中间件 * 内置中间件 * 第三方中间件
应用级中间件
应用级中间件绑定到 app 对象 使用 app.use() 和 app.METHOD() 1
2
3
4// 路由和句柄函数(中间件系统),处理指向 /user/:id 的 GET 请求
app.get('/user/:id', function (req, res, next) {
res.send('USER');
}); // :id 由req.params.id 来获取
调用next('route')时,会跳过剩余中间件
如果需要在中间件栈中跳过剩余中间件,调用 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');
});
路由级中间件
路由级中间件和应用级中间件一样,只是它绑定的对象为 express.Router()。
错误处理中间件
错误处理中间件有 4 个参数,定义错误处理中间件时必须使用这 4 个参数。即使不需要 next 对象,也必须在签名中声明它,否则中间件会被识别为一个常规中间件,不能处理错误。
错误处理中间件和其他中间件定义类似,只是要使用 4 个参数,而不是 3 个,其签名如下: (err, req, res, next)。 1
2
3
4app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
内置中间件
内置中间件只有一个express.static 。负责Express应用中托管静态资源。用法: express.static(root, [options])
可选options: |属性|描述|类型|缺省值| |----|---|---|-----| |dotfiles|是否对外输出文件名以点(.)开头的文件。可选值为 “allow”、“deny” 和 “ignore”|String|“ignore”| |etag|是否启用 etag 生成|Boolean|true| |extensions|设置文件扩展名备份选项|Array|[]| |index|发送目录索引文件,设置为 false 禁用目录索引。|Mixed|“index.html”| |lastModified|设置 Last-Modified 头为文件在操作系统上的最后修改日期。可能值为 true 或 false。|Boolean|true| |maxAge|以毫秒或者其字符串格式设置 Cache-Control 头的 max-age 属性。|Number|0| |redirect|当路径为目录时,重定向至 “/”。|Boolean|true| |setHeaders|设置 HTTP 头以提供文件的函数。|Function||
下面的例子使用了 express.static 中间件,其中的 options 对象经过了精心的设计。 1
2
3
4
5
6
7
8
9
10
11
12
13var options = {
dotfiles: 'ignore',
etag: false,
extensions: ['htm', 'html'],
index: false,
maxAge: '1d',
redirect: false,
setHeaders: function (res, path, stat) {
res.set('x-timestamp', Date.now());
}
}
app.use(express.static('public', options));
每个应用可有多个静态目录。当然也可以分别设置options。
1 | app.use(express.static('public')); |
更多关于 serve-static 和其参数的信息,请参考 serve-static 文档。 ## 第三方中间件 通过使用第三方中间件从而为 Express 应用增加更多功能。
安装所需功能的 node 模块,并在应用中加载,可以在应用级加载,也可以在路由级加载。
下面的例子安装并加载了一个解析 cookie 的中间件: cookie-parser 1
$ npm install cookie-parser
1 | var express = require('express'); |
请参考 第三方中间件 获取 Express 中经常用到的第三方中间件列表。
- 本文标题:了解下Express
- 本文作者:hddhyq
- 本文链接:https://hddhyq.github.io/2017/11/11/了解下Express/
- 版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!