express的新开发人员每每对路由处理程序和中间件之间的区别感到困惑。所以他们也对app.use()
,app.all()
,app.get()
,app.post()
,app.delete()
和app.put()
方法的区别感到困惑。express
在本文中,我将解释中间件和路由处理程序之间的区别。以及如何正确使用app.use()
,app.all()
,app.get()
,app.post()
,app.delete()
和app.put()
方法。app
app.use()
,app.all()
,app.get()
,app.post()
,app.delete()
和app.put()
所有是用来定义路由的。这些方法都用于定义路由。路由用于处理HTTP请求。路由是路径和回调的组合,在请求的路径匹配时执行。回调被称为路由处理程序。函数
它们之间的区别是处理不一样类型的HTTP请求。例如: app.get()
方法仅仅处理get请求,而app.all()
处理GET、POST等请求。post
下面是一个例子,如何定义一个路由:
var app = require("express")(); app.get("/", function(req, res, next){ res.send("Hello World!!!!"); }); app.listen(8080);
每一个路由处理程序都得到对当前正在提供的HTTP请求的请求和响应对象的引用。ui
能够为单个HTTP请求执行多个路由处理程序。这是一个例子:
var app = require("express")(); app.get("/", function(req, res, next){ res.write("Hello"); next(); }); app.get("/", function(req, res, next){ res.write(" World !!!"); res.end(); }); app.listen(8080);
这里第一个句柄写入一些响应,而后调用next()
。 next()
方法用于调用与路径路径匹配的下一个路由处理程序。this
路由处理程序必须结束请求或调用下一个路由处理程序。url
咱们还能够将多个路由处理程序传递给app.all()
,app.get()
,app.post()
,app.delete()
和app.put()
方法。code
这是一个证实这一点的例子:
var app = require("express")(); app.get("/", function(req, res, next){ res.write("Hello"); next(); }, function(req, res, next){ res.write(" World !!!"); res.end(); }); app.listen(8080);
中间件是一个位于实际请求处理程序之上的回调。它采用与路由处理程序相同的参数。中间件
要了解中间件,咱们来看一个带有dashboard
和profile
页面的示例站点。要访问这些页面,用户必须登陆。还会记录对这些页面的请求。对象
如下是这些页面的路由处理程序的代码:
var app = require("express")(); function checkLogin(){ return false; } function logRequest(){ console.log("New request"); } app.get("/dashboard", function(req, res, next){ logRequest(); if(checkLogin()){ res.send("This is the dashboard page"); } else{ res.send("You are not logged in!!!"); } }); app.get("/profile", function(req, res, next){ logRequest(); if(checkLogin()){ res.send("This is the dashboard page"); } else{ res.send("You are not logged in!!!"); } }); app.listen(8080);
这里的问题是有不少重复的代码,即咱们不得很少次使用logRequest()
和checkLogin()
函数。这也使得更新代码变得困难。所以,为了解决这个问题,咱们能够为这两条路径编写一条通用路径。
这是重写的代码:
var app = require("express")(); function checkLogin(){ return false; } function logRequest(){ console.log("New request"); } app.get("/*", function(req, res, next){ logRequest(); next(); }) app.get("/*", function(req, res, next){ if(checkLogin()){ next(); } else{ res("You are not logged in!!!"); } }) app.get("/dashboard", function(req, res, next){ res.send("This is the dashboard page"); }); app.get("/profile", function(req, res, next){ res.send("This is the dashboard page"); }); app.listen(8080);
这里的代码看起来更清晰,更易于维护和更新。这里将前两个定义的路由处理程序称为中间件,由于它们不处理请求,而是负责预处理请求。
Express为咱们提供了app.use()
方法,该方法专门用于定义中间件。 app.use()
方法可能看起来与app.all()
相似,但它们之间存在不少差别,这使得app.use()
很是适合于声明中间件。让咱们看看app.use()
方法是如何工做的:
app.use()
和 app.all()
的不一样:app.use()
只须要一个回调,而app.all()
能够进行屡次回调。
app.use()
只查看url是否以指定路径开头,app.all()
匹配完整路径。
这里有一个例子来讲明:
app.use( "/product" , mymiddleware); // will match /product // will match /product/cool // will match /product/foo app.all( "/product" , handler); // will match /product // won't match /product/cool <-- important // won't match /product/foo <-- important app.all( "/product/*" , handler); // won't match /product <-- Important // will match /product/cool // will match /product/foo
中间件内的next()
调用下一个中间件或路由处理程序,具体取决于接下来声明的那个。可是路由处理程序中的next()
仅调用下一个路由处理程序。若是接下来有中间件,则跳过它。所以,必须在全部路由处理程序以前声明中间件。
这里有一个例子来讲明:
var express = require('express'); var app = express(); app.use(function frontControllerMiddlewareExecuted(req, res, next){ console.log('(1) this frontControllerMiddlewareExecuted is executed'); next(); }); app.all('*', function(req, res, next){ console.log('(2) route middleware for all method and path pattern "*", executed first and can do stuff before going next'); next(); }); app.all('/hello', function(req, res, next){ console.log('(3) route middleware for all method and path pattern "/hello", executed second and can do stuff before going next'); next(); }); app.use(function frontControllerMiddlewareNotExecuted(req, res, next){ console.log('(4) this frontControllerMiddlewareNotExecuted is not executed'); next(); }); app.get('/hello', function(req, res){ console.log('(5) route middleware for method GET and path patter "/hello", executed last and I do my stuff sending response'); res.send('Hello World'); }); app.listen(80);
如今咱们看到了app.use()
方法的惟一性以及它用于声明中间件的缘由。
让咱们重写咱们的示例站点代码:
var app = require("express")(); function checkLogin(){ return false; } function logRequest(){ console.log("New request"); } app.use(function(req, res, next){ logRequest(); next(); }) app.use(function(req, res, next){ if(checkLogin()){ next(); } else{ res.send("You are not logged in!!!"); } }) app.get("/dashboard", function(req, res, next){ res.send("This is the dashboard page"); }); app.get("/profile", function(req, res, next){ res.send("This is the dashboard page"); }); app.listen(8080);