溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

express中間件和路由教程

發(fā)布時間:2020-07-30 02:37:16 來源:網(wǎng)絡 閱讀:1290 作者:xxxpjgl 欄目:web開發(fā)

一、路由
1、通常HTTP URL的格式是這樣的:http://host[:port][path]

  • http表示協(xié)議。
  • host表示主機。
  • port為端口,可選字段,不提供時默認為80。
  • path指定請求資源的URI(Uniform Resource Identifier,統(tǒng)一資源定位符),如果URL中沒有給出path,一般會默認成“/”(通常由瀏覽器或其它HTTP客戶端完成補充上)。

所謂路由,就是如何處理HTTP請求中的路徑部分。比如“http://xxx.com:80/users/profile”
這個URL,路由將決定怎么處理/users/profile這個路徑。
路由是由一個 URI、HTTP 請求(GET、POST等)和若干個句柄組成,它的結構如下: app.METHOD(path, [callback...], callback), app 是 express對象的一個實例, METHOD 是一個 HTTP 請求方法, path 是服務器上的路徑, callback 是當路由匹配時要執(zhí)行的函數(shù)。

//使用express顯示helloworld:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
  res.send('Hello World!');
});
app.listen(8000, function () {
  console.log('Hello World is listening at port 8000');
});

上面代碼里的app.get()調(diào)用,實際上就為我們的網(wǎng)站添加了一條路由,指定“/”這個路徑,由get的第二個參數(shù)所代表的函數(shù)來處理。
express對象可以針對常見的HTTP方法指定路由,使用下面的方法:
app.METHOD(path, callback [, callback ...])

2、路由方法
路由方法源于 HTTP 請求方法,和 express 實例相關聯(lián)。
下面這個例子展示了為應用跟路徑定義的 GET 和 POST 請求:

// GET method route
app.get('/', function (req, res) {
  res.send('GET request to the homepage');
});
// POST method route
app.post('/', function (req, res) {
  res.send('POST request to the homepage');
});

app.all() 是一個特殊的路由方法,沒有任何 HTTP 方法與其對應,它的作用是對于一個路徑上的所有請求加載中間件。
在下面的例子中,來自 “/secret” 的請求,不管使用 GET、POST、PUT、DELETE 或其他任何 http 模塊支持的 HTTP 請求,句柄都會得到執(zhí)行。

app.all('/secret', function (req, res, next) {
  console.log('Accessing the secret section ...');
  next(); // pass control to the next handler
});

3、路由路徑
路由路徑和請求方法一起定義了請求的端點,它可以是字符串、字符串模式或者正則表達式。
使用字符串的路由路徑示例:

// 匹配根路徑的請求
app.get('/', function (req, res) {
  res.send('root');
});
// 匹配 /about 路徑的請求
app.get('/about', function (req, res) {
  res.send('about');
});
// 匹配 /random.text 路徑的請求
app.get('/random.text', function (req, res) {
  res.send('random.text');
});

使用字符串模式的路由路徑示例:

// 匹配 acd 和 abcd
app.get('/ab?cd', function(req, res) {
  res.send('ab?cd');
});
// 匹配 abcd、abbcd、abbbcd等
app.get('/ab+cd', function(req, res) {
  res.send('ab+cd');
});
// 匹配 abcd、abxcd、abRABDOMcd、ab123cd等
app.get('/ab*cd', function(req, res) {
  res.send('ab*cd');
});
// 匹配 /abe 和 /abcde
app.get('/ab(cd)?e', function(req, res) {
 res.send('ab(cd)?e');
});

4、路由句柄
可以為請求處理,提供多個回調(diào)函數(shù),其行為類似 中間件。唯一的區(qū)別是這些回調(diào)函數(shù)有可能調(diào)用 next('route') 方法而略過其他路由回調(diào)函數(shù)。可以利用該機制為路由定義前提條件,如果在現(xiàn)有路徑上繼續(xù)執(zhí)行沒有意義,則可將控制權交給剩下的路徑。
路由句柄有多種形式,可以是一個函數(shù)、一個函數(shù)數(shù)組,或者是兩者混合,如下所示.

