學習使用ExpressJS 4.0中的新Router

MaxWang發表於2019-02-16

概述

ExpressJS 4.0中提出了新的路由Router。Router好比是一個“迷你版”的express應用,它沒有引入views或者settings,但是提供了路由應有的API,.use.get,.paramroute

示例應用

讓我們建立一個express應用,僅僅有少量routes和功能:

  • 基礎路由:HomeAbout
  • 一個把request請求列印到console的路由中介軟體
  • 一個帶引數的路由
  • 一個校驗特殊引數的路由中介軟體
  • 一個用於登入的路由,響應對與路徑/login的GET和POST請求
  • 校驗功能:校驗傳遞給某一個路由的引數

應用檔案架構

我們只需要兩個檔案:

- package.json  // 構建node應用所需要的外掛
- server.js     // 構建示例應用的啟動檔案

我們會把路由程式碼寫如server.js檔案。將來為了讓示例應用模組化,我們會把這些路由程式碼分別寫入不同的檔案,甚至可以為網站的不同組成部分單獨定義不同的路由檔案。

建立Node應用

建立node應用,我們需要編寫package.json檔案去定義node應用依賴的外掛。

{
    "name": "express-router-experiments",
    "main": "server.js",
    "dependencies": {
        "express": "~4.0.0"
    }
}

下面繼續安裝依賴:

$ npm install

現在我們安裝了Express,讓我們繼續編寫server.js去處理路由。

建立server

我們在package.json中指定了main屬性值為server.js,因此Express會使用server.js作為應用的入口檔案。

// server.js

// 基礎設定
// ==============================================

var express = require(`express`);
var app     = express();
var port    =   process.env.PORT || 8080;

// 路由
// ==============================================

// 示例路由
app.get(`/sample`, function(req, res) {
    res.send(`this is a sample!`);  
});

// 我們會在這裡編寫自己的路由

// 啟動server
// ==============================================
app.listen(port);
console.log(`Magic happens on port ` + port);

現在我們可以使用命令node server.js啟動server。我們使用app.get建立了一個Express 3時代的路由,如果此時開啟瀏覽器訪問http://localhost:8080/sample,我們就能看到這樣下面的文字:this is a sample!

基本用法 express.Router()

下面我們一起編寫Node應用前端路由的例子,包括Home頁面和About頁面。

// server.js

...

// 獲取router例項
var router = express.Router();

// home頁面路由(http://localhost:8080)
router.get(`/`, function(req, res) {
    res.send(`im the home page!`);  
});

// about頁面路由(http://localhost:8080/about)
router.get(`/about`, function(req, res) {
    res.send(`im the about page!`); 
});

// 把定義好的路由整合到Node應用中
app.use(`/`, router);

...

我們前面的程式碼使用express.Router()生成一個路由例項,並定義路由規則,最後把這個路由例項整合到應用中。現在我們可以通過http://localhost:8080訪問Home頁面,通過http://localhost:8080/about訪問about頁面。

請注意:我們可以改變前面定義的路由中預設的根路徑(`/`)。如果我們把app.use(`/`, router)改為app.use(`/app`, router),那麼home頁面的訪問地址變為http://localhost:8080/app,about頁面的訪問地址變為http://localhost:8080/app/about

這是一個非常有用的功能,我們可以利用它建立多個路由例項express.Router()並把這些例項都整合到Node應用中。例如,可以在Node應用中針對不同功能需求建立不同的路由:一個基礎路由,一個用於許可權校驗的路由和其他API路由。如此一來,Node應用變得更加模組化更容易擴充套件。

建立路由中介軟體Router.use()

路由中介軟體實際是一種允許一個request請求被處理之前進行某些操作的機制。例如,在把一個request請求的響應資料返回給使用者之前,我們可以檢查使用者是否有許可權,可以記錄日誌等等。
下面我們實現一個列印日誌的中介軟體,每次有一個request請求,我們就在console列印一條資訊。

// server.js

...

// 獲取router例項
var router = express.Router();

