Gin框架与《Web Development with Go》实践(七)

与Mongodb有关的数据持久

taskmanager2项目中的目录结构:


taskmaanger-data2.png

src/taskmanager2/data2/taskRepository.go
其中的内容为与mongodb中的集合task紧密相关的CRUD操作

package data2

import (
    "time"
    "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
    "taskmanager2/models2"
)

type TaskRepository struct {
    C *mgo.Collection
}

func (r *TaskRepository) Create(task *models2.Task) error {
    obj_id := bson.NewObjectId()
    task.Id = obj_id
    task.CreatedOn = time.Now()
    task.Status = "Created"
    err := r.C.Insert(&task)
    return err
}

func (r *TaskRepository) Update(task *models2.Task) error {
    // partial update on MogoDB
    err := r.C.Update(bson.M{"_id": task.Id},
        bson.M{"$set": bson.M{
            "name":        task.Name,
            "description": task.Description,
            "due":         task.Due,
            "status":      task.Status,
            "tags":        task.Tags,
        }})
    return err
}
func (r *TaskRepository) Delete(id string) error {
    err := r.C.Remove(bson.M{"_id": bson.ObjectIdHex(id)})
    return err
}
func (r *TaskRepository) GetAll() []models2.Task {
    var tasks []models2.Task
    iter := r.C.Find(nil).Iter()
    result := models2.Task{}
    for iter.Next(&result) {
        tasks = append(tasks, result)
    }
    return tasks
}
func (r *TaskRepository) GetById(id string) (task models2.Task, err error) {
    err = r.C.FindId(bson.ObjectIdHex(id)).One(&task)
    return
}
func (r *TaskRepository) GetByUser(user string) []models2.Task {
    var tasks []models2.Task
    iter := r.C.Find(bson.M{"createdby": user}).Iter()
    result := models2.Task{}
    for iter.Next(&result) {
        tasks = append(tasks, result)
    }
    return tasks
}

task资源的处理函数

资源路径与其对应的处理函数:
src/taskmanager2/routers2/task.go

package routers2

import (
    "gopkg.in/gin-gonic/gin.v1"
    "taskmanager2/controllers2"
    "taskmanager2/common2"
)

// SetTaskRoutes configures routes for task entity
func SetTaskRoutes(router *gin.Engine) *gin.Engine {

    taR := router.Group("/tm2/tasks")
    taR.Use(common2.Authorize())
    {
        taR.POST("", controllers2.CreateTask)
        taR.PUT(":id", controllers2.UpdateTask)
        taR.DELETE(":id", controllers2.DeleteTask)
        taR.GET("", controllers2.GetTasks)
        taR.GET("t/:id/", controllers2.GetTaskByID)
        taR.GET("users/:email/", controllers2.GetTasksByUser)
    }
    return router
}

具体函数:

src/taskmanager2/controllers2/taskCtrler.go

package controllers2

import (
    "net/http"
    "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
    "gopkg.in/gin-gonic/gin.v1"
    "taskmanager2/common2"
    "taskmanager2/data2"
)

// CreateTask insert a new Task document
// Handler for HTTP Post - "/tasks
func CreateTask(c *gin.Context) {
    var dataResource TaskResource
    // Decode the incoming Task json
    err := c.BindJSON(&dataResource)
    if err != nil {
        common2.DisplayAppError(
            c,
            err,
            "Invalid Task data",
            500,
        )
        return
    }
    task := &dataResource.Data
    context := NewContext()
    defer context.Close()
    context.User = task.CreatedBy

    col := context.DbCollection("tasks")
    repo := &data2.TaskRepository{C: col}

    // Insert a task document
    repo.Create(task)

    c.JSON(http.StatusCreated, TaskResource{Data: *task})
}

// GetTasks returns all Task document
// Handler for HTTP Get - "/tasks"
func GetTasks(c *gin.Context) {
    context := NewContext()
    defer context.Close()
    col := context.DbCollection("tasks")
    repo := &data2.TaskRepository{C: col}
    tasks := repo.GetAll()

    c.JSON(http.StatusOK, TasksResource{Data: tasks})
}

