本书未发布

5.10. Eudore控制器

未匹配的标注

Controller

eudore控制器实现通过分析控制器得到路由方法路径和闭包执行控制器方法。

控制器接口需要实现初始化、释放和注入三个方法,初始化和释放完成控制器对象的初始化和释放过程,注入方法完成注入控制器对应的路由到路由器中。

type Controller interface {
    Init(Context) error
    Release(Context) error
    Inject(Controller, RouterMethod) error
}

ControllerBase

ControllerBase是最基本的控制器实现,Init会初始化ctx,Inject调用ControllerInjectStateful函数实现注入路由。

type ControllerBase struct {
    Context
}

// Init 实现控制器初始方法。
func (base *ControllerBase) Init(ctx Context) error {
    base.Context = ctx
    return nil
}

// Release 实现控制器释放方法。
func (base *ControllerBase) Release(Context) error {
    return nil
}

// Inject 方法实现控制器注入到路由器的方法,ControllerBase控制器调用ControllerInjectStateful方法注入。
func (base *ControllerBase) Inject(controller Controller, router RouterMethod) error {
    return ControllerInjectStateful(controller, router)
}

// ControllerRoute 方法返回默认路由信息。
func (base *ControllerBase) ControllerRoute() map[string]string {
    return nil
}

ControllerInjectStateful

ControllerInjectStateful函数有状态控制器的路由注入功能。

实现主要分为四段:

  • 先根据控制器名称或者参数设置Group。
  • 然后创建控制器路由参数函数。
  • 遍历通过控制器类型获得路由方法和路由路径组,生成Router.AddHandler的方法和路径参数。
  • 使用ControllerFuncExtend传递控制器方法习惯参数,交给函数扩展处理。
func ControllerInjectStateful(controller Controller, router Router) error {
    pType := reflect.TypeOf(controller)
    iType := reflect.TypeOf(controller).Elem()

    // 添加控制器组。
    cname := iType.Name()
    cpkg := iType.PkgPath()
    group := router.GetParam("controllergroup")
    if group != "" {
        router = router.SetParam("controllergroup", "").Group("/" + group)
    } else if strings.HasSuffix(cname, "Controller") {
        router = router.Group("/" + strings.ToLower(strings.TrimSuffix(cname, "Controller")))
    } else if strings.HasSuffix(cname, "controller") {
        router = router.Group("/" + strings.ToLower(strings.TrimSuffix(cname, "controller")))
    }

    // 获取路由参数函数
    pfn := defaultRouteParam
    v, ok := controller.(controllerRouteParam)
    if ok {
        pfn = v.GetRouteParam
    }

    // 路由器注册控制器方法
    pool := NewControllerPoolSync(controller)
    for method, path := range getRoutesWithName(controller) {
        m, ok := pType.MethodByName(method)
        if !ok || path == "" {
            continue
        }

        router.AddHandler(getRouteMethod(method), path+" "+pfn(cpkg, cname, method), ControllerFuncExtend{
            Controller: controller,
            Name:       fmt.Sprintf("%s.%s.%s", cpkg, cname, method),
            Index:      m.Index,
            Pool:       pool,
        })
    }
    return nil
}

ControllerInjectSingleton

// ControllerInjectSingleton 方法实现注入单例控制器。
//
// 单例控制器的方法规则与ControllerInjectStateful相同。
//
// 如果存在路由器参数enable-route-extend,ControllerInjectSingleton函数将使用路由扩展函数,而不使用控制器扩展函数。
func ControllerInjectSingleton(controller Controller, router Router) error {
    pType := reflect.TypeOf(controller)
    iType := pType.Elem()

    // 添加控制器组。
    cname := iType.Name()
    cpkg := iType.PkgPath()

    switch {
    case router.GetParam("controllergroup") != "":
        group := router.GetParam("controllergroup")
        router = router.SetParam("controllergroup", "").Group("/" + group)
    case strings.HasSuffix(cname, "Controller"):
        router = router.Group("/" + strings.ToLower(strings.TrimSuffix(cname, "Controller")))
    case strings.HasSuffix(cname, "controller"):
        router = router.Group("/" + strings.ToLower(strings.TrimSuffix(cname, "controller")))
    default:
        router = router.Group("")
    }

    enableextend := router.GetParam("enable-route-extend") != ""
    router.SetParam("enable-route-extend", "")
    var fnInit, fnRelease HandlerFunc
    if enableextend {
        fnInit = newControllerSingletionInit(controller, fmt.Sprintf("%s.%s.Init", cpkg, cname))
        fnRelease = newControllerSingletionRelease(controller, fmt.Sprintf("%s.%s.Release", cpkg, cname))
    }

    // 获取路由参数函数
    pfn := defaultRouteParam
    v, ok := controller.(controllerRouteParam)
    if ok {
        pfn = v.GetRouteParam
    }

    pool := NewControllerPoolSingleton(controller)
    for method, path := range getRoutesWithName(controller) {
        m, ok := pType.MethodByName(method)
        if !ok || path == "" {
            continue
        }

        if enableextend {
            // 使用路由扩展
            h := reflect.ValueOf(controller).Method(m.Index)
            SetHandlerAliasName(h, fmt.Sprintf("%s.%s.%s", cpkg, cname, method))
            router.AddHandler(getRouteMethod(method), path+" "+pfn(cpkg, cname, method), fnInit, h.Interface(), fnRelease)
        } else {
            // 使用控制器扩展
            router.AddHandler(getRouteMethod(method), path+" "+pfn(cpkg, cname, method), ControllerFuncExtend{
                Controller: controller,
                Name:       fmt.Sprintf("%s.%s.%s", cpkg, cname, method),
                Index:      m.Index,
                Pool:       pool,
            })
        }
    }
    return nil
}

反馈和交流请加群组:QQ群373278915

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 查看所有版本


暂无话题~