技海泛舟(个人技术研究)

  • 首页
  • 日积月累
  • 学习计划
  • 随想
  • project
  • 关于
技海泛舟
一个技术宅的博客
  1. 首页
  2. 日积月累
  3. go
  4. 正文

创建api的逻辑

2024年11月20日 457点热度

搭建项目

go:generate
//go:generate go env -w GO111MODULE=on
//go:generate go env -w GOPROXY=https://goproxy.cn,direct
//go:generate go mod tidy
//go:generate go mod demo

入口主程序

在入口主程序调用 读取参数、解析jwt、日志库、链接数据库、初始化定时器、初始化路由

// server\main.go
package main
func main() {
    println("主程序入口")
    global.VGA_VP = core.Viper() // 初始化Viper
    initialize.OtherInit()       //解析JWT过期时间和缓冲时间,并在解析失败时触发panic。 2. 使用JWT过期时间设置全局BlackCache的默认过期时间。 3. 尝试打开go.mod文件,若成功且模块名为空,则从go.mod中读取并设置模块名。
    global.VGA_LOG = core.Zap()  // 初始化zap日志库
    zap.ReplaceGlobals(global.VGA_LOG)
    global.VGA_DB = initialize.Gorm() // gorm连接数据库
    initialize.Timer()                // 初始化定时器
    initialize.DBList()
    if global.VGA_DB != nil {
        initialize.RegisterTables() // 初始化表
        // 程序结束前关闭数据库链接
        db, _ := global.VGA_DB.DB()
        defer db.Close()
    }
    core.RunWindowsServer()
}

读取配置文件

