转载至:http://blog.csdn.net/wthfeng/article/details/53366169

写在前面:最近研究nodejs及其web框架express,对app.use和app.get没理解清,以致踩了坑浪费不少时间,我根据自己实践及总结出此博客,若有错误还请大家多多指教。

app对象 app对象一般用来表示Express程序。通过调用Express模块导出的顶层的express()方法来创建它:

var express = require('express');
var app = express();
app.get('/', function(req, res) {
    res.send('hello world!');
});
app.listen(3000);

app对象具有以下的方法:

  • 路由HTTP请求;具体可以看app.METHOD和app.param这两个例子。
  • 配置中间件;具体请看app.route。
  • 渲染HTML视图;具体请看app.render。
  • 注册模板引擎;具体请看app.engine。

结论 先说我发现的结论:

app.use(path,callback)中的callback既可以是router对象又可以是函数
app.get(path,callback)中的callback只能是函数

结论说完,让我们先看个栗子 例子

var express = require('express');
var app = express();
var index = require('./routes/index');
1、
app.use('/test1',function(req,res,next){
    res.send('hello test1');
		res.render('index');  //注意这里和4对比,4 是直接把路由作为第二个参数,这里是放在回调函数里,效果一样
});
2、
app.get('/test2',function(req,res,next){
    res.send('hello test2');
});
3、app.get('/test3',index);
4、app.use('/test4',index);

index是一个路由对象,结果,例1、2、4结果都能正确显示,而例3却报404。index.js很简单,如下:

var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
  res.send('hello world!');
});
module.exports = router;

两者关系 这说明,给app.get(app.post、app.put同理)直接赋个路由对象是不行的,其实,可以将app.get()看作app.use的特定请求(get)的简要写法。即:

var express = require('express');
var app = express();
app.get('/hello',function(req,res,next){
    res.send('hello test2');
});

等同于:

var express = require('express');
var app = express();
var router = express.Router();
router.get('/', function(req, res, next) {  //归根到底还是使用了router的方法
  res.send('hello world!');
});
app.use('/hello',router);

什么时用 那么,什么时用app.use,什么时用app.get呢?

路由规则是app.use(path,router)定义的,router代表一个由express.Router()创建的对象,在路由对象中可定义多个路由规则。可是如果我们的路由只有一条规则时,可直接接一个回调作为简写,也可直接使用app.get或app.post方法。即 当一个路径有多个匹配规则时,使用app.use,否则使用相应的app.method(get、post) 对express路由的解析可参考Express.js 4.0 的路由(Router)功能用法教學请添加链接描述,觉得比官网说的清楚。 app.use内部其实调用了router.use

router.use router.use([path], [function, ...] function) 给可选的path参数指定的路径挂载给定的中间件方法,未指定path参数,默认值为/。 这个方法类似于app.use()。一个简单的例子和用例在下面描述。查阅app.use()获得更多的信息。 中间件就像一个水暖管道,请求在你定义的第一个中间件处开始,顺着中间件堆栈一路往下,如果路径匹配则处理这个请求。

var express = require('express');
var app = express();
var router = express.Router();
// 这个路由器请求的简单记录器
// all requests to this router will first hit this middleware,没给path,所有请求都会先执行这个中间件
/// 這個範例是一個簡單的 middleware,在每一個請求被處理之前都會執行的 middleware ,这里是會在每一個請求被處理之前,輸出一行紀錄訊息到終端機上:
router.use(function(req, res, next) {
    console.log('%s %s %s', req.method, req.url, req.path);
    next();  //必须有next()方法,
})
// this will only be invoked if the path starts with /bar form the mount ponit
router.use('/bar', function(req, res, next) {
    // ... maybe some additional /bar logging ...
    next();
})
// always be invoked
router.use(function(req, res, next) {
    res.send('hello world');
})
app.use('/foo', router);
app.listen(3000);

router.post app.post app.use 要使用router.post,首先要: var router = express.Router(); 然后使用 router.post, 这个也是匹配对应的路由,执行回调方法 最终需要使用app.use('/',router)来使路由真正发挥作用 如果router的路径和app.js路径不一样,还要通过module.exports = router导出router, 在app.j里面,app.use('/',require('./routers/main'));,后面的router要写上相对地址; 当然了,在同一个js里,就直接app.use('/',router)就行了。

可以直接使用app.post app.use来处理路由,也可以使用router.post

express.Router 使用express.Router该类创建模块化,可安装的路由处理程序。一个Router实例是一个完整的中间件和路由系统; 因此,它通常被称为“迷你app”。

以下示例将路由器创建为模块,在其中加载中间件功能,定义一些路由,并将路由器模块安装在主应用程序中的路径上。

创建birds.jsapp目录中指定的路由器文件,其中包含以下内容:

var express = require('express')
var router = express.Router()

// middleware that is specific to this router
router.use(function timeLog (req, res, next) {
  console.log('Time: ', Date.now())
  next()
})
// define the home page route
router.get('/', function (req, res) {
  res.send('Birds home page')
})
// define the about route
router.get('/about', function (req, res) {
  res.send('About birds')
})

module.exports = router
//然后,在应用程序中加载路由器模块:
var birds = require('./birds')
// ...
app.use('/birds', birds)

该应用程序现在能够处理请求/birds和/birds/about,以及调用timeLog中间件功能是特定的路线。

next() 注意:app.use注册的中间件,如果path参数为空,则默认为"/",而path为"/"的中间件默认匹配所有的请求。

我们在定义express中间件函数的时候都会将第三个参数定义为next,这个next就是我们今天的主角,next函数主要负责将控制权交给下一个中间件,如果当前中间件没有终结请求,并且next没有被调用,那么请求将被挂起,后边定义的中间件将得不到被执行的机会。 next函数主要是用来确保所有注册的中间件被一个接一个的执行,那么我们就应该在所有的中间件中调用next函数。

next()方法出现在express框架中的中间件部分。中间件的行为类似于Java中的filter(过滤器)的工作原理,进入具体的业务处理之前,先让中间件进行处理,这样做可以封装底层处理的细节,可以让开发者更加专注于具体的业务上,提高了开发效率。

由于node异步的原因,我们需要提供一种机制,当当前中间件工作完成之后,通知下一个中间件执行。因此一个基本的中间件应该是下面的形式:

var middleware = function(req,res,next){
    next();
}