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

重要的对象
System
system用于实现go官方包中的http.Handler接口,它的ServeHTTP方法中实现了请求处理框架。
Router
定义和实现MVC的路由查找过程。
type Router interface {Router interface {MapRouteItems(cls ...controller.Controller) // 自动将Controller对象中的Action方法映射到路由表MapRouteItems(cls ...controller.Controller) // 自动将Controller对象中的Action方法映射到路由表DefineRouteItem(pattern string, cl controller.Controller, actionName string) // 手动添加路由规则,pattern为正则表达式DefineRouteItem(pattern string, cl controller.Controller, actionName string) // 手动添加路由规则,pattern为正则表达式FindRoute(path string) *Route // 实现路由查找过程FindRoute(path string) *Route // 实现路由查找过程}
SimpleRouter
Router接口的一个实现,自动映射规则为:
controller名称规则为:
([A-Z][A-Za-z0-9_]*)Controller$,匹配内容转小写即为controllerNameaction名称规则为:
^([A-Z][A-Za-z0-9_]*)Action$,匹配内容转小写后过滤掉before和after即为actionName
自动路由查找规则如下:
将request_uri视为:
/controller/actioncontroller不存在,则默认为
index,可以修改action不存在,则默认为
index,可以修改
自定义路由查找规则如下:
对request_uri做正则匹配
如果匹配后存在捕获,则捕获内容会作为action中除context外的参数,依次传入,都是string类型
ActionContext和Controller
ActionContext
处理每个请求会创建一个对应Controller的ActionContext对象:
type ActionContext interface {ActionContext interface {Request() *http.RequestRequest() *http.RequestResponseWriter() http.ResponseWriterResponseWriter() http.ResponseWriterResponseBody() []byteResponseBody() []byteSetResponseBody(body []byte)SetResponseBody(body []byte)BeforeAction()BeforeAction()AfterAction()AfterAction()Destruct()Destruct()}
Controller
组织Action:
type Controller interface {Controller interface {NewActionContext(req *http.Request, respWriter http.ResponseWriter) ActionContextNewActionContext(req *http.Request, respWriter http.ResponseWriter) ActionContext}
gracehttp
这是一个支持平滑重启的httpserver,平滑重启过程如下:

示例代码
最后附上一个最简单的使用示例:
package main mainimport ( ("github.com/goinbox/gohttp/controller""github.com/goinbox/gohttp/controller""github.com/goinbox/gohttp/gracehttp""github.com/goinbox/gohttp/gracehttp""github.com/goinbox/gohttp/router""github.com/goinbox/gohttp/router""github.com/goinbox/gohttp/system""github.com/goinbox/gohttp/system""net/http""net/http")func main() {() {dcl := new(DemoController):= new(DemoController)r := router.NewSimpleRouter():= router.NewSimpleRouter()r.DefineRouteItem("^/g/([0-9]+)$", dcl, "get").DefineRouteItem("^/g/([0-9]+)$", dcl, "get")r.MapRouteItems(new(IndexController), dcl).MapRouteItems(new(IndexController), dcl)sys := system.NewSystem(r):= system.NewSystem(r)gracehttp.ListenAndServe(":8001", sys).ListenAndServe(":8001", sys)}type BaseActionContext struct {BaseActionContext struct {Req *http.RequestReq *http.RequestRespWriter http.ResponseWriterRespWriter http.ResponseWriterRespBody []byteRespBody []byte}func (this *BaseActionContext) Request() *http.Request {(this *BaseActionContext) Request() *http.Request {return this.Reqreturn this.Req}func (this *BaseActionContext) ResponseWriter() http.ResponseWriter {(this *BaseActionContext) ResponseWriter() http.ResponseWriter {return this.RespWriterreturn this.RespWriter}func (this *BaseActionContext) ResponseBody() []byte {(this *BaseActionContext) ResponseBody() []byte {return this.RespBodyreturn this.RespBody}func (this *BaseActionContext) SetResponseBody(body []byte) {(this *BaseActionContext) SetResponseBody(body []byte) {this.RespBody = bodythis.RespBody = body}func (this *BaseActionContext) BeforeAction() {(this *BaseActionContext) BeforeAction() {this.RespBody = append(this.RespBody, []byte(" index before ")...)this.RespBody = append(this.RespBody, []byte(" index before ")...)}func (this *BaseActionContext) AfterAction() {(this *BaseActionContext) AfterAction() {this.RespBody = append(this.RespBody, []byte(" index after ")...)this.RespBody = append(this.RespBody, []byte(" index after ")...)}func (this *BaseActionContext) Destruct() {(this *BaseActionContext) Destruct() {println(" index destruct ")(" index destruct ")}type IndexController struct {IndexController struct {}func (this *IndexController) NewActionContext(req *http.Request, respWriter http.ResponseWriter) controller.ActionContext {(this *IndexController) NewActionContext(req *http.Request, respWriter http.ResponseWriter) controller.ActionContext {return &BaseActionContext{return &BaseActionContext{Req: req,Req: req,RespWriter: respWriter,RespWriter: respWriter,}}}func (this *IndexController) IndexAction(context *BaseActionContext) {(this *IndexController) IndexAction(context *BaseActionContext) {context.RespBody = append(context.RespBody, []byte(" index action ")...).RespBody = append(context.RespBody, []byte(" index action ")...)}func (this *IndexController) RedirectAction(context *BaseActionContext) {(this *IndexController) RedirectAction(context *BaseActionContext) {system.Redirect302("https://github.com/goinbox").Redirect302("https://github.com/goinbox")}type DemoActionContext struct {DemoActionContext struct {*BaseActionContext*BaseActionContext}func (this *DemoActionContext) BeforeAction() {(this *DemoActionContext) BeforeAction() {this.RespBody = append(this.RespBody, []byte(" demo before ")...)this.RespBody = append(this.RespBody, []byte(" demo before ")...)}func (this *DemoActionContext) AfterAction() {(this *DemoActionContext) AfterAction() {this.RespBody = append(this.RespBody, []byte(" demo after ")...)this.RespBody = append(this.RespBody, []byte(" demo after ")...)}func (this *DemoActionContext) Destruct() {(this *DemoActionContext) Destruct() {println(" demo destruct ")(" demo destruct ")}type DemoController struct {DemoController struct {}func (this *DemoController) NewActionContext(req *http.Request, respWriter http.ResponseWriter) controller.ActionContext {(this *DemoController) NewActionContext(req *http.Request, respWriter http.ResponseWriter) controller.ActionContext {return &DemoActionContext{return &DemoActionContext{&BaseActionContext{&BaseActionContext{Req: req,Req: req,RespWriter: respWriter,RespWriter: respWriter,},},}}}func (this *DemoController) DemoAction(context *DemoActionContext) {(this *DemoController) DemoAction(context *DemoActionContext) {context.RespBody = append(context.RespBody, []byte(" demo action ")...).RespBody = append(context.RespBody, []byte(" demo action ")...)}func (this *DemoController) GetAction(context *DemoActionContext, id string) {(this *DemoController) GetAction(context *DemoActionContext, id string) {context.RespBody = append(context.RespBody, []byte(" get action id = "+id)...).RespBody = append(context.RespBody, []byte(" get action id = "+id)...)}
运行这个代码,请求示例及输出如下:
curl http://127.0.0.1:8001/://127.0.0.1:8001/index before index action index aftercurl http://127.0.0.1:8001/index/redirect -I://127.0.0.1:8001/index/redirect -IHTTP/1.1 302 Found/1.1 302 FoundContent-Type: text/html; charset=utf-8-Type: text/html; charset=utf-8Location: https://github.com/goinbox: https://github.com/goinboxDate: Fri, 24 Aug 2018 11:57:11 GMT: Fri, 24 Aug 2018 11:57:11 GMTContent-Length: 14-Length: 14curl http://127.0.0.1:8001/demo/demo://127.0.0.1:8001/demo/demodemo before demo action demo aftercurl http://127.0.0.1:8001/g/123://127.0.0.1:8001/g/123demo before get action id = 123 demo after get action id = 123 demo after
所有destruct输出为:
index destructindex destructindex destructdemo destructdemo destruc
欢迎大家使用,使用中有遇到问题随时反馈,我们会尽快响应,谢谢!
推荐阅读
界世的你当不
只做你的肩膀
无
360官方技术公众号
技术干货|一手资讯|精彩活动
空·

8517

被折叠的 条评论
为什么被折叠?



