从宏观上讲,路由系统,只不过是express内部函数数组中一个函数而已(见第一篇),而且位置相对靠后。
最简单的路由系统,就是一个字典(hashmap),根据url,找的相应的处理函数即可。当然express的实现不可能那么简单。
express内部有个map,对于每一种请求方法(get,post...)都有映射,每个都映射到一个 路由对象的数组,如下图所示。
实际上,每写下一个
//var app = express();
app.get('/',callback);//callback是一个函数
map的get属性就会push进一个Route,即使多次对同一个路径进行app.get。当然可以给app.get的第二个参数传一个函数的数组,下面两段代码的执行效果是一样的
//first
app.get('/',[callback1,callback2]);
//second
app.get('/',callback1);
app.get('/',callback2);
不过第一个map的get数组里,会push进1个Route(里面的callbacks有2个元素),而第二个是push进2个Route(每一个的callbacks只有一个元素),如下图
express 要路由到相应的处理函数,需要method和path两个都满足条件。
1.method就是'get'、'post'等,根据这个来找到map中相应的属性
2.然后在数组中,检查path是否符合里面的Route的要求,如果符合,相应的callback函数会依次(看后面的解释)执行。callback函数的签名是:
function(req,res,next){}
如果一个callback没有结束一个请求响应的生命周期( 比如写下res.end('...') ),那么一般需要在最后写上next(),像下面那样
function(req,res,next){
//..自己的业务逻辑
next();
}
这样,就会继续检查下面的一个Route
如果callback中,会终结一个请求响应周期(一般也是这样),那么不应该有next(),也不会继续检查下一个Route
//一般路由函数都应该和这个类似
function(req,res,next){
//..自己的业务逻辑
res.end('...');//或res.render('...')等
}
试验一:多次对同一地址进行 app.get
在app.js中的 app.get('/', routes.index);
的上面写下:
app.get('/',function(req,res,next){
console.log("11");
next()
});
app.get('/',function(req,res,next){
console.log("22");
next()
});
那么请求主页的时候,控制台会依次输出11,22,最后执行routes.index 函数,向浏览器发送数据。
可以试着去掉上面任意一个next(),看看效果如何
用处
知道这些有什么用呢?我觉得用处不大(放学后,请不要打我-_-!)
不过还是可能有点用,比如:
很多年都没人访问我的主页,我很伤心,现在想加个功能,有人访问我的主页,就发个邮件给我,
让我开心一下。那么已有的处理主页的逻辑,不用任何改动,只需要在比较靠前的位置写:
app.get('/',function(req,res,next){
emaiTo('[email protected]','有人访问我的主页了,喜大普奔');
next()
});
另外一个更实际的例子可能是访问量记录
var i = 0;
app.get('*',function(req,res,next){
console.log(++i);
next();
});
'*' 是通配符,所以访问任何一个路径,包括
localhost:3000/
localhost:3000/nopage
i 都会自增,而且托nodejs单线程的线程模型的福,这样写就可以了。
最后,我隐约的感觉到,这样的方式,如果做AOP(面向切面编程)好像很方便(我乱说的。。),也就是说,可以在不影响已有代码的情况下,就可以加入一些功能
总结
- 这样看,next() 这种模型好像很常用,需要好好理解一下
- express的路由,先根据method 找到相应的数组,然后根据path,依次检查数组中的Route是否满足要求,并决定是否执行相应的callback函数。按照一般的写法(
res.end()
,res.render()
),如果找到结束当前请求的指示,执行完当前代码即可,不会继续检查数组中后面的Route - 从宏观上讲,路由系统,只不过是express内部函数数组中一个函数而已
知道以上几点应该就够了,后面做的一些试验,是非典型代码,玩的意味更大~~
下面是主要的试验代码,
var i = 0;
app.post('*' ,function(req,res,next){
res.end("nothing for post");
});
app.get('*',function(req,res,next){
console.log(++i);
next();
});
app.get('/',function(req,res,next){
console.log("11");
next()
});
app.get('/',function(req,res,next){
console.log("22");
next()
});
//以下是建express项目后,就有的代码
app.get('/', routes.index);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
原文地址:http://www.html-js.com/article/Nodejs-beginner-beginners-node-two-Express-routing