当前位置:首页 > 技术分析 > 正文内容

Go-web如何一步步整合swagger-ui_go web界面

ruisui882个月前 (02-22)技术分析11

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到,确实是不是特别难,是有一定规律的,那么接下来,我们就可以开始设计框架了。

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/2160.html

标签: go swagger
分享给朋友:

“Go-web如何一步步整合swagger-ui_go web界面” 的相关文章

厅监控结算中心加强高速公路联网收费系统运行管理

厅监控结算中心加强高速公路联网收费系统运行管理,一是严格PSAM卡管理要求,加强跟踪各营运公司PSAM卡使用情况,切实做到PSAM卡专人保管,定期核查,做好联网收费系统基础安全工作。二是督促各营运公司加强3G备份链路管理,保障数据应急通道的畅通,确保车道数据正常传输。三是落实标识站建设工作,督促各营...

带你五步学会Vue SSR

作者:liuxuan 前端名狮转发链接:https://mp.weixin.qq.com/s/6K6GUHcLwLG4mzfaYtVMBQ前言SSR大家肯定都不陌生,通过服务端渲染,可以优化SEO抓取,提升首页加载速度等,我在学习SSR的时候,看过很多文章,有些对我有很大的启发作用,有些就只是照搬官...

继Yuzu后,任天堂要求移除多个Switch模拟器项目

IT之家 7 月 11 日消息,任天堂美国分公司 (Nintendo of America) 已要求移除多个用于模拟 Nintendo Switch 游戏的开源模拟器项目,其中包括 Suyu、Nzu、Uzuy、Torzu、Sudachi 和 Yuzu-vanced 等。这些模拟器均被指控包含绕过任天...

VIM配置整理

一、基本配色set number set showcmd set incsearch set expandtab set showcmd set history=400 set autoread set ffs=unix,mac,dos set hlsearch set shiftwidth=2 s...

15款测试html5响应式的在线工具

手机、平板灯手持设备的增多,网站要顺应变化,就必须要做响应式开发,响应式网站最大的特点在于可以在不同设备下呈现不同的布局,是基于html5+css3技术,目前越来越多的网站开始采用了响应式设计,而下面15款工具可以方便测试你的html5响应式效果。Responsinatorhttp://www.re...

USB电池充电基础:应急指南

USB为便携设备供电与其串行通信功能一样,已经成为一种标准应用。如今,USB 供电已经扩展到电池充电、交流适配器及其它供电形式的应用。应用的普及带来的一个显著效果是便携设备的充电和供电可以互换插头和适配器。因此,相对于过去每种装置都采用专用适配器的架构相比,目前的解决方案允许采用多种电源进行充电。毋...