//使用一個回調(diào)函數(shù)處理路由:
app.get('/example/a', function (req, res) {
  res.send('Hello from A!');
});
//使用多個回調(diào)函數(shù)處理路由(記得指定 next 對象):
app.get('/example/b', function (req, res, next) {
  console.log('response will be sent by the next function ...');
  next();
}, function (req, res) {
  res.send('Hello from B!');
});
//使用回調(diào)函數(shù)數(shù)組處理路由:
var cb0 = function (req, res, next) {
  console.log('CB0');
  next();
}
var cb1 = function (req, res, next) {
  console.log('CB1');
  next();
}
var cb2 = function (req, res) {
  res.send('Hello from C!');
}
app.get('/example/c', [cb0, cb1, cb2]);
//混合使用函數(shù)和函數(shù)數(shù)組處理路由:
var cb0 = function (req, res, next) {
  console.log('CB0');
  next();
}
var cb1 = function (req, res, next) {
  console.log('CB1');
  next();
}
app.get('/example/d', [cb0, cb1], function (req, res, next) {
  console.log('response will be sent by the next function ...');
  next();
}, function (req, res) {
  res.send('Hello from D!');
});

METHOD可以是GET、POST等HTTP方法的小寫,例如app.get,app.post。path部分呢,既可以是字符串字面量,也可以是正則表達式。最簡單的例子,把前面代碼里的app.get()調(diào)用的一個參數(shù)’/’修改為’*’,含義就不一樣。改動之前,只有訪問“http://localhost:8000”或“http://localhost:8000/”這種形式的訪問才會返回“Hello World!”,而改之后呢,像“http://localhost:8000/xxx/yyyy.zz”這種訪問也會返回“Hello World!”。

使用express構建Web服務器時,很重要的一部分工作就是決定怎么響應針對某個路徑的請求,也即路由處理。
最直接的路由配置方法,就是調(diào)用app.get()、app.post()一條一條的配置,不過對于需要處理大量路由的網(wǎng)站來講,這會搞出人命來的。所以呢,我們實際開發(fā)中需要結合路由參數(shù)(query string、正則表達式、自定義的參數(shù)、post參數(shù))來減小工作量提高可維護性。

5、響應方法
下表中響應對象(res)的方法向客戶端返回響應,終結請求響應的循環(huán)。如果在路由句柄中一個方法也不調(diào)用,來自客戶端的請求會一直掛起。

  • res.download() 提示下載文件。
  • res.end() 終結響應處理流程。
  • res.json() 發(fā)送一個 JSON 格式的響應。
  • res.jsonp() 發(fā)送一個支持 JSONP 的 JSON 格式的響應。
  • res.redirect() 重定向請求。
  • res.render() 渲染視圖模板。
  • res.send() 發(fā)送各種類型的響應。
  • res.sendFile 以八位字節(jié)流的形式發(fā)送文件。
  • res.sendStatus() 設置響應狀態(tài)代碼,并將其以字符串形式作為響應體的一部分發(fā)送。

6、app.route()
可使用 app.route() 創(chuàng)建路由路徑的鏈式路由句柄。由于路徑在一個地方指定,這樣做有助于創(chuàng)建模塊化的路由,而且減少了代碼冗余和拼寫錯誤。請參考 Router() 文檔 了解更多有關路由的信息。
下面這個示例程序使用 app.route() 定義了鏈式路由句柄。

app.route('/book')
  .get(function(req, res) {
    res.send('Get a random book');
  })
  .post(function(req, res) {
    res.send('Add a book');
  })
  .put(function(req, res) {
    res.send('Update the book');
  });

7、express.Router
express還提供了一個叫做Router的對象,行為很像中間件,你可以把Router直接傳遞給app.use,像使用中間件那樣使用Router。另外你還可以使用router來處理針對GET、POST等的路由,也可以用它來添加中間件,總之你可以將Router看作一個微縮版的app。
可使用 express.Router 類創(chuàng)建模塊化、可掛載的路由句柄。Router 實例是一個完整的中間件和路由系統(tǒng),因此常稱其為一個 “mini-app”。
下面的實例程序創(chuàng)建了一個路由模塊,并加載了一個中間件,定義了一些路由,并且將它們掛載至應用的路徑上。

在 app 目錄下創(chuàng)建名為 birds.js 的文件,內(nèi)容如下:

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

// 該路由使用的中間件
router.use(function timeLog(req, res, next) {
  console.log('Time: ', Date.now());
  next();
});
// 定義網(wǎng)站主頁的路由
router.get('/', function(req, res) {
  res.send('Birds home page');
});
// 定義 about 頁面的路由
router.get('/about', function(req, res) {
  res.send('About birds');
});
module.exports = router;