// 路由中介軟體:每當有一個request請求都會執行
router.use(function(req, res, next) {

    // 列印request的method和url
    console.log(req.method, req.url);

    // 繼續處理request請求,尋找匹配的路由
    next(); 
});

// home頁面路由 (http://localhost:8080)
router.get(`/`, function(req, res) {
    res.send(`im the home page!`);  
});

// about頁面路由 (http://localhost:8080/about)
router.get(`/about`, function(req, res) {
    res.send(`im the about page!`); 
});

// 把定義好的路由整合到Node應用中
app.use(`/app`, router);

...

我們用router.use()用來定義了路由中介軟體,並且把它應用到所有訪問我們Node應用的請求上。開啟瀏覽器訪問http://localhost:8080/app,我們可以看到console列印的資訊:im the home page!

在程式碼中,中介軟體和路由的位置順序非常重要。一個request請求到來時,它們會按照程式碼中的先後順序依次執行。這就意味著如果你把中介軟體寫在某一個路由的後面,路由會攔截這個request請求並完成響應,中介軟體則永遠不會被執行。

帶引數的路由 /hello/:name

我們想要在URL中傳遞一個人的名字name,讓NODE應用輸出 Hello name! 這裡可以使用帶引數的路由。

// server.js
...
// 獲取router例項
var router = express.Router();
...

// 帶引數的路由 (http://localhost:8080/hello/:name)
router.get(`/hello/:name`, function(req, res) {
    res.send(`hello ` + req.params.name + `!`);
});

// 把定義好的路由整合到Node應用中
app.use(`/`, router);
...

現在我們訪問http://localhost:8080/hello/holly就可以看到瀏覽器頁面展示的資訊:

Hello holly!

建立引數中介軟體

如果想要校驗上面傳入URL的人的名字,確保名字是符合規範的,我們需要在路由中介軟體中去校驗URL中的引數name。它有個特殊的名字,引數中介軟體。我們可以使用express.param()去建立它。

// server.js
...

// 獲取router例項
var router = express.Router();

...

// 引數中介軟體 校驗name引數
router.param(`name`, function(req, res, next, name) {
    // 在這裡進行校驗操作
    console.log(`doing name validations on ` + name);

    // 校驗通過我們把校驗後的名字賦值給req物件
    req.name = name;
    // 繼續處理request請求,尋找匹配的路由
    next(); 
});

// 帶引數的路由 (http://localhost:8080/hello/:name)
router.get(`/hello/:name`, function(req, res) {
    res.send(`hello ` + req.name + `!`);
});

// 把定義好的路由整合到Node應用中
app.use(`/`, router);

現在當我們訪問到/hello/:name路由,我們編寫的引數中介軟體就會介入並做相應的校驗處理。校驗通過我們把校驗後的名字賦值給req物件,並在相應的.get路由中使用req.name獲取校驗後的名字。開啟瀏覽器,訪問http://localhost:8080/hello/sally,我們可以看到瀏覽器展示的資訊:

Hello sally!

console控制檯列印出:

doing name validations on sally

如果你使用RESTful API,你甚至可以校驗token是否有效,來判斷使用者是否有許可權訪問。

鏈式路由

我們也可以直接在app物件上建立路由。利用app.route()可以針對一個路由定義多個路由處理函式。例如,對/login路由發起get請求,展示登入介面,同時也可以對/login路由發起post請求,提交登入表單資訊。我們就可以使用app.route來建立這個/login路由。

// ROUTES
// ==============================================

app.route(`/login`)

    // 展示登入介面 (GET http://localhost:8080/login)
    .get(function(req, res) {
        res.send(`this is the login form`);
    })

    // 提交登入表單 (POST http://localhost:8080/login)
    .post(function(req, res) {
        console.log(`processing`);
        res.send(`processing the login form!`);
    });

...

總結

使用Express 4.0中的路由,我們可以更靈活的定義路由:

  • 多次使用express.Router()定義一組路由
  • 使用express.Router()劃分模組,並用app.use()把他們整合起來
  • 使用路由中介軟體對request請求進行預處理
  • 使用引數中間.param()件對URL中引數進行校驗
  • 使用app.route()建立鏈式路由

相關文章