中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

淺析Express中的路由與應用模式

發布時間:2020-06-25 14:34:43 來源:網絡 閱讀:1930 作者:簡單是美美 欄目:web開發

1. 引言

Express是一個基于Node.js的輕量級web開發框架,具有體積小,使用靈活等特點。查看Express的源碼,如果不計供使用的中間件,主體框架只有一千余行代碼,非常簡練。

Express模型的核心為Express中定義的路由和路由器。分析Express源碼可發現Express的路由提供多種靈活的應用模式。

我們首先介紹一下Express中的路由、路由器相關概念、結構及其特點,然后針對典型場景描述使用Express路由的四種應用模式。

2.Express中的路由與路由器

Express具有典型的MVC模型特征。我們將路由定義為一個二元組route=(path, endpoint):其中pathHTTP請求的路徑,endpoint為請求路徑應映射到的端點(端點可視為處理該請求的實體),Express中的路由器負責將請求映射到對應端點進行處理。

Express中的路由器分為兩種類型:

app類型的路由器常使用如下代碼創建:

var express = require('express');
var app = express();

router類型的路由器常使用如下代碼創建:

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

approuter是形為function(request, response, next)形式的函數對象,使用app.verb()router.verb()形式函數實現路由注冊(路由注冊本質上是一個觀察者模式)。

app.verb()router.verb()中的verb常使用usegetpostputdeleteroute等動詞,不同動詞管轄的HTTP請求方法范圍不同,這些動詞函數的參數形式常為(pathExp, handleCallback)形式:其中pathExp表示請求路徑,可為正則表達式;handleCallback為路徑映射處理函數。

app是Express框架所構建程序的請求處理入口,app可作為頂層路由器使用,在應用中也可掛載下級路由器(使用router對象)以實現分級路由。其間的關系可由下圖表示:

淺析Express中的路由與應用模式


考察如下代碼: 

app.use('/reports', router1);
router1.get('/querymysql/:id', queryMysqlData, handleQueryData);

對于http請求URL“/reports/querymysql/1”,Express中的路由器將此請求路由到queryMysqlData函數處理。

3.      Express中的路由應用模式

3.1.   REST模式

對于一個使用restful風格的應用, 讓我們想一想在不使用Express的時候如何在Node.js中處理rest請求,我們常常會寫下如下示例代碼:

