上下文

201 阅读3分钟

具体代码看Github

完整框架看Github

上下文

设计Context

  1. 对于Web服务来说,无非是根据*http.Request,响应http.ResponseWriter。但是这两个接口提供的方法粒度太细。 当我们想要返回一个完成的响应,需要考虑响应头和响应体,其中响应头中又包含响应状态码,响应消息类型等等。而且每次都需要 这样操作,显得太繁琐
  2. 使用Context将请求对象和响应对象进行封装,优化用户的使用体验,并且对一些操作进行自定义

思考一下,请求上下文需要在哪里创建?

  • 之前我们聊过,ServeHTTP方法向前对接用户[浏览器],向后对接Web框架
  • 请求上下文肯定是用户请求对来了的时候创建,对吧,因此得出结论:在ServeHTTP中创建

问题又来了,构建了请求上下文应该怎么用,或者说,应该给谁用?

  • 给视图函数用啊,视图函数拿到上下文,解析请求对象,响应数据
  • 我们之前的HandlerFunc视图函数签名这时候需要改了,接收的参数不再是*http.Requesthttp.ResponseWriter,而直接是上下文对象
    type HandlerFunc func(ctx Context)
    

好了,视图函数拿到了请求上下文,那怎么用呢?你不可能既让我用上下文,对一些常用的操作还得我手写吧? 换个问法就是,上下文需要提供怎样的API?

  1. 统一的响应
    • 状态码设置
    • 响应体的设置
    • 响应数据格式的设置
  2. 提供多种响应方式
    • JSON格式
    • 纯文本格式
    • HTML格式
    • ...

上述的都是对于响应的封装,那对请求的封装呢?

  1. 获取查询参数【Query类型】
  2. 获取请求参数【Param类型】
    http://www.baidu.com/user/1?username=jason&password=jason123
    
    1. 其中,"1"表示请求参数
    
    2. "username=jason"和"password=jason123"表示查询参数
    
  3. 获取到请求体数据

思考

目前我们的框架设计得合理吗?

目前从市面上主流的Web框架上来看,一个框架需要的如下几个"组件"(暂时叫做组件)

  1. 引擎:盘活整个框架的核心
  2. 路由树:包括路由和视图函数的绑定
  3. 上下文
  4. AOP方案:面向切面编程。类中间件
  5. ...

根据目前我们实现的部分:引擎和路由树还是耦合在一起的

引擎只是组合整个框架,不做其他任何的特别操作。包括添加路由、匹配路由等等 它就有点像net/http包中的Handler接口一样,只作为一个中间桥梁,转发请求和响应结果

  1. router为engine提供注册路由API,它是核心API
  2. engine提供用户提供注册路由API,它是衍生API
  3. router提供查找路由功能,并执行命中的视图函数。就将ServeHTTP中的一部分逻辑抽离出来