【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實現。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章