Go實現一個mvc模式的web路由

main函數,實例化http server,自動加載路由映射表:api

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  路由規則的具體實現:mvc

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)
        }
}
相關文章
相關標籤/搜索