此框架的请求处理主要是依赖于Golang中的net/http包
http.ListenAndServe 方法的使用
实现http简单服务示例:参考文档 https://studygolang.com/pkgdoc
示例1
http.Handle("/foo", fooHandler)
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})
log.Fatal(http.ListenAndServe(":8080", nil))
示例2:
s := &http.Server{
Addr: ":8080",
Handler: myHandler,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
log.Fatal(s.ListenAndServe())
本框架的处理思路:
从http包看,http.ListenAndServe(":8080", nil) 这个方法的第二个参数是http.Handler对象,而这个对象是一个接口,所以要实现ServeHttp方法
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
在core包下面声明了一个Application对象,这个对象实现了 ServeHTTP 方法,在这个方法里面进行路由的判断,然后根据取到的路由找到 控制器和对应的方法,最后在协程里面利用反射调用 对用的控制器的相应的方法从而得到调用方法的结果(这个结果指的是方法调用成功或者失败之类的结果)。在执行调用方法的过程中,http请求的参数通过 ServeHTTP的 *Request对象获取,http的响应的结果可以通过 fmt.Fprint(ResponseWriter对象, "响应结果字符串")。
注:关于请求参数的获取以及响应结果的返回,在之后的博客中会详细讲到。
框架入口:public包中的main.go
func main() {
routers := route.GetRouter()
controllers := route.GetControllers()
app := new(core.Application)
app.Routers = routers
app.Controllers = controllers
err := http.ListenAndServe("localhost:8080", app)
if err != nil {
log.Println("ListenAndServe: ", err)
}
}
}
在这个方法中首先 初始化一个Application对象,然后获取用户注册的路由及控制器,将其作为app对象的属性赋给app对象,然后使用http.ListenAndServe("localhost:8080", app) 。当请求过来的时候就会直接到app的ServeHTTP方法中,然后就会顺着 2 的思路执行。
其他处理
路由的处理
在这个框架中路由如下:
package route
import "goweb/controller"
var routers = map[string]string{
// 示例 请求类型@控制器@方法
"/test": "get@TestController@Test",
}
var controllers = map[string]interface{}{
// 示例 反射中用到
"TestController": &controller.TestController{},
}
func GetRouter() map[string]string {
return routers
}
func GetControllers() map[string]interface{} {
return controllers
}
在1.2.3 中提到了这个框架的路由的使用时 赋值给app对象了,然后再app中进行路由处理。通过routers数组可以获取路由和控制器、方法之间的关系,通过controllers数组获取到对应的控制器的结构体的地址,然后通过反射机制调用对应的控制器的对应方法
利用反射调用方法
// 反射调用方法
func CallFuncByName(myClass interface{}, funcName string, params ...interface{}) (out []reflect.Value, err error) {
myClassValue := reflect.ValueOf(myClass)
m := myClassValue.MethodByName(funcName)
if !m.IsValid() {
return make([]reflect.Value, 0), fmt.Errorf("Method not found \"%s\"", funcName)
}
in := make([]reflect.Value, len(params))
for i, param := range params {
in[i] = reflect.ValueOf(param)
}
out = m.Call(in)
return out, nil
}
反射一般用在知道对象及方法名称,想要得到对象的类或者调用对象的方法的情况。在MVC框架中(根据解析到的路由,动态执行方法)用得比较多一些。
注:
原文:https://www.cnblogs.com/zhuchenglin/p/12687746.html