抖音极简版| 青训营笔记

231 阅读3分钟

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

项目所用技术栈

GO GIN GORM GIN-JWT REDIS

项目亮点

  • token使用GIN-JWT生成,保证token的安全性,除了登陆注册和视频流,其他接口都需要通过中间件验证token是否合法

屏幕截图 2022-06-12 123256.png

  • 点赞数据通过redis存储,每条视频都有一个score,score由视频发布时间和点赞数决定
  • 用户ID和视频ID使用雪花算法生成唯一ID,密码使用MD5加密存储
  • 对于sql语句使用预编译占位符填充的方法编写,一定程度上防止sql注入,gorm中interpolateParams设置为false,删去Conn到数据库中预编译的三个步骤,提高查询效率 image.png
  • 视频封面使用ffmpeng进行抽取

image.png

项目层次结构

controller:为前端发送的请求提供接口并返回数据和状态码
middlewares:中间件
public:存放视频和封面到本地
respository:封装了操作数据库的增删改查方法
service:封装了较为复杂的业务逻辑
util:工具类

项目演示

视频流

屏幕截图 2022-06-12 004758.png

点赞

屏幕截图 2022-06-12 004820.png 喜爱列表

5fdc8fae753496e8a369a2d9f4cf6fb.jpg

发布列表

屏幕截图 2022-06-12 010358.png

评论列表

屏幕截图 2022-06-12 131356.png

模型数据

user 主键Id

type User struct {
   Id            int64  `json:"id,omitempty" gorm:"column:id"`
   Password      string `json:"password,omitempty" gorm:"column:password"`
   Name          string `json:"name,omitempty" gorm:"unique_index,column:name"`
   FollowCount   int64  `json:"follow_count,omitempty" gorm:"column:followcount"`
   FollowerCount int64  `json:"follower_count,omitempty" gorm:"column:followercount"`
   IsFollow      bool   `json:"is_follow,omitempty" gorm:"column:IsFollow"`
   Token         string `gorm:"unique_index,column:token"`
}

comment 主键ID 外键UserID 和VideoID

type Comment struct {
   Id         int64 `json:"id,omitempty"`
   UserID     int64
   User       User `json:"user" gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
   VideoID    int64
   Video      Video  `json:"user" gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
   Content    string `json:"content,omitempty"`
   CreateDate string `json:"create_date,omitempty"`
}

video 主键ID 外键Author ID

type Video struct {
   Id            int64 `json:"id,omitempty"`
   AuthorID      int64
   Author        User      `json:"author" gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
   PlayUrl       string    `json:"play_url" json:"play_url,omitempty"`
   CoverUrl      string    `json:"cover_url,omitempty"`
   FavoriteCount int64     `json:"favorite_count,omitempty"`
   CommentCount  int64     `json:"comment_count,omitempty"`
   IsFavorite    bool      `json:"is_favorite,omitempty"`
   CreateTime    time.Time `gorm:"column:create_time"`
   Title         string    `json:"title" gorm:"column:title"`
}

粉丝

type FollowFollower struct {
   gorm.Model
   FollowId   int64
   FollowerId int64
   IsFavorite bool
}

各个接口说明

feed

逻辑

根据客户端传输的latest_time作为本次视频流的起始索引,执行GetVideoList方法
GetVideoList:

  • 从Redis中的查询视频的ids并根据视频的得分高低返回ids。(Redis以zset的数据结构存储视频的id)再根据ids到
  • MYSQL中获取视频数据。每次请求中得分高的视频排在前面。得分由视频发布时间和点赞数决定,起始分数为发布时间,每次点赞加432分。取消则减432分

接口测试

image.png

Register

逻辑:

  • 从url中获取username和password,数据库查询是否存在
  • 不存在使用JWT生成token,使用雪花算法生成userID
  • 将User存进数据库中,密码使用md5加密

接口测试

屏幕截图 2022-06-12 132726.png

Login

逻辑:

  • 从url中获取username和password,根据username获取token,token存在则返回userID和token,不存在则提示用户不存在

接口测试

屏幕截图 2022-06-12 132826.png

Publish

逻辑:

  • 从表单中获取title和token、文件,使用雪花算法生成videoID,根据用户名存储视频的url,mysql保存video的信息,redis以zset的形式保存video的id

接口测试

屏幕截图 2022-06-12 132826.png

屏幕截图 2022-06-12 133938.png

favourite

逻辑:

  • 从url中获取token,vidoID,actiontype并根据token获取user数据
  • actiontype为1,则为视频加分和加点赞数,并在redis中将userID存入视频的点赞列表,将videoID存入视频的喜爱列表,存入为0则减分和减点赞数,从点赞列表删去userID,从喜爱列表中删区videoID

接口测试

屏幕截图 2022-06-12 134252.png

屏幕截图 2022-06-12 134414.png

comment

逻辑:

  • 从url中获取token和text(评论字段),videoID,ationtype,根据token获取user数据
  • 如果actiontype=1则添加评论并存入数据库,如果等于0则删除评论

Follow

逻辑:

  • 从url中获取关注者和被关注者、token、actiontype,先判断关注者是不是作者,如果是作者返回错误
  • 根据actiontype判断是关注还是取消,如果关注则保存关注者id和被关注者id到follow表中,如果是取消则将表中的IsFavorite属性设为false