天天看點

【nodejs】讓nodejs像後端mvc架構(asp.net mvc )一樣處理請求--自動路由篇(1/8)【route】前情概要我們的實作思路攔截所有請求根據規則進行路由的比對

文章目錄

前情概要

在使用express架構開發的時候,每加一個請求,都在增加一條route請求規則,類似于下面的代碼,很煩有木有!

app.use('/myroute path', (req, res, next) => { //dosomething })

我們難道不能再智能一點點麼,學習後端mvc架構一樣,比如加個标記,或者預設規則直接自動映射嘛。約定勝于配置嘛!

我們的實作思路

  1. 攔截所有請求
  2. 根據我們的規則進行路由的比對
  3. 調用比對到的處理函數

這個太好辦了,app.use('/') 搞定。參考下面的代碼

import * as express from 'express'
import * as controllers from './controller'
import { RequestHandler, RouteHandler } from 'gd-express-basic'

const _app = express();
//第一個express 中間件,處理一下跨域請求中的options請求。
_app.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Content-Type,Content-Length,Authorization,Accept,X-Requested-With');
    res.header('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS');
    if (req.method == 'OPTIONS') {
        res.send(new ResponseBase(200));
    }
    next && next();
});
//第二個中間件,攔截所有請求對路由做自動映射
RouteHandler(_app, controllers);
//第三個中間件,處理請求
_app.use(RequestHandler);
//第N個中間件,處理一下error呀,404呀等其他情況。           

根據規則進行路由的比對

接下來看一看RouteHandler方法。主要幹幾個事情

  1. 緩存所有action,友善後續的調用。【 請求處理函數的特性注冊篇【 詳細說明】
  2. 攔截所有請求,并根據規則解析到對應的action上面去。【app.use('/', (req, res, next)】
  3. 根據解析出來的controller 、action名稱以及目前請求的method找到對應的action并記錄到目前請求對象上,友善接下來的請求處理。

    目前我們的規則很簡單。url分2層,第一層為controller名稱,第二層為action名稱。即:/{controller}/{action};

/**
 * 路由選擇進行中間件
 * 
 * @export
 * @param {core.Express} app 
 * @param {*} controllers 
 */
export function RouteHandler(app: core.Express, controllers: any) {
   //程式啟動的時候,找到目前所有的controllers,并根據規則緩存好我們所有的處理函數(action),友善接下來的比對
   //請求處理函數發現篇【controller+action】具體講到
    find(controllers)
//攔截所有請求,對請求
    app.use('/', (req, res, next) => {
    //拿到route并解析出來controller和action的名稱。
        var pathArr = getRouteTokens(req.path)
        var controller = (pathArr[0] && pathArr[0].toLowerCase()) || 'home';
        var action = (pathArr[1] && pathArr[1].toLowerCase()) || 'index'
        //根據參數找到能處理這個請求的action
        var desc = GetActionDescriptor(controller, action, req.method)
        if (!desc) {
            desc = GetActionDescriptor(controller, '_default', req.method)
        }
        if (desc && (!desc.HttpMethod || (desc.HttpMethod && desc.HttpMethod === req.method))) {

            res.locals.authInfo = { isAuth: desc.isAuth };
            //如果請求能比對到可以處理的action,則指派
            res.locals.actionDescriptor = desc;
        }else{//否則跳過。當然在這裡也可以直接傳回404,結束本次請求。
         }
        next && next()
    })
}

function getRouteTokens(path: string) {
    var pathArr = path.split('/');
    var arr: string[] = [];
    pathArr.forEach(element => {
        if (element) arr.push(element)
    });
    return arr
}           
代碼那是相當的簡單。其實隻幹了一件事情,據我們的url規則找到與之比對的在項目啟動的時候掃描緩存的請求處理函數
  1. 考慮到前端不太會有area的概念,是以暫時沒有支援,如果要支援其實也很簡單,增加一個area注冊,然後再做路由比對的時候多判斷一次area就完事兒了。
  2. 估計也不太會有自定義route 的要求,比如dotnet mvc 裡面的【[Route("/path")]】特性。是以也暫未做支援。如果确實有也可以通過app.use實作。

繼續閱讀