然后在應用中加載路由模塊:

var birds = require('./birds');
app.use('/birds', birds);

應用即可處理發(fā)自 /birds 和 /birds/about 的請求,并且調(diào)用為該路由指定的 timeLog 中間件。
上面這種用法,會針對URL中的“/birds”路徑應用router,你在router對象上配置的各種路由策略和中間件,都會被在合適的時候應用。
8、路由模塊
express工具創(chuàng)建的應用,有一個routes目錄,下面保存了應用到網(wǎng)站的Router模塊,index.js和user.js。這兩個模塊基本一樣,我們研究一下index.js。

//index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});
module.exports = router;

index.js創(chuàng)建了一個Router實例,然后調(diào)用router.get為“/”路徑應用了路由函數(shù)。最后呢使用module.exports將Router對象導出。
下面是app.js里引用到index.js的代碼:

//app.js
var routes = require('./routes/index');
...
app.use('/', routes);
  • 第一處,require(‘./routes/index’)將其作為模塊使用,這行代碼導入了index.js,并且將index.js導出的router對象保存在變量routes里以供后續(xù)使用。注意,上面代碼里的routes就是index.js里的router。
  • 第二處代碼,把routes作為一個中間件,掛載到了“/”路徑上。

9、模塊
前面分析index.js時看到了module.exports的用法。module.exports用來導出一個Node.js模塊內(nèi)的對象,調(diào)用者使用require加載模塊時,就會獲得導出的對象的實例。
我們的index.js導出了Router對象。app.js使用require(‘./routes/index’)獲取了一個Router實例。
module.exports還有一個輔助用法,即直接使用exports來導出。

exports.signup = function(req, res){
  //some code
}
exports.login = function(req, res){
  //some code
}

上面的代碼(假定在users.js文件里)直接使用exports來導出。當使用exports來導出時,你設置給exports的屬性和方法,實際上都是module.exports的。這個模塊最終導出的是module.exports對象,你使用類似“exports.signup”這種形式設置的方法或?qū)傩?,調(diào)用方在require后都可以直接使用。
使用users模塊的代碼可能是這樣的:

var express = require('express');
var app = express();
...
var users = require('./routes/users');
app.post('/signup', users.signup);
app.post('/login', users.login);
...

二、中間件
1、概念
express里有個中間件(middleware)的概念。所謂中間件,就是在收到請求后和發(fā)送響應之前這個階段執(zhí)行的一些函數(shù)。
中間件(Middleware) 是一個函數(shù),它可以訪問請求對象(request object (req)), 響應對象(response object (res)), 和 web 應用中處于請求-響應循環(huán)流程中的中間件,一般被命名為 next 的變量。
中間件的功能包括:

  • 執(zhí)行任何代碼。
  • 修改請求和響應對象。
  • 終結請求-響應循環(huán)。
  • 調(diào)用堆棧中的下一個中間件。
    如果當前中間件沒有終結請求-響應循環(huán),則必須調(diào)用 next() 方法將控制權交給下一個中間件,否則請求就會掛起。
    要在一條路由的處理鏈上插入中間件,可以使用express對象的use方法。該方法原型如下:
    app.use([path,] function [, function...])
    當app.use沒有提供path參數(shù)時,路徑默認為“/”。當你為某個路徑安裝了中間件,則當以該路徑為基礎的路徑被訪問時,都會應用該中間件。比如你為“/abcd”設置了中間件,那么“/abcd/xxx”被訪問時也會應用該中間件。
    在一個路徑上掛載一個中間件之后,每當請求的路徑的前綴部分匹配了這個路由路徑,那么這個中間件就會被執(zhí)行。 由于默認的路徑為/,中間件掛載沒有指定路徑,那么對于每個請求,這個中間件都會被執(zhí)行
    express中間件和路由教程
    中間件方法是順序處理的,所以中間件包含的順序是很重要的
    express中間件和路由教程
    調(diào)用中間件時候的路徑可以是代表路徑的一串字符,一個路徑模式,一個匹配路徑的正則表達式,或者他們的一組集合
    express中間件和路由教程
    中間件方法可以是一個中間件方法,一系列中間件方法,一組中間件方法或者他們的集合。由于路由router和express實例app也實現(xiàn)了中間件接口,所以你可以像使用其他任一中間件方法那樣使用它們
    express中間件和路由教程
    對于相同的掛載路徑可以掛載多個中間件,因為路徑的相同,調(diào)用next的時候會自動執(zhí)行下一個匹配相同路徑的中間件
    express中間件和路由教程
    中間件函數(shù)的原型如下:
    function (req, res, next)
    第一個參數(shù)是Request對象req。第二個參數(shù)是Response對象res。第三個則是用來驅(qū)動中間件調(diào)用鏈的函數(shù)next,如果你想讓后面的中間件繼續(xù)處理請求,就需要調(diào)用next方法。
    給某個路徑應用中間件函數(shù)的典型調(diào)用是這樣的:
    app.use('/abcd', function (req, res, next) {
    console.log(req.baseUrl);
    next();
    })

    Express 應用可使用如下幾種中間件:

  • 應用級中間件
  • 路由級中間件
  • 錯誤處理中間件
  • 內(nèi)置中間件
  • 第三方中間件
    2、app.static中間件
    Express提供了一個static中間件,可以用來處理網(wǎng)站里的靜態(tài)文件的GET請求,可以通過express.static訪問。
    express.static的用法如下:
    express.static(root, [options])
    第一個參數(shù)root,是要處理的靜態(tài)資源的根目錄,可以是絕對路徑,也可以是相對路徑。第二個可選參數(shù)用來指定一些選項,比如maxAge、lastModified等,更多選項的介紹看這里:http://expressjs.com/guide/using-middleware.html#middleware.built-in。
    一個典型的express.static應用如下:
    var options = {
    dotfiles: 'ignore',
    etag: false,
    extensions: ['htm', 'html'],
    index: false,
    maxAge: '1d',
    redirect: false,
    setHeaders: function (res, path, stat) {
    res.set('x-timestamp', Date.now());
    }
    }
    app.use(express.static('public', options));

    上面這段代碼將當前路徑下的public目錄作為靜態(tài)文件,并且為Cache-Control頭部的max-age選項為1天。還有其它一些屬性,請對照express.static的文檔來理解。

