gobox中的http请求处理框架

奇技指南

今天和大家介绍下我们自主开发的go语言轻型框架gobox,为什么叫gobox呢?因为我们设计让每一个单独的模块都作为一个box,那这些box的集合就称为gobox,再使用go的pkg管理机制引入到项目中。随着go官方推出了dep这个包管理工具,我们把gobox中的每一个box都单独拿出来作为一个项目管理,这就是现在的gobox。

今天这一期,主要来说下使用gobox中的http请求处理框架。


http请求处理架构图

640?wx_fmt=png


重要的对象

System

system用于实现go官方包中的http.Handler接口,它的ServeHTTP方法中实现了请求处理框架。

Router

定义和实现MVC的路由查找过程。

 
 
  1. type Router interface {Router interface {
  2.     MapRouteItems(cls ...controller.Controller)     // 自动将Controller对象中的Action方法映射到路由表MapRouteItems(cls ...controller.Controller)     // 自动将Controller对象中的Action方法映射到路由表
  3.     DefineRouteItem(pattern string, cl controller.Controller, actionName string)   // 手动添加路由规则,pattern为正则表达式DefineRouteItem(pattern string, cl controller.Controller, actionName string)   // 手动添加路由规则,pattern为正则表达式

  4.     FindRoute(path string) *Route    // 实现路由查找过程FindRoute(path string) *Route    // 实现路由查找过程
  5. }
SimpleRouter

Router接口的一个实现,自动映射规则为:

  1. controller名称规则为: ([A-Z][A-Za-z0-9_]*)Controller$,匹配内容转小写即为controllerName

  2. action名称规则为: ^([A-Z][A-Za-z0-9_]*)Action$,匹配内容转小写后过滤掉 beforeafter即为actionName

自动路由查找规则如下:

  1. 将request_uri视为: /controller/action

  2. controller不存在,则默认为 index,可以修改

  3. action不存在,则默认为 index,可以修改

自定义路由查找规则如下:

  1. 对request_uri做正则匹配

  2. 如果匹配后存在捕获,则捕获内容会作为action中除context外的参数,依次传入,都是string类型


ActionContext和Controller

ActionContext

处理每个请求会创建一个对应Controller的ActionContext对象:

 
 
  1. type ActionContext interface {ActionContext interface {
  2.     Request() *http.RequestRequest() *http.Request
  3.     ResponseWriter() http.ResponseWriterResponseWriter() http.ResponseWriter

  4.     ResponseBody() []byteResponseBody() []byte
  5.     SetResponseBody(body []byte)SetResponseBody(body []byte)

  6.     BeforeAction()BeforeAction()
  7.     AfterAction()AfterAction()
  8.     Destruct()Destruct()
  9. }
Controller

组织Action:

 
 
  1. type Controller interface {Controller interface {
  2.     NewActionContext(req *http.Request, respWriter http.ResponseWriter) ActionContextNewActionContext(req *http.Request, respWriter http.ResponseWriter) ActionContext
  3. }
gracehttp

这是一个支持平滑重启的httpserver,平滑重启过程如下:

640?wx_fmt=png


示例代码

最后附上一个最简单的使用示例:

 
 
  1. package main main

  2. import ( (
  3.     "github.com/goinbox/gohttp/controller""github.com/goinbox/gohttp/controller"
  4.     "github.com/goinbox/gohttp/gracehttp""github.com/goinbox/gohttp/gracehttp"
  5.     "github.com/goinbox/gohttp/router""github.com/goinbox/gohttp/router"
  6.     "github.com/goinbox/gohttp/system""github.com/goinbox/gohttp/system"

  7.     "net/http""net/http"
  8. )

  9. func main() {() {
  10.     dcl := new(DemoController):= new(DemoController)
  11.     r := router.NewSimpleRouter():= router.NewSimpleRouter()

  12.     r.DefineRouteItem("^/g/([0-9]+)$", dcl, "get").DefineRouteItem("^/g/([0-9]+)$", dcl, "get")
  13.     r.MapRouteItems(new(IndexController), dcl).MapRouteItems(new(IndexController), dcl)

  14.     sys := system.NewSystem(r):= system.NewSystem(r)

  15.     gracehttp.ListenAndServe(":8001", sys).ListenAndServe(":8001", sys)
  16. }

  17. type BaseActionContext struct {BaseActionContext struct {
  18.     Req        *http.RequestReq        *http.Request
  19.     RespWriter http.ResponseWriterRespWriter http.ResponseWriter
  20.     RespBody   []byteRespBody   []byte
  21. }

  22. func (this *BaseActionContext) Request() *http.Request {(this *BaseActionContext) Request() *http.Request {
  23.     return this.Reqreturn this.Req
  24. }

  25. func (this *BaseActionContext) ResponseWriter() http.ResponseWriter {(this *BaseActionContext) ResponseWriter() http.ResponseWriter {
  26.     return this.RespWriterreturn this.RespWriter
  27. }

  28. func (this *BaseActionContext) ResponseBody() []byte {(this *BaseActionContext) ResponseBody() []byte {
  29.     return this.RespBodyreturn this.RespBody
  30. }

  31. func (this *BaseActionContext) SetResponseBody(body []byte) {(this *BaseActionContext) SetResponseBody(body []byte) {
  32.     this.RespBody = bodythis.RespBody = body
  33. }

  34. func (this *BaseActionContext) BeforeAction() {(this *BaseActionContext) BeforeAction() {
  35.     this.RespBody = append(this.RespBody, []byte(" index before ")...)this.RespBody = append(this.RespBody, []byte(" index before ")...)
  36. }

  37. func (this *BaseActionContext) AfterAction() {(this *BaseActionContext) AfterAction() {
  38.     this.RespBody = append(this.RespBody, []byte(" index after ")...)this.RespBody = append(this.RespBody, []byte(" index after ")...)
  39. }

  40. func (this *BaseActionContext) Destruct() {(this *BaseActionContext) Destruct() {
  41.     println(" index destruct ")(" index destruct ")
  42. }

  43. type IndexController struct {IndexController struct {
  44. }

  45. func (this *IndexController) NewActionContext(req *http.Request, respWriter http.ResponseWriter) controller.ActionContext {(this *IndexController) NewActionContext(req *http.Request, respWriter http.ResponseWriter) controller.ActionContext {
  46.     return &BaseActionContext{return &BaseActionContext{
  47.         Req:        req,Req:        req,
  48.         RespWriter: respWriter,RespWriter: respWriter,
  49.     }}
  50. }

  51. func (this *IndexController) IndexAction(context *BaseActionContext) {(this *IndexController) IndexAction(context *BaseActionContext) {
  52.     context.RespBody = append(context.RespBody, []byte(" index action ")...).RespBody = append(context.RespBody, []byte(" index action ")...)
  53. }

  54. func (this *IndexController) RedirectAction(context *BaseActionContext) {(this *IndexController) RedirectAction(context *BaseActionContext) {
  55.     system.Redirect302("https://github.com/goinbox").Redirect302("https://github.com/goinbox")
  56. }

  57. type DemoActionContext struct {DemoActionContext struct {
  58.     *BaseActionContext*BaseActionContext
  59. }

  60. func (this *DemoActionContext) BeforeAction() {(this *DemoActionContext) BeforeAction() {
  61.     this.RespBody = append(this.RespBody, []byte(" demo before ")...)this.RespBody = append(this.RespBody, []byte(" demo before ")...)
  62. }

  63. func (this *DemoActionContext) AfterAction() {(this *DemoActionContext) AfterAction() {
  64.     this.RespBody = append(this.RespBody, []byte(" demo after ")...)this.RespBody = append(this.RespBody, []byte(" demo after ")...)
  65. }

  66. func (this *DemoActionContext) Destruct() {(this *DemoActionContext) Destruct() {
  67.     println(" demo destruct ")(" demo destruct ")
  68. }

  69. type DemoController struct {DemoController struct {
  70. }

  71. func (this *DemoController) NewActionContext(req *http.Request, respWriter http.ResponseWriter) controller.ActionContext {(this *DemoController) NewActionContext(req *http.Request, respWriter http.ResponseWriter) controller.ActionContext {
  72.     return &DemoActionContext{return &DemoActionContext{
  73.         &BaseActionContext{&BaseActionContext{
  74.             Req:        req,Req:        req,
  75.             RespWriter: respWriter,RespWriter: respWriter,
  76.         },},
  77.     }}
  78. }

  79. func (this *DemoController) DemoAction(context *DemoActionContext) {(this *DemoController) DemoAction(context *DemoActionContext) {
  80.     context.RespBody = append(context.RespBody, []byte(" demo action ")...).RespBody = append(context.RespBody, []byte(" demo action ")...)
  81. }

  82. func (this *DemoController) GetAction(context *DemoActionContext, id string) {(this *DemoController) GetAction(context *DemoActionContext, id string) {
  83.     context.RespBody = append(context.RespBody, []byte(" get action id = "+id)...).RespBody = append(context.RespBody, []byte(" get action id = "+id)...)
  84. }

运行这个代码,请求示例及输出如下:

 
 
  1. curl http://127.0.0.1:8001/://127.0.0.1:8001/
  2. index before  index action  index after 

  3. curl http://127.0.0.1:8001/index/redirect -I://127.0.0.1:8001/index/redirect -I
  4. HTTP/1.1 302 Found/1.1 302 Found
  5. Content-Type: text/html; charset=utf-8-Type: text/html; charset=utf-8
  6. Location: https://github.com/goinbox: https://github.com/goinbox
  7. Date: Fri, 24 Aug 2018 11:57:11 GMT: Fri, 24 Aug 2018 11:57:11 GMT
  8. Content-Length: 14-Length: 14

  9. curl http://127.0.0.1:8001/demo/demo://127.0.0.1:8001/demo/demo
  10. demo before  demo action  demo after

  11. curl http://127.0.0.1:8001/g/123://127.0.0.1:8001/g/123
  12. demo before  get action id = 123 demo after get action id = 123 demo after 

所有destruct输出为:

 
 
  1. index destruct 
  2. index destruct 
  3. index destruct 
  4. demo destruct 
  5. demo destruc

欢迎大家使用,使用中有遇到问题随时反馈,我们会尽快响应,谢谢!


推荐阅读


界世的你当不

只做你的肩膀

640?wx_fmt=jpeg 640?wx_fmt=jpeg

 360官方技术公众号 

技术干货|一手资讯|精彩活动

空·


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include <stdio.h> int main(){ void gobox(int a,int b); void getbox(); void findbanana(int a,int b); void getbanana(); int monkey,banana,box; printf("请依次输入猴子,香蕉,箱子 的位置\n"); printf("猴子的位置:"); scanf("%d",&monkey); printf("香蕉的位置:"); scanf("%d",&banana); printf("箱子的位置:"); scanf("%d",&box); printf("-----------------------------------\n"); if(monkey!=box){ printf("猴子够不到香蕉,要先去搬箱子:"); gobox(monkey,box); getbox(); if(box!=banana){ printf("猴子需要搬着箱子去找到香蕉:"); findbanana(banana,box); getbanana(); }else{ printf("香蕉就在箱子的上面\n"); getbanana(); } }else{ printf("箱子就在猴子旁边,猴子拿到了箱子"); getbox(); if(box!=banana){ printf("猴子需要搬着箱子去找到香蕉:"); findbanana(banana,box); getbanana(); }else{ printf("香蕉就在箱子的上面\n"); getbanana(); } } } void gobox(int a,int b){ int flag; flag = b - a; if(flag>0){ printf("Run(monkey,box)\n"); printf("猴子需要向右移动%d步拿到箱子\n",flag); }else{ printf("Run(monkey,box)\n"); printf("猴子需要向左移动%d步拿到箱子\n",flag); } } void findbanana(int a,int b){ int flag; flag=b-a; if(flag>0){ printf("Run(monkey,banana)\n"); printf("猴子需要向左搬着箱子移动%d步找到香蕉\n",flag); }else{ printf("Run(monkey,banana)\n"); printf("猴子需要向右搬着箱子移动%d步找到香蕉\n",flag); } } void getbox(){ printf("猴子拿到了箱子:"); printf("Getbox(monkey,box)\n"); } void getbanana(){ printf("猴子踩在箱子上拿到了香蕉:"); printf("Getbanana(monkey,banana)\n"); }请输出主要数据定义和主要功能模块设计
05-25

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值