var server = http.createServer(function (request, response) {
     switch (request.url) {
                    case 'uri1'
                        handleUri1 (request, response);
                        break;
                    case ' uri2'
                        handleU ri2(request, response);
                        break;
                    case ' uri3'
                        handleU ri3 (request, response);
                        break;
 
                    case ' uri4'
                        handleU ri4 (request, response);
                        break;
                    ...
                    default:
                        logToConsole('unknown path:' + path);
                        response.writeHead(404);
                        response.end("404 Not found");
                        break;
                }
}

Express將上面代碼中對每個rest資源的操作(switch分支)轉換為路由,路由中的路徑為rest資源的URI,處理端點為function(request, response, next)形式、對rest資源的操作函數。

常使用app.route函數實現一個完整的restful接口,如下示例代碼:

app.route('/uri1')
  .get(function(req, res) {
    handleGetUri1();
  })
  .post(function(req, res) {
    handlePost Uri1 ();
  })
  .put(function(req, res) {
    handlePut Uri 1();
  })
.delete(function(req, res) {
    handleDeleteUri 1();
  });

3.2.   AOP模式

在處理不同路徑的HTTP請求時,常常需要在請求處理前和處理后做一些通用操作,這種應用需求是一個典型的AOP應用要求。

Express中允許定義一個具有通配路徑的路由,在調用其它路徑的路由前會先調用該通配路徑路由。此通配路徑路由也成為其它路徑路由切面的一個注入點,考察如下示例代碼:

router.use(function timelog(req,res,next){
    console.log("receive report request time is:",Date.now());
    next(); //注意next函數的使用,必須聲明該函數才能調用后繼映射函數
});
 
router.get('/chart1', proxy({
    target: 'http://127.0.0.1:8082',
    changeOrigin: true,
    pathRewrite: {
        '^/reports/chart1': '/loadChart1'
    }
}));
 
router.get('/querymysql/:id', queryMysqlData, handleQueryData);

上述代碼中,在執行router'/chart1'路由和'/querymysql/:id'路由之前都會執行timelog函數,在日志中記錄當前路由執行時間。

3.3.   責任鏈模式

Node.js中,由于多使用異步函數,常會出現異步回調函數中嵌套異步回調函數的情形。當出現多重異步回調時,則代碼會變得混亂和難以維護。

考察一個應用場景:應用需要在數據庫中進行多次查詢,并對多次查詢的結果綜合處理。若使用數據庫提供的異步查詢接口,則需要在前一個查詢操作的回調函數中進行下一個查詢操作,若寫在一個回調函數中,代碼顯臃腫。

Express的一個路由可定義多個處理函數,這些處理函數可設計為鏈式調用,實現了責任鏈模式,考察如下代碼:

app.get('/test',function(req,res,next){
    handle1();
    next();
},function(req,res,next){
    handle2();
    next();
},function(req,res,next){
   handle3();
});

上述代碼中:handle1, handle2, handle3構成了一個處理責任鏈“handle1->handle2->handle3”,通過next函數指引鏈式調用。

Express中路由的責任鏈應用特性使得多重異步嵌套的代碼變得清晰和優雅。

    針對本節開始提到的數據庫查詢應用場景,下面的示例代碼展示了責任鏈模式的應用特點。

router.get('/querymysql/:id', queryMysqlData, handleQueryData);
 
//查詢mysql表中的數據
function queryMysqlData(req, res, next) {
    if ("id" in req.params) {
        dbpool.query(" select * from articles where id=?" ,[req.params.id], function (err, rows, fields) {
            if (err) {
                res.send(err.stack);
            } else {
                if (rows && rows.length > 0) {
                    console.log('The queried rows is: ', rows.length);
                    res.articles = rows;
                    next();
                } else {
                    res.send("no query results!");
                }
            }
        });
    } else {
        res.send("invalid query params!");
    }
}
 
//處理查詢mysql后得到的數據
function handleQueryData(req, res) {
    if ("articles" in res) {
        res.send("id:" + req.params.id + ";title:" + res.articles[0].title);
    }else{
        res.send("no query data handled!");
    }
}

3.4.   熔斷器模式

上節提到的責任鏈模式本質上是一個逐級調用模型。在分布式服務架構(微服務架構)中,深度調用常常需要考慮調用可達性問題,即需要考慮某級調用會否一直不響應。調用可達性問題常使用熔斷器模式,即在調用端設置一個熔斷器,熔斷條件產生時,熔斷器發生熔斷,返回給調用方調用失敗信息。

考慮這樣的應用場景:對于一些有處理時間要求的請求,當在指定時間內沒有完成處理,需要向請求方返回處理失敗信息。針對此應用場景,可在Express路由中設置超時熔斷器,當處理超時,開啟熔斷器,通知請求方本次處理請求失敗。

上述應用場景可使用如下示例代碼應對:

app.get('/circuit',function(req, res, next){
    var bt=setTimeout(function () {
        next('route'); //觸發熔斷
    },3000); //設置熔斷時間為3秒
   res.breakTimer = bt;
   next();
},function(req,res,next){
    handle2();
    next();
},function(req,res,next){
   handle3();
   clearTimeout(res.breakTimer);//正常執行完畢,取消熔斷定時器
});
 
app.get('/circuit ',function(req,res,next){
  if(!res.finished){ //如果還沒有響應,啟動熔斷
    //返回給調用者熔斷信息
    res.send("breakCondition is true, notify the invoker.");
  }
});


4.      小結

本文介紹了Express框架中路由和路由器的概念、結構和特點,并針對典型應用場景歸納了RESTAOP、責任鏈、熔斷器四種應用模式,可用于應用開發中的一些常用場景。

5.      參考文獻

  1.  http://expressjs.com/

  2. http://www.runoob.com/



向AI問一下細節

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

AI

揭西县| 谷城县| 郎溪县| 汾阳市| 阿尔山市| 津南区| 灯塔市| 常熟市| 黑山县| 吉林市| 永寿县| 安图县| 溧水县| 张北县| 上思县| 开封县| 鄂温| 博爱县| 青田县| 米易县| 营口市| 福鼎市| 和静县| 云梦县| 博白县| 泸定县| 左云县| 勃利县| 土默特右旗| 廉江市| 天全县| 北流市| 神农架林区| 湘潭县| 长葛市| 泰州市| 沁源县| 石阡县| 临邑县| 齐齐哈尔市| 垣曲县|