使用Golang 封装一个Api框架----请求处理篇

前言:此框架的请求处理主要是依赖于Golang中的net/http包

  1. http.ListenAndServe 方法的使用

    1. 实现http简单服务示例:参考文档 https://studygolang.com/pkgdoc

      1. 示例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. 示例2:

        s := &http.Server{
         Addr:           ":8080",
         Handler:        myHandler,
         ReadTimeout:    10 * time.Second,
         WriteTimeout:   10 * time.Second,
         MaxHeaderBytes: 1 << 20,
        }
        log.Fatal(s.ListenAndServe())
        
  2. 本框架的处理思路:

    1. 从http包看,http.ListenAndServe(":8080", nil) 这个方法的第二个参数是http.Handler对象,而这个对象是一个接口,所以要实现ServeHttp方法

      type Handler interface {
      	ServeHTTP(ResponseWriter, *Request)
      }
      
    2. 在core包下面声明了一个Application对象,这个对象实现了 ServeHTTP 方法,在这个方法里面进行路由的判断,然后根据取到的路由找到 控制器和对应的方法,最后在协程里面利用反射调用 对用的控制器的相应的方法从而得到调用方法的结果(这个结果指的是方法调用成功或者失败之类的结果)。在执行调用方法的过程中,http请求的参数通过 ServeHTTP的 *Request对象获取,http的响应的结果可以通过 fmt.Fprint(ResponseWriter对象, "响应结果字符串")。

      注:关于请求参数的获取以及响应结果的返回,在之后的博客中会详细讲到。

    3. 框架入口: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 的思路执行。

  3. 其他处理

    1. 路由的处理

      在这个框架中路由如下:

      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数组获取到对应的控制器的结构体的地址,然后通过反射机制调用对应的控制器的对应方法

    2. 利用反射调用方法

      // 反射调用方法     
      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框架中(根据解析到的路由,动态执行方法)用得比较多一些。

注:1. 本文涉及到的代码的git仓库地址:https://github.com/zhuchenglin/goweb
      2. 如需转载请注明出处: https://www.cnblogs.com/zhuchenglin/p/12687746.html

posted @ 2020-04-12 21:22  lin_zone  阅读(...)  评论(...编辑  收藏