简易笔记的简易实现(2)路由定义与逻辑处理 | 青训营笔记

42 阅读5分钟

这是我参与「第五届青训营」伴学笔记创作活动的第6天

前言

这是简易笔记项目的第二篇,本篇主要描述路由的定义和具体的逻辑处理函数的实现。

此项目的代码已开源,lhou/easy-note,欢迎访问和提issue。如果能给个star就更好了。

定义路由

根据这篇文章的定义,定义以下路由

路由组路由方式说明
//loginpost登录
/registerpost注册
/user/:idget获取用户信息
/note/:idget获取笔记信息
/get获取笔记列表
/post创建笔记
/:idput修改笔记
/:iddelete删除笔记

定义逻辑处理函数

通过分析,逻辑处理函数主要有两部分

  1. 用户部分
  2. 笔记部分

下面将逐个实现

用户部分的逻辑处理

通过路由分析可知,我们需要实现注册、登录、获取用户信息三个逻辑。 首先先定义一个userHandler的结构体

type UserHandler struct {
   Repo repo.UserRepo
}

这里面的repo是上篇文章编写的用户数据处理,在这引用可以方便开发。

注册逻辑实现

注册逻辑主要有以下几步

  1. 用户输入校验
  2. 存入数据库
  3. 根据返回结果判断注册成功与否
  4. 将注册结果返回给用户

用户输入校验

首先根据模型,定义一个结构体用于接收用户提供的数据。在本项目中,是用户名、密码、头像和性别。

下面是实现的具体代码,如果校验失败,那么直接返回错误值,结束本次注册流程。这里面我封装了返回函数。原生的函数是c.Json(statusCode,data)

var registerForm struct {
    Username, Password, Avatar string
    Gender                     int
   }
err := c.BindAndValidate(&registerForm)
if err != nil {
    resp.BadRequestResponse(c, 1, "请求参数错误")
    return
   }

存入数据库

调用已经定义好的插入数据的函数,将数据封装成模型,获取返回值。

result := userHandler.Repo.InsertUser(&models.User{
      Username: registerForm.Username,
      Password: registerForm.Password,
      Gender:   registerForm.Gender,
      Avatar:   registerForm.Avatar,
   })

返回注册结果

根据上步的返回结果,判断是否注册成功并将结果返回给用户。

 if !result {
      resp.BadRequestResponse(c, 2, "注册失败,请检查您输入")
      return
   }
   resp.SuccessResponse(c, "注册成功", nil)

下面是整个注册逻辑实现的代码

func (userHandler *UserHandler) Register(_ context.Context, c *app.RequestContext) {
   // 定义一个结构体用于接收用户的注册信息
   var registerForm struct {
      Username, Password, Avatar string
      Gender                     int
   }
   err := c.BindAndValidate(&registerForm)
   if err != nil {
      resp.BadRequestResponse(c, 1, "请求参数错误")
      return
   }
   result := userHandler.Repo.InsertUser(&models.User{
      Username: registerForm.Username,
      Password: registerForm.Password,
      Gender:   registerForm.Gender,
      Avatar:   registerForm.Avatar,
   })
   if !result {
      resp.BadRequestResponse(c, 2, "注册失败,请检查您输入")
      return
   }
   resp.SuccessResponse(c, "注册成功", nil)
}

登陆逻辑的实现

登录逻辑与注册逻辑类似,这里不再赘述。下面是实现代码

func (userHandler *UserHandler) Login(_ context.Context, c *app.RequestContext) {
   var loginForm struct {
      Username, Password string
   }
   err := c.BindAndValidate(&loginForm)
   if err != nil {
      resp.BadRequestResponse(c, 1, "请求参数错误")
   }
   result := userHandler.Repo.CheckUser(loginForm.Username, loginForm.Password)
   if !result {
      resp.BadRequestResponse(c, 2, "登陆失败,请检查您的用户名和密码")
      return
   }
   resp.SuccessResponse(c, "登陆成功", nil)
   return
}

获取用户信息

注意到,在路由参数中,我们定义了id来作为查询用户信息的关键字。这里我们使用c.Param("id")来获取。这里获取的是字符串类型,需要将其转成整形。其他的部分与注册逻辑相同。

func (userHandler *UserHandler) GetUserById(_ context.Context, c *app.RequestContext) {
   id, err := strconv.Atoi(c.Param("id"))
   if err != nil {
      resp.BadRequestResponse(c, 1, "请求参数错误")
   }
   user := userHandler.Repo.GetUserById(id)
   if user != nil {
      resp.NotFountResponse(c, "找不到该用户")
   }
   resp.SuccessResponse(c, "请求成功", user)

}

笔记部分的处理逻辑实现

