sagooiot后端api实现

sagooiot-professional项目API接口实现步骤详解

API接口实现架构概述

sagooiot-professional项目采用GoFrame框架构建,遵循清晰的分层架构设计,其API接口实现主要通过GoFrame CLI工具自动生成骨架,再由开发者进行业务逻辑填充。下面详细解析整个实现流程和架构设计。

API接口实现完整步骤

1. 接口定义层(api层)

API接口首先在api/v1/{module}目录下定义,如api/v1/system/sys_user.go

  • 定义请求(Req)和响应(Res)结构体
  • 使用GoFrame的g.Meta标签声明接口元数据(路径、HTTP方法、摘要、标签等)
  • 定义参数验证规则

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// UserListReq 用户列表请求参数
type UserListReq struct {
g.Meta `path:"/system/user/list" method:"get" summary:"获取用户列表" tags:"用户管理"`
PageNum int `json:"pageNum" v:"required|min:1" dc:"页码"`
PageSize int `json:"pageSize" v:"required|min:1|max:100" dc:"每页数量"`
KeyWords string `json:"keyWords" dc:"关键词搜索"`
DeptId int `json:"deptId" dc:"部门ID"`
Status int `json:"status" dc:"状态"`
}

// UserListRes 用户列表响应参数
type UserListRes struct {
List []*UserInfoRes `json:"data" dc:"用户列表数据"`
Total int `json:"total" dc:"总数"`
CurrentPage int `json:"currentPage" dc:"当前页码"`
}

2. 控制器层(controller层)

控制器层位于internal/controller/{module}目录下,如internal/controller/system/sys_user.go

  • 定义控制器结构体和全局变量
  • 实现API接口对应的处理函数
  • 处理请求参数转换和验证
  • 调用服务层(service)的方法处理业务逻辑
  • 构造并返回响应数据

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SysUser 用户
var SysUser = cSysUser{}

type cSysUser struct{}

// UserList 用户列表
func (c *cSysUser) UserList(ctx context.Context, req *system.UserListReq) (res *system.UserListRes, err error) {
//获取所有用户列表
var input *model.UserListDoInput
if err = gconv.Scan(req, &input); err != nil {
return
}
total, out, err := service.SysUser().UserList(ctx, input)
if err != nil {
return
}
res = new(system.UserListRes)
res.Total = total
res.CurrentPage = req.PageNum
if out != nil {
if err = gconv.Scan(out, &res.Data); err != nil {
return
}
}
return
}

3. 服务接口层(service层)

服务接口层位于internal/service目录下,如internal/service/system.go

  • 定义服务接口(如ISysUser
  • 定义全局访问函数(如SysUser())和注册函数(如RegisterSysUser()
  • 实现单例模式的服务访问机制

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
type ISysUser interface {
// UserList 用户列表
UserList(ctx context.Context, input *model.UserListDoInput) (total int, out []*model.UserListOut, err error)
// Add 添加用户
Add(ctx context.Context, input *model.AddUserInput) (err error)
// 其他方法...
}

func SysUser() ISysUser {
if localSysUser == nil {
panic("implement not found for interface ISysUser, forgot register?")
}
return localSysUser
}

func RegisterSysUser(i ISysUser) {
localSysUser = i
}

4. 业务逻辑层(logic层)

业务逻辑层位于internal/logic/{module}目录下,如internal/logic/system/sys_user.go

  • 实现服务接口定义的所有方法
  • 包含具体的业务逻辑实现
  • 调用数据访问层(dao)进行数据操作
  • init()函数中注册服务实现

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
type sSysUser struct {
}

func init() {
service.RegisterSysUser(sysUserNew())
}

func sysUserNew() *sSysUser {
return &sSysUser{}
}

// UserList 用户列表
func (s *sSysUser) UserList(ctx context.Context, input *model.UserListDoInput) (total int, out []*model.UserListOut, err error) {
m := dao.SysUser.Ctx(ctx)
// 构建查询条件
if input.KeyWords != "" {
keyWords := "%" + input.KeyWords + "%"
m = m.Where("user_name like ? or user_nickname like ?", keyWords, keyWords)
}
// 其他查询条件...

//根据数据权限过滤数据
m, _ = service.SysAuthorize().FilterDataByPermissions(ctx, m)

//获取总数
total, err = m.Count()
// 获取分页数据
// 处理结果...
return
}

5. 数据访问层(dao层)

数据访问层位于internal/dao目录下,如internal/dao/sys_user.go

  • 提供数据库表的访问对象
  • 封装数据库操作方法
  • 由GoFrame CLI工具自动生成基础代码

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================

package dao

import (
"sagooiot/internal/dao/internal"
)

// SysUser is globally public accessible object for table sys_user operations.
var SysUser = sysUserDao{
internal.NewSysUserDao(),
}

6. 数据模型层(model层)

数据模型层位于internal/model目录下,包含多个子目录:

  • entity:数据库实体模型,由GoFrame CLI自动生成
  • do:数据操作模型
  • 其他业务模型

示例代码(entity):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================

package entity

import (
"github.com/gogf/gf/v2/os/gtime"
)

// SysUser is the golang structure for table sys_user.
type SysUser struct {
Id int64 `json:"id" orm:"id"`
UserName string `json:"userName" orm:"user_name" description:"用户名"`
UserTypes string `json:"userTypes" orm:"user_types" description:"系统 system 企业 company"`
// 其他字段...
}

自动生成与手动实现的结合方式

项目采用"自动生成骨架 + 手动实现业务"的混合方式:

  1. 自动生成部分

    • API接口定义和基础结构
    • 数据模型(entity、dao)
    • 服务接口定义
    • 控制器基本框架
    • 从代码注释可以看出:// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
  2. 手动实现部分

    • 具体业务逻辑(logic层)
    • 复杂参数验证和转换
    • 自定义查询和数据处理
    • 事务管理和错误处理

关键技术特点

  1. 接口与实现分离:通过service层定义接口,logic层实现接口,降低耦合度
  2. 依赖注入:通过Register函数注册服务实现,支持测试和替换
  3. 单例模式:通过全局变量和访问函数实现服务的单例访问
  4. 参数转换:使用gconv.Scan实现不同结构体间的参数转换
  5. 数据权限控制:在service层集成数据权限过滤机制
  6. 国际化支持:使用gi18n.Translate实现错误信息的国际化

总结

sagooiot-professional项目的API接口实现采用了GoFrame框架推荐的分层架构,结合了自动生成和手动编码的方式。GoFrame CLI工具负责生成基础代码骨架,开发者在此基础上实现具体业务逻辑。这种方式既提高了开发效率,又保证了代码的规范性和可维护性。