大项目总结 | 青训营笔记

137 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第六篇笔记

本次笔记记录我们组的项目:抖声后端开发的要点。

项目结构

image-20220614122548381.png

  • cmd/ 存放项目启动相关

    • bin/ 本地调试时存放项目生成的二进制可执行文件

    • runtime/ 存放项目运行时产生的文件

      • logs/ 存放项目运行时日志
  • common/

    • config/ 项目的配置读取
    • cron/ 定时任务
    • db/ 数据库支持
    • log/ 日志配置
    • model/ 数据表
    • oss/ OSS,配置了 minio 和 aliyun 两种
    • result/ 规范了全局的错误码和返回值
  • controller/ 控制层实现

  • doc/ 存放项目文档

    • imgs/ 存放文档所需的图片
  • middlewire/ 中间件

  • service/ 服务层实现

  • test/ 项目单元测试

  • util/ 存放封装了项目通用逻辑的小工具

  • app.example.yaml 项目配置文件示例(远程服务器配置ignore,不上传至仓库)

数据库设计

注:该文档为最初始的文档,实际数据表以 common 中的 model.go 为准

用户表

字段类型注释
idint64id,主键
namestring用户昵称,index
usernamestring登录用户名
passwordstring登录密码
follow_countint64关注总数
follower_countint64粉丝总数

视频表

字段类型注释
idint64id,主键
publish_idint64发布者id,外键对应于用户表id
play_urlstring视频播放地址
cover_urlstring视频封面地址
create_timestring创建时间,精确到秒
favorite_countint64视频点赞总数
comment_countint64视频评论总数
titlestring视频标题

评论表

字段类型注释
idint64评论id,主键
user_idint64评论人id,外键
contentstring评论内容
create_timestring评论时间,mm-dd
video_idint64评论视频id,外键

关注表

字段类型注释
idint64id,主键
user_idint64被关注人id,外键
follow_idint64关注人id,外键
create_timestring关注时间,精确到秒

视频点赞表

字段类型注释
idint64id,主键
user_idint64用户id,外键
video_idint64视频id,外键
create_timeint64点赞时间

项目初始化

 func init() {
    once.Do(func() {
       config.ReadCfg()
       config.Init()
       log.Init()
       db.Init()
       oss.Init()
       cron.Init()
    })
 }
 func main() {
   r := gin.Default()
 ​
   handle(r)
 ​
   r.Run(fmt.Sprintf("%s:%s", config.AppCfg.Host, config.AppCfg.Port))
 }

路由

路由在 router.go 中,注意鉴权中间件的使用。

路由转到相应的controller,再执行相关service,并返回responce或错误

service为具体功能实现

鉴权

本项目采用jwt鉴权

注册

  1. *gin.Context.ShouldBindWith 判断长度是否合法

  2. 数据库查询是否存在用户名err = db.MySQL.Debug().Model(&model.User{}).Where("username = ?", req.Username).Select("id").Count(&count).Error

    注意没查到也返回err,要有err != gorm.ErrRecordNotFound

  3. 采用bcrypt加盐加密,保护在数据库的密码安全

  4. 通过user.id创建token,和refreshToken ,前者2h,后者30d,并存入Redis set

登录

  1. 解析参数
  2. 数据库查询用户名是否存在
  3. 密码校验bcrypt.CompareHashAndPassword
  4. 通过user.id创建token,和refreshToken ,前者2h,后者30d,并存入Redis set

拦截鉴权

所有服务均要get或post当前用户的token,暂不清楚前端存储token方式。

查询refreshToken,不存则代表超三十天未登录,需重新登录;若未过期,在redis更新两个token,并给login发送post。这种鉴权方法可以有效防止token被窃取,token频繁刷新,提高了web项目的安全性。

日志

采用zap

对象存储

阿里云oss存储视频,返回url

文件类型判断用filetype.IsVideo

注意需分两次独立open multipart.file类型的文件,因为同一打开的文件经过校验后会损坏,会上传损坏的视频

通用result设计

 res.Success(c, res.R{
       "userid": data.UserId,
       "token":  data.Token,
    })