Go实现一个mvc模式的web路由 - Go语言中文社区

Go实现一个mvc模式的web路由


main函数,实例化http server,自动加载路由映射表:

package main                                                                                                                                                                                                                                                                  

import ( 
        "go-safe-info-flow/controllers"
        "library"
        "runtime"
)

func main() {
        //实例化一个HttpServer                                                                                                        
        server := library.NewServer("", 8080)
        //业务使用的controller在这里进行注册,将c/a关系加入到路由映射表中以作自动路由                                                                                                                                                                                          
        server.AddController(&controllers.FrontSkin{})
        server.Run()
}

library.HttpApi.go  路由规则的具体实现:

package library

import (
        "net/http"
        "reflect"
        "runtime"
        "strconv"
        "strings"
)

//http api最重要的两部分
//1. 根据业务定制处理不同路由规则的handler  扩展到mvc结构中就是每一个请求找到对应的m/c/a
//2. 实例化一个server并 监听端口

func NewServer(addr string, port int) *HttpServer {
        return &HttpServer{
                httpAddr: addr,
                httpPort: port,
                mux:      &httpMux{router: make(map[string]map[string]reflect.Type)},
        }   
}

//自定义一个server结构
type HttpServer struct {
        httpAddr string
        httpPort int 

        mux *httpMux
}

//多路复用器
type httpMux struct {
        router map[string] /*controller*/ map[string] /*action*/ reflect.Type
}

const (
        controllerSuffix = "Controller"
        actionSuffix     = "Action"
)

//添加controller
func (this *HttpServer) AddController(c interface{}) {
        reflectType := reflect.TypeOf(c)
        //      reflectVal := reflect.ValueOf(c)
        typeVal := reflectType.Elem()
        //获取controller name  只有reflectType才可以获取
        var controllerName string
        if hasSuffix := strings.HasSuffix(typeVal.Name(), controllerSuffix); hasSuffix {
                controllerName = strings.TrimSuffix(typeVal.Name(), controllerSuffix)
        } else {
                controllerName = strings.TrimSpace(typeVal.Name())
        }

        //controller已经添加到路由中了
        if _, ok := this.mux.router[controllerName]; ok {
                return
        } else {
                this.mux.router[controllerName] = make(map[string]reflect.Type)
        }

        this.mux.addAction(controllerName, reflectType)
}

func (this *httpMux) addAction(controllerName string, rt reflect.Type) {
        for i := 0; i < rt.NumMethod(); i++ {
                method := rt.Method(i).Name
                if strings.HasSuffix(method, actionSuffix) {
                        action := strings.TrimSuffix(method, actionSuffix)
                        this.router[controllerName][action] = rt.Elem()
                }
        }

}

//handler实现方法,自动路由,并执行相应的业务逻辑方法
func (this *httpMux) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
        //解析参数
        //      r.ParseForm()
        path := strings.TrimPrefix(r.URL.Path, "/")

        if path == "" || path == "/" {
                //              rw.WriteHeader(http.StatusForbidden)
                http.Error(rw, "forbidden", http.StatusForbidden)
                return
        }

        rPath := strings.Split(path, "/")
        cname := strings.Title(rPath[0])
        if _, ok := this.router[cname]; ok {
                var mname string
                if len(rPath) == 1 || rPath[1] == "" {
                        mname = "Index"
                } else {
                        mname = strings.Title(rPath[1])
                }

                if controller, ok := this.router[cname][mname]; ok {
                        //初始化controller 返回指向struct的指针
                        //var in []reflect.Value

                        vc := reflect.New(controller)
                        methodName := mname + actionSuffix

                        r.ParseForm()
                        method := vc.MethodByName("Init") //初始化controller
                        in := make([]reflect.Value, 0, 2)
                        in = append(in, reflect.ValueOf(rw))
                        in = append(in, reflect.ValueOf(r))
                        method.Call(in)

                        method = vc.MethodByName(methodName)

                        method.Call([]reflect.Value{})

                } else {
                        http.NotFound(rw, r)
                        return
                }
        } else {
                http.NotFound(rw, r)
                return
        }

}

//运行server
func (server *HttpServer) Run() {
        runtime.GOMAXPROCS(runtime.NumCPU())
        //      addr := fmt.Sprintf("%s:%d", server.httpAddr, server.httpPort)
        addr := server.httpAddr + ":" + strconv.Itoa(server.httpPort)
        err := http.ListenAndServe(addr, server.mux)

        if err != nil {
                panic(err)
        }
} 

 

转载于:https://my.oschina.net/u/3470972/blog/1552020

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_34365635/article/details/92388936
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-04-19 09:19:45
  • 阅读 ( 1175 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