使用express創(chuàng)建的HelloExpress項目的app.js文件里有這樣一行代碼:

app.use(express.static(path.join(dirname, 'public')));
這行代碼將HelloExpress目錄下的public目錄作為靜態(tài)文件交給static中間件來處理,對應的HTTP URI為“/”。path是一個Node.js模塊,
dirname是Node.js的全局變量,指向當前運行的js腳本所在的目錄。path.join()則用來拼接目錄。

有了上面的代碼,你就可以在瀏覽器里訪問“http://localhost:3000/stylesheets/style.css”。
我們做一點改動,把上面的代碼修改成下面這樣:

app.use('/static', express.static(path.join(__dirname, 'public')));
上面的代碼呢,針對/static路徑使用static中間件處理public目錄。這時你再用瀏覽器訪問“http://localhost:3000/stylesheets/”
就會看到一個404頁面,將地址成
“http://localhost:3000/static/stylesheets/style.css”
就可以了。

3、應用級中間件
應用級中間件綁定到 app 對象 使用 app.use() 和 app.METHOD(), 其中, METHOD 是需要處理的 HTTP 請求的方法,例如 GET, PUT, POST 等等,全部小寫。例如:

var app = express();
// 沒有掛載路徑的中間件,應用的每個請求都會執(zhí)行該中間件
app.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});
// 掛載至 /user/:id 的中間件,任何指向 /user/:id 的請求都會執(zhí)行它
app.use('/user/:id', function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});
// 路由和句柄函數(shù)(中間件系統(tǒng)),處理指向 /user/:id 的 GET 請求
app.get('/user/:id', function (req, res, next) {
  res.send('USER');
});

4、下面這個例子展示了在一個掛載點裝載一組中間件。

