{code: 0, msg: "", data:{}}
) , 想要在中间件去自动包装上它,也很难执行;最后就是——如果只依靠 http.Request/httpResponse
,你也难在中间件感知到其他参与者的处理状态,。相信我说的这些问题,使用过的同学应该都有所感触 , 而这些问题并非难以解决 , 它们中的大部分基本都是可以通过自行建立一套约定来得以缓解(比如将这些信息都通过 context 去获取),而 Droplet 也是诞生于我在过往团队中去克服这些问题的实践之中,是一个相对可靠的实现 。
工作原理带着上面提到的这些问题,我们来看看 Droplet 的工作原理是怎样的 , 如下图所示:

文章插图
如我所说的那样,Droplet 的核心在于
提供基于pipeline的请求/响应处理能力
,因此我们可以看见这个图中涉及的所有模块都是基于 pipleline,可以说 Droplet 的所有能力都是由其扩展而来 。这里我们先介绍下图中出现的几个中间件(Middleware,这是组成 pipepine 关键元素):- HttpInfoInjector: 注入 http 相关的一些信息,如 requestid, http.Request 等
- RespReshape: 根据 handler 的响应结果来进行一些调整 , 包括:发生错误时设置上默认的错误码、错误信息;如果缺少响应 wrapper 时包装上配置好的 wrapper
- HttpInput: 如果你设置了 API 的输入参数类型,那么该中间件会自动根据 Content-Type、 struct tag 来读取对应的参数值,同时自动使用 validator 来检测参数错误
- TrafficLog: 如名字所示,如果你配置了响应的 logger,那么该中间件会执行日志记录 。请注意该中间件工作在其他默认中间件的后面、你的handler之前,因此它统计的耗时是你业务函数的真正耗时,而不包含其他中间件的耗时时间,你可以考虑通过 网关 或 Mesh 来记录完整的接口耗时 。
TipsGetStart
- Middleware 处理请求和响应顺序是相反的——即第一个处理请求的中间件它会是最后一个处理响应的 。
- 框架工作在应用层的优势有两点:
- 与接入层框架解耦,保证绝项目代码可平滑 扩展/切换 其他接入层框架
- 能够获取到结构化的接口 输入参数 与 输出参数 你可以对其进行更具精细的切面操作
这里以首先获取对应 wrapper 的 submodule:Gin
为例,其他框架类似 。
go get github.com/shiningrush/droplet/wrapper/gin// if you want to ensure the droplet is latest, you can get dropletgo get github.com/shiningrush/droplet
然后程序代码如下:package mainimport ( "reflect" "github.com/gin-gonic/gin" "github.com/shiningrush/droplet/core" "github.com/shiningrush/droplet/wrapper" ginwrap "github.com/shiningrush/droplet/wrapper/gin")func main() { r := gin.Default()// 使用 wrapper 包装原始的 API r.POST("/json_input/:id", ginwrap.Wraps(JsonInputDo, wrapper.InputType(reflect.TypeOf(&JsonInput{})))) r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")}type JsonInput struct {// 从 path 读取, 并且为必须参数 IDstring`auto_read:"id,path" json:"id" validate:"required"`// 从 header 读取, 并且为必须参数 Userstring`auto_read:"user,header" json:"user" validate:"required"`// 从 json unmarshal 后的ips字段读取 IPs[]string `json:"ips"`// 从 json unmarshal 后的 count 字段读取 Count int`json:"count"`// 读取原始的 http body , 接收参数类型必须为 []byte or io.ReadCloser Body[]byte`auto_read:"@body"`}func JsonInputDo(ctx core.Context) (interface{}, error) { input := ctx.Input().(*JsonInput) return input, nil}
参数绑定如 Usage
一节中所展示的,我们可以通过 wrapper.InputType
选项来告诉 Droplet 是否期望自动化进行参数绑定,如果某些场景下你不需要从 Body 进行自动的参数绑定了,可以通过显式的选项来禁止它 , 如:r.POST("/json_input/:id", ginwrap.Wraps(JsonInputDo, wrapper.InputType(reflect.TypeOf(&JsonInput{}), wrapper.DisableUnmarshalBody())))
参数绑定的Tag格式如下:auto_read: ({key},{source}) or @body
其中值如下:- key: 用于到各个来源中匹配对应值
- source: 可选值有 query, header, path, body(缺省默认)
- @body: 特殊的取值 , 意味着获取原生的body作为字段值,此时你的字段类型应该为 []byte or io.ReadCloser
响应整形通常来说API都会在响应的最外层进行一层包装,比如 Droplet 自带的 wrapper 如下所示:
推荐阅读
- 《上传那些事儿之Nest与Koa》——文件格式怎么了!
- 四十七 SpringCloud微服务实战——搭建企业级开发框架:【移动开发】整合uni-app搭建移动端快速开发框架-添加Axios并实现登录功能
- 一篇文章带你了解NoSql数据库——Redis简单入门
- 微信小程序仿手机相册组件——简单版
- 个人如何开发手机游戏(如何自己开发一款手机游戏)
- 一篇文章带你了解服务器操作系统——Linux简单入门
- 一 意大利留学—米兰新美术学院 米兰新美术学院
- 二 【SSM】学习笔记——SpringMVC入门
- three.js 如何用webgl搭建一个3D库房,3D仓库,3D码头,3D集装箱可视化孪生系统——第十五课
- 四十六 SpringCloud微服务实战——搭建企业级开发框架:【移动开发】整合uni-app搭建移动端快速开发框架-环境搭建