码迷,mamicode.com
首页 > 其他好文 > 详细

express路由探析(续)

时间:2014-11-05 01:51:32      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   io   color   ar   for   sp   strong   

  上一篇分析了express的路由机制,这次主要补充一些没有说到的东西。

  之前说到,Router是中间件容器,Route是路由中间件,他们各自维护一个stack数组,里面存放layer,layer是封装中间件的一个数据结构。其实Router中不仅能存放一般的中间件,还能存放Router,这一点在源码中能看的出来,因为Router的构造函数中返回的是一个router函数,而中间件的生成也需要一个处理程序(函数),那么如果把Router()返回的处理程序作为参数传入中间件的生成方法中,就相当于Router中存放了一个Router中间件,只不过这两个Router是两个不同的实例。app.Router是最顶层的,里面可以包含新的Router,新的Router是作为中间件添加到app.Router的,由于Router的结构设计,可以保证访问到里面每个中间件的处理程序,包括嵌套的Router里面的每个中间件。从express -e projectName命令生成的项目模型中就包括这种用法,下面是projectName项目根目录(不是express根目录)下的app.js文件:

var express = require(express);
var path = require(path);
var favicon = require(serve-favicon);
var logger = require(morgan);
var cookieParser = require(cookie-parser);
var bodyParser = require(body-parser);

var routes = require(./routes/index);
var users = require(./routes/users);

var fs = require(fs);

var app = express();  

// view engine setup
app.set(views, path.join(__dirname, views));
app.set(view engine, ejs);

// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + ‘/public/favicon.ico‘));
app.use(logger(dev));  //从这里这里开始添加中间件,因为之前没添加过,所以会实例化一个Router,在实例化的时候会添加两个中间件(query和init),因此这个中间件是第三个
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, public)));

app.use(/, routes); //routes是“./routes/index.js”文件中创建的Router实例,也就是通过这句代码在顶层Router里面添加了新的Router
app.use(/users, users);

//var count = routes.stack.length;
var count = app._router.stack.count;
var content = "";
console.log(count);
/*for (var i = 0; i<count; i++) {
    content+=dump_obj(routes.stack[i]) + "\r\n\r\n";
    console.log(app._router.stack[i]);
};*/

console.log(app._router.stack[7]);  //输出顶层Router中的一个特殊中间件,即app.use(‘/‘,routes)语句添加的routes,该中间件也是Router对象

/*fs.writeFile(‘message.txt‘, content, function (err) {
  if (err) throw err;
  console.log(‘It\‘s saved!‘);
});

function dump_obj(myObject) {  
  var s = "";  
  for (var property in myObject) {  
   s = s + "\n "+property +": " + myObject[property] ;  
  }  
  return s;
}*/
// catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error(Not Found); err.status = 404; next(err); }); // error handlers // development error handler // will print stacktrace if (app.get(env) === development) { app.use(function(err, req, res, next) { res.status(err.status || 500); res.render(error, { message: err.message, error: err }); }); } // production error handler // no stacktraces leaked to user app.use(function(err, req, res, next) { res.status(err.status || 500); res.render(error, { message: err.message, error: {} }); }); module.exports = app;

下面是./routes/index.js的代码,在里面新实例化了一个Router对象,然后在该对象上添加了5个中间件

var express = require(express);
var router = express.Router();  //这里新实例化一个Router,直接调用app(application.js)中的app.use()或app[method]能保证在app中的Router实例只有一个,但是我们仍然可以再手动实例化新的Router,app.Router其实是最顶层的中间件容器,只能有一个

var users = {
    byvoid:{
        name : "Carbo",
        website : http://www.byvoid.com
    }
};

/*--------- test start 下面是测试代码,在新创建的Router中添加中间件,待会儿要输出进行验证 ---------*/
var route = router.route(/user);
route.get(function(req,res,next){},function(req,res){});  //第一个中间件添加了两个处理函数,下面的输出会进行验证

router.all(user/:username,function(req,res,next){
    if(users[req.params.username]){
        next();
    }
    else{
        next(new Error(req.params.username+does not exist.));
    }
});

router.get(/user/:username,function(req,res){
    res.send(JSON.stringify(users[req.params.username]));
});

router.get(‘/user/:username‘,function(req,res){
    res.send(‘user:‘ + req.params.username);
});
/*--------- test end -----------*/
 
/* GET home page. */
router.get(‘/‘, function(req, res) {
  res.render(‘index‘, { title: ‘Express‘ });
});

module.exports = router;

运行后的输出如下:

新创建的Router(这里只是作为一个中间件): /*该Router对象中添加了5个中间件,可以看到第一个中间件的stack中有两个元素,与上面代码相对应,这里用橙色标出*/

{ path: ‘/user‘,

  stack: 

   [ { handle: [Function],

       name: ‘<anonymous>‘,

       params: undefined,

       path: undefined,

       keys: [],

       regexp: /^\/?$/i,

       method: ‘get‘ },

     { handle: [Function],

       name: ‘<anonymous>‘,

       params: undefined,

       path: undefined,

       keys: [],

       regexp: /^\/?$/i,

       method: ‘get‘ } ],

  methods: { get: true } }

{ path: ‘user/:username‘,

  stack: 

   [ { handle: [Function],

       name: ‘<anonymous>‘,

       params: undefined,

       path: undefined,

       keys: [],

       regexp: /^\/?$/i,

       method: undefined } ],

  methods: { _all: true } }

{ path: ‘/user/:username‘,

  stack: 

   [ { handle: [Function],

       name: ‘<anonymous>‘,

       params: undefined,

       path: undefined,

       keys: [],

       regexp: /^\/?$/i,

       method: ‘get‘ } ],

  methods: { get: true } }

{ path: ‘/user/:username‘,

  stack: 

   [ { handle: [Function],

       name: ‘<anonymous>‘,

       params: undefined,

       path: undefined,

       keys: [],

       regexp: /^\/?$/i,

       method: ‘get‘ } ],

  methods: { get: true } }

{ path: ‘/‘,

  stack: 

   [ { handle: [Function],

       name: ‘<anonymous>‘,

       params: undefined,

       path: undefined,

       keys: [],

       regexp: /^\/?$/i,

       method: ‘get‘ } ],

  methods: { get: true } }

9

顶层Router(中间件容器): /*下面是顶层Router中的第7个中间件,该中间件也是个Router,蓝色部分是封装了子Router的Layer,子Router中的stack中有5个路由中间件,也就是上面输出的5个;子Router是handler(中间件处理程序)的属性值,也就是说这个子Router是作为普通中间件添加到app.Router中的*/

{ handle:   

   { [Function: router]

     params: {},

     _params: [],

     caseSensitive: undefined,

     mergeParams: undefined,

     strict: undefined,

     stack: [ [Object], [Object], [Object], [Object], [Object] ] },

  name: ‘router‘,

  params: undefined,

  path: undefined,

  keys: [],

  regexp: { /^\/?(?=\/|$)/i fast_slash: true },

  route: undefined }

  既然app.Router中可以添加Router对象,那么我们可以新建一个js文件,专门用来添加自定义的中间件,在该js文件中里面实例化一个Router对象,将路由的注册或非路由中间件的添加代码都写到该文件里,然后导出该Router对象,最后在app.js中将该Router添加到app.Router中。

express路由探析(续)

标签:style   blog   http   io   color   ar   for   sp   strong   

原文地址:http://www.cnblogs.com/neverstop/p/4075249.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!