func Viper(path ...string) *viper.Viper {
 v := viper.New()
    v.SetConfigFile("config")
    v.SetConfigType("yaml")
    err := v.ReadInConfig()
    if err != nil {
        panic(fmt.Errorf("Fatal error config file: %s \n", err))
    }
    v.WatchConfig()

    v.OnConfigChange(func(e fsnotify.Event) {
        fmt.Println("config file changed:", e.Name)
        if err = v.Unmarshal(&global.VGA_CONFIG); err != nil {
            fmt.Println(err)
        }
    })
    if err = v.Unmarshal(&global.VGA_CONFIG); err != nil {
        panic(err)
    }

    // root 适配性 根据root位置去找到对应迁移位置,保证root路径有效
    global.VGA_CONFIG.AutoCode.Root, _ = filepath.Abs("..")
    return v

初始化日志

func Zap() (logger *zap.Logger) {
    if ok, _ := utils.PathExists(global.VGA_CONFIG.Zap.Director); !ok { // 判断是否有Director文件夹
        fmt.Printf("create %v directory\n", global.VGA_CONFIG.Zap.Director)
        _ = os.Mkdir(global.VGA_CONFIG.Zap.Director, os.ModePerm)
    }
    levels := global.VGA_CONFIG.Zap.Levels()
    length := len(levels)
    cores := make([]zapcore.Core, 0, length)
    for i := 0; i < length; i++ {
        core := internal.NewZapCore(levels[i])
        cores = append(cores, core)
    }
    logger = zap.New(zapcore.NewTee(cores...))
    if global.VGA_CONFIG.Zap.ShowLine {
        logger = logger.WithOptions(zap.AddCaller())
    }
    return logger
}

创建api

1.新建数据模型,server/model/模块名称/模块数据表.

server\model\example\userinfo.go
package example
type Userinfo struct {
  Name string `uri:"name" form:"name" json:"name"`
  Pwd  string `uri:"pwd" form:"pwd" json:"pwd"`
}
type UserinfoResponse struct {
  Userinfo example.Userinfo `json:"userinfo"`
  Token    string           `json:"token"`
}

2.gorm初始化新增数据表,server\initialize\gorm.go 中 func RegisterTables增加注册数据模型语句

// server\initialize\gorm.go
package initialize
func RegisterTables() {
    db := global.VGA_DB
    err := db.AutoMigrate(
    ...
    example.Userinfo{},
    ...
    )
    if err != nil {
        global.VGA_LOG.Error("register table failed", zap.Error(err))
        os.Exit(0)
    }
        global.VGA_LOG.Info("register table success")
}

3.增加路由组和方法 server/router/模块/模块数据表.go,定义POST,GET等的处理函数

// server\router\example\exa_customer.go
package example
type ExaRouter struct {
}

func (e *ExaRouter) InitExaAPiRouter(Router *gin.RouterGroup) {
  exaApiRouter := Router.Group("exaApi").Use(middleware.ExaMiddleware())
  exaApiRouterWithoutRecord := Router.Group("exaApi")
  exaApi := v1.ApiGroupApp.ExaApiGroup  // 也可放在enter中统一定义
  {
    exaApiRouter.POST("login", exaApi.Login)        
    exaApiRouter.POST("loginJson", exaApi.LoginJson) 
  }
  {
    exaApiRouterWithoutRecord.GET("getUserInfo", exaApi.GetUserInfo)                  
    exaApiRouterWithoutRecord.GET("getUserInfoPath/:name/:pwd", exaApi.GetUserInfoPath) 
  }
}

server\router\example\enter.go中统一增加路由组,初始化路由信息,以及调用的exaApiapi方法

// server\router\example\enter.g
package example
type RouterGroup struct {
    ...
    ExaRouter
}

var (
...
exaApi = v1.ApiGroupApp.ExaApiGroup  //也可放在具体路由模块数据表中直接定义
)

4.如果多级分组,还可以在server/router/enter.go增加路由组

package router
var RouterGroupApp = new(RouterGroup)
type RouterGroup struct {
    System  system.RouterGroup
    Example example.RouterGroup // 这里可以新增路由组
}

5.server/initialize/router.go引入并注册新加入的路由组

// server\initialize\router.go
package initialize
func Routers() *gin.Engine {
    Router := gin.New()
    Router.Use(gin.Recovery())
    if gin.Mode() == gin.DebugMode {
        Router.Use(gin.Logger())
    }
    exampleRouter := router.RouterGroupApp.Example
        PublicGroup := Router.Group(global.VGA_CONFIG.System.RouterPrefix)
    PrivateGroup := Router.Group(global.VGA_CONFIG.System.RouterPrefix)

    PrivateGroup.Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
        {
        // 健康监测
        PublicGroup.GET("/health", func(c *gin.Context) {
            c.JSON(http.StatusOK, "ok")
        })
    }
    exampleRouter.InitExaAPiRouter(PrivateGroup)              // 用户信息路由

    global.VGA_ROUTERS = Router.Routes()

    global.VGA_LOG.Info("router register success")
    return Router

6.api/v1/模块/模块数据表.go实现上述函数中的api网络交互层具体内容,并引用service进行数据库操作

// server\api\v1\example\enter.go
// enter为api功能块的入口块,即api的入口文件
type ApiGroup struct {
  ExaApi
}
var (
  exaService = service.ServiceGroupApp.ExaServiceGroup.ExaApiService
)
// server\api\v1\example\exa_api.go
type ExaApi struct {
}

// Login /*
// http://127.0.0.1:8888/exaApi/login
// application/x-www-form-urlencoded或者form-data
func (e *ExaApi) Login(c *gin.Context) {
  var userinfo example.Userinfo
  err := c.ShouldBind(&userinfo)
    user, err = exaService.Login(&userinfo)
  if err != nil {
    response.FailWithMessage(err.Error(), c)
    return
  }
  response.OkWithMessage(exaService.Login(userinfo), c)
}

// http://127.0.0.1:8888/exaApi/getUserInfo?name=zhangsan&pwd=6666
func (e *ExaApi) GetUserInfo(c *gin.Context) {
  var userinfo example.Userinfo
  err := c.ShouldBind(&userinfo)
  if err != nil {
    response.FailWithMessage(err.Error(), c)
    return
  }
  response.OkWithMessage(exaService.GetUserInfo(userinfo), c)
}

// http://127.0.0.1:8888/exaApi/login
//
//  raw {
//     "name":"zhangsan",
//     "pwd":"23333"
//  }
func (e *ExaApi) LoginJson(c *gin.Context) {
  var userinfo example.Userinfo
  err := c.ShouldBindJSON(&userinfo)

  if err != nil {
    response.FailWithMessage(err.Error(), c)
    return
  }
  response.OkWithMessage(exaService.Login(userinfo), c)
}

// http://127.0.0.1:8888/exaApi/getUserInfoPath/zhangsan/555
func (e *ExaApi) GetUserInfoPath(c *gin.Context) {
  var userinfo example.Userinfo
  err := c.ShouldBindUri(&userinfo)
  if err != nil {
    response.FailWithMessage(err.Error(), c)
    return
  }
  response.OkWithMessage(exaService.GetUserInfo(userinfo), c)
}

7.service/模块/模块数据表.go,service层处理数据表中具体CURD操作
入口模块

// server\service\system\enter.go
package system

type ServiceGroup struct {
exaService
}
var ExaServiceApp = new(exaService)

具体server层

 // server\service\example\exa_user.go
 package example
type ExaApiService struct {
}

var ExaApiServiceApp = new(ExaApiService)

func (exaService *ExaService) Login(u *example.Userinfo) (userInter *system.SysUser, err error) {
    if nil == global.VGA_DB {
        return nil, fmt.Errorf("db not init")
    }

    var user system.SysUser
    err = global.VGA_DB.Where("username = ?", u.Username).Preload("Authorities").Preload("Authority").First(&user).Error
    if err == nil {
        if ok := utils.BcryptCheck(u.Password, user.Password); !ok {
            return nil, errors.New("密码错误")
        }
        MenuServiceApp.UserAuthorityDefaultRouter(&user)
    }
    return &user, err
}

func (exaApi *ExaApiService) GetUserInfo(u example.Userinfo) (user example.Userinfo, err error) {
var reqUser system.SysUser
    err = global.VGA_DB.Preload("Authorities").Preload("Authority").First(&reqUser, "uuid = ?", uuid).Error
    if err != nil {
        return reqUser, err
    }
    MenuServiceApp.UserAuthorityDefaultRouter(&reqUser)
    return reqUser, err
}

使用go-swagger配置文档

url参数类型 query、path、body、header,formData
数据参数类型 string integer number boolean struct
以login登录api为例

// Login
// @Summary  用户登录
// @Tags     ExaApi
// @Produce   application/json
// @Param name formData string false "名字"
// @Param pwd formData string false "密码" 
// @Success  200   {object}  response.Response{data=exaApiRes.UserinfoResponse,msg=string,code=int}  "返回包括用户信息,token,过期时间"
// @Router   /exaApi/login [post]
func (e *ExaApi) Login(c *gin.Context) {
  var userinfo example.Userinfo
  err := c.ShouldBind(&userinfo)
  ...  // 业务逻辑
  if err != nil {
    response.FailWithMessage(err.Error(), c)
    return
  }
  response.OkWithDetailed(exaApiRes.UserinfoResponse{
    Userinfo: userinfo,
    Token:    userinfo.Pwd,
  }, "登录成功", c)
}

然后在路由初始化时配置swagger的路由条目

// server\initialize\router.go
 docs.SwaggerInfo.BasePath = global.GVA_CONFIG.System.RouterPrefix
Router.GET(global.GVA_CONFIG.System.RouterPrefix+"/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: 暂无
最后更新:2024年11月20日
< 上一篇
归档
  • 2024 年 11 月
  • 2024 年 8 月
  • 2024 年 5 月
  • 2024 年 2 月
  • 2023 年 12 月
  • 2023 年 11 月
  • 2023 年 9 月
  • 2023 年 6 月
  • 2022 年 12 月
  • 2022 年 11 月
  • 2022 年 10 月
  • 2022 年 9 月
  • 2022 年 8 月
  • 2022 年 7 月
  • 2022 年 6 月
  • 2022 年 5 月
  • 2022 年 4 月
  • 2022 年 3 月
  • 2022 年 2 月
  • 2022 年 1 月
  • 2021 年 12 月
  • 2021 年 11 月
  • 2021 年 10 月
  • 2021 年 5 月
分类
  • Android
  • Arduino
  • cordova
  • css
  • go
  • html5
  • JavaScript
  • nodejs
  • oracle
  • project
  • system
  • uni-app
  • vscode
  • vue
  • 学习计划
  • 摘抄
  • 随想
最新 热点 随机
最新 热点 随机
windows安装mysql ,VSCODE连接MySQL数据库 创建api的逻辑 观看七战奥运会 德国波尔告别 go utils工具 Go语言中的sort包帮我们实现了对任一类型的数组进行排序。 vue + go安装
Android日期时间对话框 css3制作圣诞树 【go】运行main时,error obtaining VCS status: exit status 读阮一峰老师-未来娱乐业 Element-UI InfiniteScroll 无限滚动 css基础

COPYRIGHT © 技海泛舟(个人技术研究). 2021-2023. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

黑ICP备19002110号-1

黑公网安备 23060202000432号