// 一個中間件棧,對任何指向 /user/:id 的 HTTP 請求打印出相關信息
app.use('/user/:id', function(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
}, function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

5、作為中間件系統(tǒng)的路由句柄,使得為路徑定義多個路由成為可能。在下面的例子中,為指向 /user/:id 的 GET 請求定義了兩個路由。第二個路由雖然不會帶來任何問題,但卻永遠不會被調(diào)用,因為第一個路由已經(jīng)終止了請求-響應循環(huán)。

// 一個中間件棧,處理指向 /user/:id 的 GET 請求
app.get('/user/:id', function (req, res, next) {
  console.log('ID:', req.params.id);
  next();
}, function (req, res, next) {
  res.send('User Info');
});
// 處理 /user/:id, 打印出用戶 id
app.get('/user/:id', function (req, res, next) {
  res.end(req.params.id);
});

6、如果需要在中間件棧中跳過剩余中間件,調(diào)用 next('route') 方法將控制權交給下一個路由。 注意: next('route') 只對使用 app.VERB() 或 router.VERB() 加載的中間件有效。

// 一個中間件棧,處理指向 /user/:id 的 GET 請求
app.get('/user/:id', function (req, res, next) {
  // 如果 user id 為 0, 跳到下一個路由
  if (req.params.id == 0) next('route');
  // 否則將控制權交給棧中下一個中間件
  else next(); //
}, function (req, res, next) {
  // 渲染常規(guī)頁面
  res.render('regular');
});

// 處理 /user/:id, 渲染一個特殊頁面
app.get('/user/:id', function (req, res, next) {
  res.render('special');
});

7、路由級中間件

路由級中間件和應用級中間件一樣,只是它綁定的對象為 express.Router()。

var router = express.Router();
路由級使用 router.use() 或 router.VERB() 加載。

上述在應用級創(chuàng)建的中間件系統(tǒng),可通過如下代碼改寫為路由級:

var app = express();
var router = express.Router();

// 沒有掛載路徑的中間件,通過該路由的每個請求都會執(zhí)行該中間件
router.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});
// 一個中間件棧,顯示任何指向 /user/:id 的 HTTP 請求的信息
router.use('/user/:id', function(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
}, function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});
// 一個中間件棧,處理指向 /user/:id 的 GET 請求
router.get('/user/:id', function (req, res, next) {
  // 如果 user id 為 0, 跳到下一個路由
  if (req.params.id == 0) next('route');
  // 負責將控制權交給棧中下一個中間件
  else next(); //
}, function (req, res, next) {
  // 渲染常規(guī)頁面
  res.render('regular');
});
// 處理 /user/:id, 渲染一個特殊頁面
router.get('/user/:id', function (req, res, next) {
  console.log(req.params.id);
  res.render('special');
});
// 將路由掛載至應用
app.use('/', router);

8、錯誤處理中間件
錯誤處理中間件有 4 個參數(shù),定義錯誤處理中間件時必須使用這 4 個參數(shù)。即使不需要 next 對象,也必須在簽名中聲明它,否則中間件會被識別為一個常規(guī)中間件,不能處理錯誤。

錯誤處理中間件和其他中間件定義類似,只是要使用 4 個參數(shù),而不是 3 個,其簽名如下: (err, req, res, next)。

