天天看點

【nodejs】讓nodejs像後端mvc架構(asp.net mvc)一樣處理請求--請求處理函數裝飾器注冊篇(5/8)【controller+action】前情概要get,post,actionname的裝飾器實作方式裝飾器使用列子裝飾器的基本原理

文章目錄

前情概要

上篇文章把action的注冊講完了,但是我們的處理函數沒有指定可接受的httpmethod,也沒有别名上面的。下面我們使用typescript的特性之一裝飾器來實作一把這個特性。

在控制器和處理函數的注冊篇中有說到的第三,第四個參數就在這裡排上用場拉。

SetActionDescriptor(cName, aName, undefined, undefined, _reg_controller_name, cType, aType)//加入緩存

第三個參數[httpMethod] 請求方法類型。預設給undefined,後續再通過掃描action上面的特性标簽增加進來

第四個參數 [actionName] 路由action名字。預設給undefined,後續再通過掃描action上面的特性标簽增加進來

get,post,actionname的裝飾器實作方式

代碼非常簡單,通過SetActionDescriptor函數對目前的action的某些屬性進行重寫。

typescript的裝飾器目前來說還是一個實驗性的功能,依照微軟的尿性,應該也沒變動了,就算有也是增加新功能新特性。

然後裝飾器這玩意和後端語言的比如dotnet的特性(attribute)、java的标注等比較相似。可以給方法增加一些額外的資料等。具體,可檢視

typescript 裝飾器參考文檔
import { SetActionDescriptor } from './RouteFactory';
import { ActionParamDescriptor, SetActionParamDescriptor, parameterFromType } from './RouteHandler';
/**
 * 标記目前方法隻接受post請求
 * 
 * @export
 * @returns 
 */
export function post() {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        SetActionDescriptor(target.constructor.name, propertyKey, 'post')
    }
}
/**
 * 标記目前方法隻接受get請求
 * 
 * @export
 * @returns 
 */
export function get() {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        SetActionDescriptor(target.constructor.name, propertyKey, 'get')
    }
}
/**
 * 重寫目前方法的名字,請求使用重寫後的名字進行調用
 * 
 * @export
 * @param {string} actionName 
 * @returns 
 */
export function actionName(actionName: string) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        SetActionDescriptor(target.constructor.name, propertyKey, undefined, actionName)
    }
}           

裝飾器使用列子

覺不覺得眼熟?是不是和C#、java裡面的特性、标注差不多。

//HostController.ts
import { BaseController, get, post, auth, actionName, ViewResult } from "gd-express-basic";

export class HostController extends BaseController {
    @get()
    public index() {
        return this.view("hostIndex", {});
    }
    @auth()
    @post()
    @actionName("saveHost")
    public hostAdd() {
        return this.view("hostAdd", {});
    }
}           

裝飾器的基本原理

HostController.ts 為typescript源檔案代碼。

HostController.js為使用tsc編譯為es6後的代碼。

//HostController.js
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
//decorators 就是我們聲明的裝飾器傳回的處理閉包函數啦
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    //d(target, key, r) ,調用函數,實際上就是return function (target: any, propertyKey: string, descriptor: PropertyDescriptor)調用這裡傳回的這個function。
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
const gd_express_basic_1 = require("gd-express-basic");
class HostController extends gd_express_basic_1.BaseController {
    index() {
        return this.view("hostIndex", {});
    }
    hostAdd() {
        return this.view("hostAdd", {});
    }
}
// 1.執行__decorate函數
__decorate([
    gd_express_basic_1.get(),//調用我們聲明的裝飾器,傳回要處理函數(閉包)
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", void 0)
], HostController.prototype, "index", null);
__decorate([
    gd_express_basic_1.auth(),
    gd_express_basic_1.post(),
    gd_express_basic_1.actionName("saveHost"),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", void 0)
], HostController.prototype, "hostAdd", null);
exports.HostController = HostController;
//# sourceMappingURL=HostController.js.map           

簡單來說就是在源檔案加載的時候執行一次__decorate函數,__decorate函數内可以簡單了解為調用我們的聲明的裝飾器函數傳回的閉包函數。

到此,我們的controller和action的發現和配置基本上算完成了。