前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【nodejs】让nodejs像后端mvc框架(asp.net mvc)一样处理请求--控制器和处理函数的注册篇(4/8)【controller+action】

【nodejs】让nodejs像后端mvc框架(asp.net mvc)一样处理请求--控制器和处理函数的注册篇(4/8)【controller+action】

作者头像
旺财的城堡
发布2018-11-20 16:38:21
3680
发布2018-11-20 16:38:21
举报
文章被收录于专栏:calvincalvin

前情概要

前边的文章把一些基本的前置任务都完成了。接下就是比较重要的处理函数action是如何自动发现和注册的拉,也就是入口函数RouteHandler(也是我们的第一个express中间件)里面的一些细节。

扫描action并添加到缓存

说一说我们的思路,其实和静态语言中的反射概念有点类似。

  1. 循环传进来的所有controller声明。详见 控制器的声明和定义篇---controller注册到RouteHandler
  2. 循环所有声明的controllers,并将每一个controller里面的action添加到action缓存中。

关键方法也就是Object.getOwnPropertyNames和Object.getOwnPropertyDescriptor2个方法了。目的则是对象上的所有成员,对应到比如说.net,java之类的就是反射拉。

代码语言:javascript
复制
export function RouteHandler(app: core.Express, controllers: any) {
    find(controllers)
    //app.use('/', (req, res, next) => 。。。。。。
}
function find(controllers: any) {
   //controllers本质上是一个对象,类似:{host:{},home:{},site:{}}。那我们这里的key就是controller的名字,value就是controller实列了。
    var _reg_controller_names = Object.getOwnPropertyNames(controllers)//对象上所有成员,就是我们所有的controller名称集合。
    for (var index = 0; index < _reg_controller_names.length; index++) {
        var _reg_controller_name = _reg_controller_names[index];//controller的名称,比如:home
        var _reg_controller_Desc = Object.getOwnPropertyDescriptor(controllers, _reg_controller_name) as PropertyDescriptor//controller的描述对象
        if (_reg_controller_name === '__esModule') continue;

        var cType = _reg_controller_Desc.value;//controller的类型,比如:Homecontroller
        var cName = cType.name;//controller的class名称。比如"HomeController";

        var aNames = Object.getOwnPropertyNames(cType.prototype)//controller所有成员,也就是我们的action
        for (var index2 = 0; index2 < aNames.length; index2++) {
            var aName = aNames[index2];
            if (aName === 'constructor') continue;
            var aType = (Object.getOwnPropertyDescriptor(cType.prototype, aName) as PropertyDescriptor).value//具体的每一个action函数
            SetActionDescriptor(cName, aName, undefined, undefined, _reg_controller_name, cType, aType)//加入缓存
            //第三个参数[httpMethod] 请求方法类型。默认给undefined,后续再通过扫描action上面的特性标签增加进来
            //第四个参数 [actionName] 路由action名字。默认给undefined,后续再通过扫描action上面的特性标签增加进来
        }
    }
}

SetActionDescriptor的实现

代码语言:javascript
复制
/**
 *
 *
 * @export
 * @param {string} controllerTypeName 控制器类型名字
 * @param {string} actionTypeName 方法类型名字
 * @param {string} [httpMethod] 请求方法类型
 * @param {string} [actionName] 路由action名字
 * @param {string} [controllerName] 路由控制器名字
 * @param {*} [controllerType] 控制器对象
 * @param {*} [actionType] action 对象
 * @returns {ActionDescriptor}
 */
export function SetActionDescriptor(controllerTypeName: string, actionTypeName: string, httpMethod?: string, actionName?: string, controllerName?: string, controllerType?: any, actionType?: any, isAuth?: boolean): ActionDescriptor {

    var _actions = _dic_override.get(controllerTypeName)
    if (!_actions) {
        _actions = new Map<string, ActionDescriptor>();
        _dic_override.set(controllerTypeName, _actions)
    }
    var _action = _actions.get(actionTypeName);
    if (!_action) {
        _action = new ActionDescriptor();
        _actions.set(actionTypeName, _action)
    }
    _action.ControllerTypeName = controllerTypeName;
    _action.ActionTypeName = actionTypeName;

    if (!_action.ActionName)
        _action.ActionName = actionTypeName

    if (httpMethod)
        _action.HttpMethod = httpMethod.toUpperCase();

    if (controllerType)
        _action.ControllerType = controllerType;
    if (controllerName)
        _action.ControllerName = controllerName;

    if (actionName)
        _action.ActionName = actionName;
    if (actionType)
        _action.ActionType = actionType

    if (isAuth === true || isAuth === false)
        _action.isAuth = isAuth;

    _action.Id = _action.ActionName + (_action.HttpMethod ? ('_' + _action.HttpMethod) : '')

    return _action
}

SetActionDescriptor方法参数有值得情况下则更新,没有值则跳过。因为针对同一个action可能会被调用多次。对一个action的描述信息也是分部分分多次set进来的。一部分是通过对象的原型,还有一部分则是ts的装饰器(后端语言的attribute)。 需要注意的是每个action有个id字段。id字段使用http method和action name 来拼接。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-07-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前情概要
  • 扫描action并添加到缓存
  • SetActionDescriptor的实现
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档