// GetTaskByID returns a single Task document by id
// Handler for HTTP Get - "/tasks/t/:id"
func GetTaskByID(c *gin.Context) {
    // Get id from the incoming url
    id := c.Param("id")
    context := NewContext()
    defer context.Close()

    col := context.DbCollection("tasks")
    repo := &data2.TaskRepository{C: col}
    task, err := repo.GetById(id)
    if err != nil {
        if err == mgo.ErrNotFound {
            c.JSON(http.StatusNoContent, gin.H{})

        } else {
            common2.DisplayAppError(
                c,
                err,
                "An unexpected error has occurred",
                500,
            )

        }
        return
    }
    c.JSON(http.StatusOK, TaskResource{Data: task})
}

// GetTasksByUser returns all Tasks created by a User
// Handler for HTTP Get - "/tasks/users/:email"
func GetTasksByUser(c *gin.Context) {
    // Get id from the incoming url
    user := c.Param("email")
    context := NewContext()
    defer context.Close()
    col := context.DbCollection("tasks")
    repo := &data2.TaskRepository{C: col}
    tasks := repo.GetByUser(user)

    c.JSON(http.StatusOK, TasksResource{Data: tasks})
}

// UpdateTask update an existing Task document
// Handler for HTTP Put - "/tasks/:id"
func UpdateTask(c *gin.Context) {
    // Get id from the incoming url
    id := bson.ObjectIdHex(c.Param("id"))
    var dataResource TaskResource
    // Decode the incoming Task json
    err := c.BindJSON(&dataResource)
    if err != nil {
        common2.DisplayAppError(
            c,
            err,
            "Invalid Task data",
            500,
        )
        return
    }
    task := &dataResource.Data
    task.Id = id
    context := NewContext()
    defer context.Close()
    col := context.DbCollection("tasks")
    repo := &data2.TaskRepository{C: col}
    // Update an existing Task document
    if err := repo.Update(task); err != nil {
        common2.DisplayAppError(
            c,
            err,
            "An unexpected error has occurred",
            500,
        )
        return
    }
    c.Status(http.StatusNoContent)
}

// DeleteTask deelete an existing Task document
// Handler for HTTP Delete - "/tasks/:id"
func DeleteTask(c *gin.Context) {

    id := c.Param("id")
    context := NewContext()
    defer context.Close()
    col := context.DbCollection("tasks")
    repo := &data2.TaskRepository{C: col}
    // Delete an existing Task document
    err := repo.Delete(id)
    if err != nil {
        common2.DisplayAppError(
            c,
            err,
            "An unexpected error has occurred",
            500,
        )
        return
    }
    c.Status(http.StatusNoContent)
}

json资源模型

src/taskmanager2/controllers2/resources.go

package controllers2

import (
    "taskmanager2/models2"
)

type (
    ...
    TaskResource struct {
        Data models2.Task `json:"data"`
    }
    TasksResource struct {
        Data []models2.Task `json:"data"`
    }
    ...
)

task资源的测试API操作

登录系统并获取jwt

post --- localhost:8890/tm2/users/login
调用:


响应:


增加数据

post --- localhost:8890/tm2/tasks/
调用:


响应:


数据库中查看结果:


删除数据

delete --- localhost:8890/tm2/tasks/593e72625a9c4078ae5f1a79
调用:


响应:


数据库中查看结果(第14条数据已被删除):


修改数据

put --- localhost:8890/tm2/tasks/593e72495a9c4078ae5f1a78
调用:


响应:


tm-p2.png

数据库中查看结果:
原数据:


新数据:


获取全部的数据

get --- localhost:8890/tm2/tasks
调用:


响应:


通过task的id获取数据

get --- localhost:8890/tm2/tasks/t/593e6f985a9c4078ae5f1a77/
调用:


响应:


通过user的email获取数据

get --- localhost:8890/tm2/tasks/users/007@abc.com
调用:

响应:


小结

至此,RESTful API中,user和task资源的功能已全部实现。实践证明gin框架能够很好地满足此应用的改造要求。
在改造的过程中,某些细节之处仍有不足,待日后慢慢完善。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容