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)
}
}