• 使用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

  • 相关阅读:
    【Git】为GitHub添加ssh配置
    【Linux】cmake编译指定 gcc/g++
    【Git】提交历史查看
    【AFL(十五)】LAVA-M服务器篇
    Docker实用技巧(五):查看容器占用磁盘大小
    Docker实用技巧(四):限制cpu数量
    【AFL(十四)】afl-plot 使用详解
    【AFL(十三)】afl-whatsup 使用详解
    Docker实用技巧(三):容器与主机之间的端口映射
    【AFL(十二)】make文件管理
  • 原文地址:https://www.cnblogs.com/zhuchenglin/p/12687746.html
Copyright © 2020-2023  润新知