Controller

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

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

/*
Controller 定义控制器接口。

控制器默认具有Base、Data、Singleton、AutoRoute、View五种实现:
    Base是最基本的控制器实现;
    Data在Base基础上使用ContextData作为请求上下文,默认具有更多的方法;
    Singleton是单例控制器,每次请求公用一个控制器;
    AutoRoute将控制器方法转换成处理函数使用,使用函数扩展;
    View在Base基础上会使用Data和推断的模板渲染view。

默认控制器实现下列功能:
    控制器处理,将控制器对应方法转换成路由注册
    有状态和无状态控制器,使用控制器处理扩展(ControllerBase controllerPoolSingleton)
    路由映射控制器,将方法转换成一般的路由处理函数,使用函数扩展(ControllerAutoRoute)。
    控制器构造错误传递(NewControllerError)
    控制器前置和后置处理函数,Init和Release方法在控制器方法前后调用
    自定义控制器函数映射关系(实现func ControllerRoute() map[string]string)
    自定义控制器路由组和路由参数(实现func ControllerParam(pkg, name, method string) string)
    控制器路由组合,如果组合一个名称为xxxController控制器,会组合获得xxx控制器的路由方法
    控制器方法组合,如果组合一个名称非xxxController控制器,可以控制器属性ctl.xxx直接调用方法。
*/
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.ControllerParam
    }

    // 路由器注册控制器方法
    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.ControllerParam
    }

    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
}

results matching ""

    No results matching ""