笔记部分主要包括以下内容

  1. 创建笔记
  2. 删除笔记
  3. 修改笔记
  4. 获取单个笔记
  5. 获取笔记列表(分页)

由于已经写好了对应的数据处理函数,因此以上部分的内容大体相同。结构均为获取、校验参数,请求数据库,返回处理结果三部分。代码如下

type NoteHandler struct {
   Repo repo.NoteRepo
}

func (noteHandler *NoteHandler) GetNoteById(_ context.Context, c *app.RequestContext) {
   id, err := strconv.Atoi(c.Param("id"))
   if err != nil {
      resp.BadRequestResponse(c, 1, "请求参数错误")
   }
   note := noteHandler.Repo.GetNoteById(id)
   if note == nil {
      resp.NotFountResponse(c, "找不到该笔记")
   }
   resp.SuccessResponse(c, "请求成功", note)
}

func (noteHandler *NoteHandler) ListNote(_ context.Context, c *app.RequestContext) {
   page, err := strconv.Atoi(c.Query("page"))
   if err != nil {
      resp.BadRequestResponse(c, 1, "请求参数错误")
   }
   size, err := strconv.Atoi(c.Query("size"))
   if err != nil {
      resp.BadRequestResponse(c, 1, "请求参数错误")
   }
   userId := c.GetInt("userId")
   var total *int64
   notes := noteHandler.Repo.ListNote(page, size, userId, total)
   if notes == nil {
      resp.NotFountResponse(c, "找不到笔记")
   }
   resp.SuccessResponse(c, fmt.Sprintf("找到%d篇", total), notes)
}

func (noteHandler *NoteHandler) UpdateNote(_ context.Context, c *app.RequestContext) {
   id, err := strconv.Atoi(c.Param("id"))
   if err != nil {
      resp.BadRequestResponse(c, 1, "请求参数错误")
   }
   var note struct {
      Name, Note string
   }
   err = c.BindAndValidate(&note)
   if err != nil {
      resp.BadRequestResponse(c, 1, "请求参数错误")
   }
   userId := c.GetInt("userId")
   result := noteHandler.Repo.UpdateNote(&models.NoteInfo{
      BaseModel: models.BaseModel{
         Id: id,
      },
      Name:   note.Name,
      Note:   note.Note,
      UserId: userId,
   })
   if !result {
      resp.BadRequestResponse(c, 5, "修改失败")
   }
   resp.SuccessResponse(c, "修改成功", nil)
}

func (noteHandler *NoteHandler) DeleteNote(_ context.Context, c *app.RequestContext) {
   id, err := strconv.Atoi(c.Param("id"))
   if err != nil {
      resp.BadRequestResponse(c, 1, "请求参数错误")
   }
   result := noteHandler.Repo.DeleteNote(id, c.GetInt("userId"))
   if !result {
      resp.BadRequestResponse(c, 6, "删除失败")
   }
   resp.SuccessResponse(c, "删除成功", nil)
}

func (noteHandler *NoteHandler) CreateNote(_ context.Context, c *app.RequestContext) {
   var note struct {
      Name, Note string
   }
   err := c.BindAndValidate(&note)
   if err != nil {
      resp.BadRequestResponse(c, 1, "请求参数错误")
   }
   userId := c.GetInt("userId")
   result := noteHandler.Repo.InsertNote(&models.NoteInfo{
      Name:   note.Name,
      Note:   note.Note,
      UserId: userId,
   })
   if !result {
      resp.BadRequestResponse(c, 5, "创建失败")
   }
   resp.SuccessResponse(c, "创建成功", nil)
}

路由与处理函数绑定

在完成数据处理函数的编写后,我们需要将其与路由绑定。下面是路由绑定的函数。

func InitRouters(h *server.Hertz) {
   var userHandler handler.UserHandler
   var noteHandler handler.NoteHandler
   h.POST("/login", userHandler.Login)
   h.POST("/register", userHandler.Register)
   userRouter := h.Group("/user")
   {
      userRouter.GET("/:id", userHandler.GetUserById)
   }
   noteRouter := h.Group("/note")
   {
      noteRouter.GET("/", noteHandler.ListNote)
      noteRouter.GET("/:id", noteHandler.GetNoteById)
      noteRouter.POST("/", noteHandler.CreateNote)
      noteRouter.PUT("/:id", noteHandler.UpdateNote)
      noteRouter.DELETE("/:id", noteHandler.DeleteNote)
   }
}

添加假数据

在完成上述步骤后,我们已经可以访问了,但是因为数据库中没有数据,我们只能得到查找失败的结果。为了完成测试,我们需要往数据库中添加假数据。这里推荐一个网站代码生成 - SQL之父 (sqlfather.com),这个网站可以快捷的生成假数据。

未完待续