[关闭]
@bornkiller 2014-10-14T15:55:25.000000Z 字数 2828 阅读 2254

Expresss 路由

nodejs


前言

Express提供了三种路由方案,path, Router, route。中间件哲学,每个负责具体业务实现,都与中间件行为相似。同时提供了三种路由方式,各有优劣。

路由特别说明

使用app.use()方式,所有以path参数开头的路径,都会使用该中间件,具体的HTTP verb则为完全匹配方式。

  1. // will match paths starting with /abcd
  2. app.use('/abcd', function (req, res, next) {
  3. next();
  4. })

每次请求,都会先做路径匹配,判定需要调用哪些函数,然后按序调用。app.param()则在序列开始前调用,用以路径参数合法化检查。

  1. app.param('identity', function(req, res, next, identity) {
  2. if (/^[A-Za-z]+$/.test(identity)) {
  3. next();
  4. } else {
  5. res.status(404).end();
  6. }
  7. });
  8. app.get('/author/:identity', function(req, res) {
  9. res.send('hello world!');
  10. });

如果路径全为字母,则向下调用,否则不进入调用序列。测试如下:

  1. describe('express param', function () {
  2. it('param identity pass', function (done) {
  3. request
  4. .get('/author/angular')
  5. .expect(200)
  6. .end(done);
  7. });
  8. it('param identity pending', function (done) {
  9. request
  10. .get('/author/angular12')
  11. .expect(404)
  12. .end(done);
  13. });
  14. });

文档貌似示例可以这样写,但在本机上测试未成功。

  1. app.param('identity', /^[A-Za-z]+$/);

不建议在这个地方过于深究,大概了解作用即可。

路由定义

简单情况之下,可以直接使用path定义路由。

  1. app.use('/', function(req, res, next) {
  2. next();
  3. });

所有/开头的路径都会引用处理,非常方便使用。假设nodejs实现restful API,需要定义resource。假设blog为资源,使用path方式实现如下

  1. app.get('/blog/', function(req, res) {
  2. res.send('blog list');
  3. });
  4. app.get('/blog/:identity', function(req, res) {
  5. res.send('blog content');
  6. });
  7. app.post('/blog/:identity', function(req, res) {
  8. res.send('blog update');
  9. });
  10. app.put('/blog/', function(req, res) {
  11. res.send('blog create');
  12. });
  13. app.delete('/blog/:identity', function(req, res) {
  14. res.send('blog delete');
  15. });

使用Router方式如下实现:

  1. var blog = express.Router();
  2. blog.get('/', function(req, res) {
  3. res.send('blog list');
  4. });
  5. blog.get('/:identity', function(req, res) {
  6. res.send('blog content');
  7. });
  8. blog.post('/:identity', function(req, res) {
  9. res.send('blog update');
  10. });
  11. blog.put('/', function(req, res) {
  12. res.send('blog create');
  13. });
  14. blog.delete('/:identity', function(req, res) {
  15. res.send('blog delete');
  16. });
  17. app.use('/blog', blog);

从代码上看出,使用Router并不会节省代码,而且结构高度相似。但是单个url更短,构建restful API时,更加直观。私以为使用Router方式效率更高,所以做了一个简单测试。定义了四个resourceauthor, blog, comment, draft,分别使用path, Router来实现,大概实现代码更上面所述高度相似,不在赘述。

  1. app.use(function(req, res, next) {
  2. console.log('routerA start time stamp %d', Date.now());
  3. next();
  4. });

在最上方使用此方式,用以记录参照时间。在请求URL函数中,输出当前时间戳,用以比较时间消耗。输出结果如下(routerA为采用Router方式,routerB为采用path方式):

  1. /usr/local/bin/node routerA.js
  2. routerA start time stamp 1413270521788
  3. routerA end time stamp 1413270521800
  4. /usr/local/bin/node routerB.js
  5. routerB start time stamp 1413270521826
  6. routerB end time stamp 1413270521836

测试结果pathRouter方式快2ms,差距不大,但与预期结果相反,可能是测试方式存在错误,并不表示公正。速度并不是考虑因素,而是应该考虑具体的借口方式。如果是restful API,建议采用Router方式,梳理起来更加轻松。再看一下app.route()使用方式。

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

其返回对象可以使用HTTP verbs以及其他中间件处理函数,唯一需要注意的点,get等方法只接受一个类中间件函数作为参数,不能传入值做URL处理。

  1. app.route('/route')
  2. .get('/event', function(req, res) {
  3. res.send('route get shuffle');
  4. })

这种处理方式错误。

总结

路由定义,path方式万能,适合所有情况。Router方式通常为路径前缀统一的情况使用,如定义resourceroute方式通常为路径统一的情况使用,通常应该见于面向URL的API定义。总结来说,只是为了接口定义在代码层级的梳理,让接口定义方式更加优雅。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注