app.use(function(err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

9、內(nèi)置中間件
從 4.x 版本開始,, Express 已經(jīng)不再依賴 Connect 了。除了 express.static, Express 以前內(nèi)置的中間件現(xiàn)在已經(jīng)全部單獨作為模塊安裝使用了。

express.static(root, [options])
express.static 是 Express 唯一內(nèi)置的中間件。它基于 serve-static,負責在 Express 應用中提托管靜態(tài)資源。
參數(shù) root 指提供靜態(tài)資源的根目錄。
可選的 options 參數(shù)擁有如下屬性。

  • dotfiles 是否對外輸出文件名以點(.)開頭的文件??蛇x值為 “allow”、“deny” 和 “ignore” String “ignore”
  • etag 是否啟用 etag 生成 Boolean true
  • extensions 設置文件擴展名備份選項 Array []
  • index 發(fā)送目錄索引文件,設置為 false 禁用目錄索引。 Mixed “index.html”
  • lastModified 設置 Last-Modified 頭為文件在操作系統(tǒng)上的最后修改日期??赡苤禐?true 或 false。 Boolean true
  • maxAge 以毫秒或者其字符串格式設置 Cache-Control 頭的 max-age 屬性。 Number 0
  • redirect 當路徑為目錄時,重定向至 “/”。 Boolean true
  • setHeaders 設置 HTTP 頭以提供文件的函數(shù)。 Function
    下面的例子使用了 express.static 中間件,其中的 options 對象經(jīng)過了精心的設計。
    var options = {
    dotfiles: 'ignore',
    etag: false,
    extensions: ['htm', 'html'],
    index: false,
    maxAge: '1d',
    redirect: false,
    setHeaders: function (res, path, stat) {
    res.set('x-timestamp', Date.now());
    }
    }
    app.use(express.static('public', options));

    每個應用可有多個靜態(tài)目錄。

    app.use(express.static('public'));
    app.use(express.static('uploads'));
    app.use(express.static('files'));

    9、第三方中間件
    通過使用第三方中間件從而為 Express 應用增加更多功能。

安裝所需功能的 node 模塊,并在應用中加載,可以在應用級加載,也可以在路由級加載。

下面的例子安裝并加載了一個解析 cookie 的中間件: cookie-parser

$ npm install cookie-parser
var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');

// 加載用于解析 cookie 的中間件
app.use(cookieParser());

三、總結
1、什么是router路徑,什么是middleware?
我們輸入www.baidu.com 來訪問百度的主頁,瀏覽器會自動轉(zhuǎn)換為 http://www.baidu.com:80/(省略一些參數(shù))。
http:// 代表我們同服務器連接使用的是http協(xié)議,
www.baidu.com 代表的是服務器的主機地址,會被我們的pc通過DNS解析為IP地址。
80是默認的應用層端口。
/ 即為我們訪問的服務器(www.baidu.com)的路徑,服務器要對我們訪問的這個路徑做出響應,采取一定的動作。我們可以把這一過程看做一個路由。
訪問的路徑‘/’即為router的路徑,服務器采取的動作即為middleware,即為一個個特殊的函數(shù)。
2. router路徑
www.baidu.com/test: 路徑為 /test
www.baidu.com/test?name=1&number=2: 路徑同樣為/test, ?后面會被服務器理解傳給路徑的參數(shù)。
3. Middleware
express應用其實就是由一系列順序執(zhí)行的Middleware組成。
中間件其實就是一個訪問express應用傳入的req,res,nex參數(shù)的函數(shù),這個函數(shù)可以訪問任何通過req,res傳入的資源。
如果當前中間件沒有完成對網(wǎng)頁的res響應 ,還可以通過next把router 留給下一middleware繼續(xù)執(zhí)行
路由的產(chǎn)生是通過HTTP的各種方法(GET, POST)產(chǎn)生的,Middleware可以跟router路徑跟特定的HTTP方法綁定,也可以跟所有的方法綁定。
3.1 通過express應用的use(all),把Middleware同router路徑上的所有HTTP方法綁定:

app.use(function (req, res, next) {
    console.log('Time: %d', Date.now());
    next();
})

3.2 通過express應用的http.verb,把Middleware同router路徑上的特定的HTTP方法綁定:

app.get('/', function(req, res){
  res.send('hello world');
});
app.post('/', function(req, res){
  res.send('hello world');
});

4、express的Router對象
當express實例的路由越來越多的時候,最好把路由分類獨立出去,express的實例(app) 能更好的處理其他邏輯流程。Express的Router對象是一個簡化的 app實例,只具有路由相關的功能,包括use, http verbs等等。最后這個Router再通過app的use掛載到app的相關路徑下。

var express = require('express');
var app = express();
var router = express.Router();
// simple logger for this router's requests
// all requests to this router will first hit this middleware
router.use(function(req, res, next) {
  console.log('%s %s %s', req.method, req.url, req.path);
  next();
});
// this will only be invoked if the path ends in /bar
router.use('/bar', function(req, res, next) {
  // ... maybe some additional /bar logging ...
  next();
});
// always invoked
router.use(function(req, res, next) {
  res.send('Hello World');
});
app.use('/foo', router);
app.listen(3000);

router的路由必須通過app.use和app.verbs 掛載到app上才能被響應。所以上述代碼,只有在app捕捉到 /foo路徑上的路由時,才能router中定義的路由,雖然router中有針對 '/' 的路由,但是被app中的路由給覆蓋了。

5、附:app.verbs和app.use的路由路徑區(qū)別:
先看一段測試代碼:

var express = require('express');
var app = express();
var router = express.Router();
app.get('/', function(req, res){
     console.log('test1');
});
app.use('/', function(req, res){
     console.log('test2');
});
router.get('/', function(req, res){
     console.log('test3');
});
app.listen(4000);

輸入url: localhost:4000
輸出結果:test1
輸入url: localhost:4000/hello
輸出結果:test2

結論:app.get掛載‘/’的路由只響應跟'/'精確匹配的GET請求。 而app.use掛載的'/'的路由響應所有以'/' 為起始路由的路由,且不限制HTTP訪問的方法。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI