Goui
Go-web如何一步步整合swagger-ui我们可以官方提供的方式:https://github.com/go-swagger/go-swagger , 主要方式是:1、写我们的go程序,2、让swagger工具扫描我们的go文件,3、生成swagger注释。
我们先说存在的问题:1、注释本地生成,会因为swagger版本不一致出现问题,出现各种git冲突,需要采用打包编译时去执行生成。2、违背了编程的方式。 3、为什么Java的swagger那么火,是因为和spring-boot完美整合,那么Spring解决的其实就是ioc的控制,所以go的web也不需要程序去控制,路由,输入,输出,所以我们需要这么做。 前期准备1、需要实现Spring-Boot的 controoler接口的方式
大致需求:1、拿到路由,2、拿到请求、响应(这个是go所有web框架做不到的,所以需要转变思想) @RestController public class UserController { @Autowired private UserRepository repository; @PostMapping("/save") public User echo(UserInfoDto info) { return repository.save(User.builder().id(info.getId()).userName(info.getName()).build()); } }2、转变思想
这个反射调用的框架,我写了一个,希望大家多多提交bug,因为反射本身缺陷很多:https://github.com/Anthony-Dong/gorpc var ( userService = service.NewUserService() ) func userRoute(e *engines.Engine) { g := e.Group("/report") g.POST("benchmark", http.NewHandlerFunc(userService.BenchMark)) } // 定义 context.Context(必不可少),类似于Java的ThreadLocal // request *dto.BenchmarkRequest 请求 // *dto.BenchmarkResponse 详情 // error 由于go本身没有throw,所以需要显示的申明 // 后期考虑加入web模块,但是目前主流web框架都是依赖于ctx向下传递,所以go和Java这点不一样(目前不考虑,可以考虑使用gin的context),虽然Springmvc中也可以接受http-request,http-response 但是由于它的bind,用户都不care了(这就是申明式编程的好处) type UserService interface { BenchMark(ctx context.Context, request *dto.BenchmarkRequest) (*dto.BenchmarkResponse, error) }
实现了这个,那么我们就开始吧,因为这些要求的,我们都可以拿到。 3、定义强路由
1、因为go本身并没有方法级别的注解,如果我们可以在每个interface上申明接口,在每个方法上申明路由 // path=/user_service type UserService interface { // path=/benchmark method=get BenchMark(ctx context.Context, request *dto.BenchmarkRequest) (*dto.BenchmarkResponse, cerror.Cerror) }
如果这样子,那么对于go的开发者特别不友好
2、所有采用func注册的方式
可以在接口后面指定get/其他 g.POST("benchmark", http.NewHandlerFunc(userService.BenchMark),op.Get())
目前采用的这种方式:1、可以显示的声明,符合go开发者的习惯,2、可以不用扫描go文件(spring-boot采用的这种方式) 整合swagger客户端找到swagger的web端资源包,然后将其都暴露出去,接下来核心就是 /swagger.json 了。
资源在我的这个项目的swagger里面 https://github.com/Anthony-Dong/gorpc ,后期会考虑静态资源使用api调用的方式(转发的方式),目前是借助工具写在了go文件里:https://github.com/a-urth/go-bindata ,这个工具很nice,可以讲文件写入到go文件里,以二进制的形式,我们知道go是不可以打包成jar包的,只有二进制文件,静态资源是一个很难受的事情,所以需要这么做。 const ( js = "js" css = "css" html = "html" byte = "byte" json = "json" ) func addSwagger(path string, _type string) func(writer http.ResponseWriter, request *http.Request) { return func(writer http.ResponseWriter, request *http.Request) { body, _ := swagger.Asset(path) switch _type { case js: writer.Header().Set("content-type", "application/javascript") case css: writer.Header().Set("content-type", "text/css") case json: writer.Header().Set("content-type", "application/json") } if _type == byte { fmt.Fprint(writer, body) return } fmt.Fprint(writer, string(body)) } } func addSwaggerRouter(path string, _type string) { http.HandleFunc("/"+path, addSwagger(path, _type)) } func main() { // swagger内置服务端需要的东西 addSwaggerRouter("swagger-ui/absolute-path.js", js) addSwaggerRouter("swagger-ui/favicon-16x16.png", byte) addSwaggerRouter("swagger-ui/favicon-32x32.png", byte) addSwaggerRouter("swagger-ui/index.html", html) addSwaggerRouter("swagger-ui/index.js", js) addSwaggerRouter("swagger-ui/oauth2-redirect.html", html) addSwaggerRouter("swagger-ui/package.json", json) addSwaggerRouter("swagger-ui/swagger-ui-bundle.js", js) addSwaggerRouter("swagger-ui/swagger-ui-bundle.js.map", html) addSwaggerRouter("swagger-ui/swagger-ui-standalone-preset.js", js) addSwaggerRouter("swagger-ui/swagger-ui-standalone-preset.js.map", html) addSwaggerRouter("swagger-ui/swagger-ui.css", css) addSwaggerRouter("swagger-ui/swagger-ui.css.map", html) addSwaggerRouter("swagger-ui/swagger-ui.js", js) addSwaggerRouter("swagger-ui/swagger-ui.js.map", html) http.HandleFunc("/swagger.json", func(writer http.ResponseWriter, request *http.Request) { writer.Header().Set("content-type", "application/json") fmt.Fprintf(writer, doc) }) http.ListenAndServe(":8888", nil) }swagger-json
这个文件来自于 faygo,swagger核心是一个api接口,类似于下面这个样子 { "swagger": "2.0", "info": { "description": "Spring Swaager2 REST API", "version": "V1", "title": "REST API", "contact": { "name": "anthony", "url": "https://github.com/Anthony-Dong", "email": "574986060@qq.com" }, "license": { "name": "The Apache License", "url": "https://opensource.org/licenses/MIT" } }, "host": "localhost:8888", "basePath": "/", "tags": [ { "name": "user-controller", "description": "User Controller" } ], "paths": { "/find/{id}": { "get": { "tags": [ "user-controller" ], "summary": "find", "operationId": "findUsingGET", "produces": [ "*/*" ], "parameters": [ { "name": "id", "in": "path", "description": "id", "required": true, "type": "integer", "format": "int64" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/User" } } }, "deprecated": false } }, "/save/{name}": { "get": { "tags": [ "user-controller" ], "summary": "echo", "operationId": "echoUsingGET", "produces": [ "*/*" ], "parameters": [ { "name": "name", "in": "path", "description": "name", "required": true, "type": "string" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/User" } } }, "deprecated": false } } }, "definitions": { "User": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "userName": { "type": "string" } }, "title": "User" } } }一步步写doc
下面是swagger-doc的大致结构,我们必须将我们的api注入进去 doc := swagger.Swagger{ Version: swagger.Version, Info: &swagger.Info{ Title: "REST API", Contact: &swagger.Contact{ Email: "fanhaodong516@gmail.com", }, License: &swagger.License{ Name: "The Apache License", Url: "https://opensource.org/licenses/MIT", }, }, Host: "localhost:8888", BasePath: "/", Tags: []*swagger.Tag{}, //tag Paths: map[string]map[string]*swagger.Opera{},// 所有的api路由 Definitions: map[string]*swagger.Definition{},// 定义dto对象 }tag 是什么
user-controller 就是一个tag ,对于go来说一般是group可以定义为一个 controller
// Tag object Tag struct { Name string `json:"name"` // 一个标签:user-controller Description string `json:"description"` // 一个des:user-controller }
同时所有的 path 都可以指定多个tag Opera struct { Tags []string `json:"tags"` // 这里是tag Summary string `json:"summary"` Description string `json:"description"` OperationId string `json:"operationId"` Consumes []string `json:"consumes,omitempty"` Produces []string `json:"produces,omitempty"` Parameters []*Parameter `json:"parameters,omitempty"` Responses map[string]*Resp `json:"responses"` // {"httpcode":resp} Security []map[string][]string `json:"security,omitempty"` }认识path
这就是一个path Paths map[string]map[string]*Opera `json:"paths,omitempty"`
结构是个两级map "/save": { "post": { "tags": [ "user-controller" ], "summary": "echo", "operationId": "echoUsingPOST", "consumes": [ //请求类型 "application/json" ], "produces": [ // 响应类型 "*/*" ], "parameters": [ // 核心关注的点 ,如果多级别 { "name": "id", // 字段描述 "in": "query", // 查询 "required": false, // 是否强需求,可以借助于binding,也就是go的Validator(https://github.com/go-playground/validator) "type": "integer", // 类型 "format": "int64" // 真实类型(go类型) }, { "name": "name", "in": "query", "required": false, "type": "string" }, { "name": "user.id", "in": "query", "required": false, "type": "integer", "format": "int64" }, { "name": "user.userName", "in": "query", "required": false, "type": "string" } ], "responses": { "200": {// 状态吗 "description": "OK", // 响应描述 "schema": { "$ref": "#/definitions/User" // 指定路由:(nice,所以我们的dto全部放到modle里) } } }, "deprecated": false } },总结
通过以上,我们可以get到,确实是不是特别难,是有一定规律的,那么接下来,我们就可以开始设计框架了。
新闻之热点大事件今日头条新闻之热点大事件马斯克发起关于是否应出售10特斯拉股票的投票特斯拉CEO埃隆马斯克在社交媒体上发起一项投票意见征询。马斯克表示,最近有很多人认为未实现收益是一种避税手段,所
法国撑不住了!将2340亿订单交给华为,美国无法阻止只能干瞪眼?贸易摩擦后,欧洲各国纷纷终止与华为合作,法国甚至曾公开表示,在2028年前拆除华为的一切5G设备,但是近期,法国态度却180度大转弯。不但主动缓和关系,而且将2340亿大单交给华为
Flink操练(六十)之数据写入到redis关键代码publicstaticclassMyRedisMapperimplementsRedisMapperTuple2String,Integer获取keyOverridepu
集结112人搞研发,国产芯片迎来黑马,中兴是第一大客户文BU审核子扬校对知秋上交所官网消息,10月12日德科立招股说明书(申报稿)被受理。这也就是说,德科立离上市又进了一步,这个蛰伏二十余载的光电子黑马,终于即将迎来大放异彩的时刻。2
中小企业能办大事,14家专精特新小巨人企业荣获国家科学技术奖来源工业和信息化部网站近日,2020年度国家科学技术奖获奖名单公布,264个项目10名科技专家和1个国际组织入选。经初步统计,工业和信息化部培育的武大吉奥信息技术有限公司甘肃蓝科石
洗衣机你们知道里面有多脏吗?您好,如果不拆出来的话其实不知道有多脏,不过现在市面上那么多清洁用品,如果洗衣机用久了那就用清洁的一些用品洗一洗去污,如果实在接受不了,那就只能换一个了,毕竟洗衣机也只是个工具。第
为什么用两个手机的人越来越多?一个手机工作,一个手机生活娱乐,两不误啊。越来越多的人用两个手机。个人分析有两方面原因一方面是工作业务繁忙,另一面是便于刷头条赚取流量。这主要是在于现在手机的电消耗的太快了,充电器
药店里可以买助听器吗?助听器不能随便购买。助听器要到专业的验配中心去验配,每个人的听力损失不同,需要进行专业检测之后再进行选配,这样配得的助听器会更适合自己,能起到保护残余听力和帮助聆听的效果,希望能帮
什么样的耳聋需要戴助听器呢?对于耳聋患者而言,只要你感到自己的听力出现了问题,同时已经对生活,对讲话沟通产生了一定的影响的时候,如果你是这类耳聋患者的,那么你就需要及时佩戴助听器了。我们佩戴助听器正确的定义是
来自未来的智能生活Aqara妙控套装体验不知从什么时候开始,智能家居这个词开始在各大数码品牌和装修公司疯狂传播,但功能确良莠不齐,并且很难兼容,在以前,很难有一个品牌能够把所有的智能设备完美的连接到一起,虽然我很想让我的
为何感觉做网页的不多但是前端却比安卓ios的需求大?因为现在网页开发人员已经不再单纯的只开发网页在Web2。0时代前端开发人员都是往大前端方向发展HTMLCSSJS只是基本功还得需要会VueReactAngular三大框架小程序和W