项目地址
本项目依赖
使用标准库实现,无额外依赖
为什么需要路由调度层
golang http标准库只能精确匹配请求的URI,然后执行handler。现在一般web项目都至少有个Controller层,以struct实现,根据不同的请求路径派发到不同的方法中去。
路由调度器定义
Class.forName("xxx").newInstance()
routesaaction名称ccontroller名称controllerName*http.Requesthttp.ResponseWriter
由于golang的继承不是一般的OOP,所以也没有父子类这种说法,路由注册那里只能使用interface{}
代码实现
app/app.go
该文件为核心调度文件
package app
import (
"net/http"
"reflect"
"fmt"
)
type application struct {
routes map[string]interface{}
}
func New() *application {
return &application{
routes: make(map[string]interface{}),
}
}
func (p *application) ServeHTTP(w http.ResponseWriter, r *http.Request) {
controllerName := r.URL.Query().Get("c")
actionName := r.URL.Query().Get("a")
if controllerName == "" || actionName == "" {
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
return
}
route, ok := p.routes[controllerName]
if !ok {
http.Error(w, "Controller Not Found", http.StatusNotFound)
return
}
ele := reflect.ValueOf(route).Elem()
ele.FieldByName("Request").Set(reflect.ValueOf(r))
ele.FieldByName("Response").Set(reflect.ValueOf(w))
ele.MethodByName(actionName).Call([]reflect.Value{})
}
func (p *application) printRoutes() {
for route, controller := range p.routes {
ele := reflect.ValueOf(controller).Type().String()
fmt.Printf("%s %s\n", route, ele)
}
}
func (p *application) Get(route string, controller interface{}) {
p.routes[route] = controller
}
func (p *application) Run(addr string) error {
p.printRoutes()
fmt.Printf("listen on %s\n", addr)
return http.ListenAndServe(addr, p)
}
app/controller.go
控制器"基类"
package app
import "net/http"
type Controller struct {
Response http.ResponseWriter
Request *http.Request
}
controller/site.go
具体业务逻辑类
package controllers
import (
"fmt"
"app"
)
type SiteController struct {
app.Controller
}
func (p SiteController) Index() {
fmt.Fprint(p.Response, p.Request.RequestURI)
}
main.go
入口文件
package main
import (
_ "github.com/go-sql-driver/mysql"
"app"
"controllers"
)
func main() {
application := app.New()
application.Get("site", &controllers.SiteController{})
application.Run(":8080")
}
运行项目
http://localhost:8080?c=site&a=Index/?c=site&a=Index
写在最后
希望这个小小的项目能启发到各位读者,早日开发出适合自己的Web框架!