简单 web 服务与客户端开发实战

概述

利用 web 客户端调用远端服务是服务开发本实验的重要内容。其中,要点建立 API First 的开发理念,实现前后端分离,使得团队协作变得更有效率。

任务目标

  • 选择合适的 API 风格,实现从接口或资源(领域)建模,到 API 设计的过程
  • 使用 API 工具,编制 API 描述文件,编译生成服务器、客户端原型
  • 使用 Github 建立一个组织,通过 API 文档,实现 客户端项目 与 RESTful 服务项目同步开发
  • 使用 API 设计工具提供 Mock 服务,两个团队独立测试 API
  • 使用 travis 测试相关模块

负责板块

服务端开发

json序列化和反序列化

REST风格

REST是使用json作为请求request和响应response的body的格式。可参考我之前的博客。
REST是由Roy Fielding提出的一种软件架构,现如今也是因为REST模式的web服务与复杂的SOAP、XML-RPC对比来说, 更加简洁,越来越多的web服务开始采用REST风格设计和实现。

实现

package controller

import (
	"encoding/json"
	"net/http"
	"strconv"
	"strings"

	"github.com/Sevice-Computing/Go-REST/lib"
	"github.com/Sevice-Computing/Go-REST/model"
)

// AddArticle Method
func AddArticle(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	article := model.Article{}
	article.Title = r.PostFormValue("title")
	article.Content = r.PostFormValue("content")
	article.Date = r.PostFormValue("date")
	article.Tag = strings.Split(r.PostFormValue("tag"), ",")
	userid, _ := strconv.Atoi(r.PostFormValue("userid"))
	user := model.QueryUserbyID(int32(userid))
	user.Password = ""
	article.User = user
	article = model.CreateArticle(article)
	if article.ID == -1 {
		w.WriteHeader(http.StatusInternalServerError)
	} else {
		buf, _ := json.Marshal(article)
		w.WriteHeader(http.StatusOK)
		w.Write(buf)
	}
}

// DeleteArticle Method
func DeleteArticle(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	id := lib.GetID(r.URL.Path)
	queryArticle := model.QueryArticlebyID(id)
	if queryArticle.ID != id {
		w.WriteHeader(http.StatusNotFound)
	} else {
		err := model.DeleteArticle(id)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
		} else {
			w.WriteHeader(http.StatusOK)
		}
	}
}

// GetAllArticle Method
func GetAllArticle(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	pageA := r.URL.Query()["page"]
	if len(pageA) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	page, _ := strconv.Atoi(pageA[0])
	if page <= 0 {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	articles := model.QueryAllArticle()
	if (len(articles)-1)/10 < page-1 {
		w.WriteHeader(http.StatusNotFound)
		return
	} else if len(articles) > 10 && len(articles) < page*10 {
		articles = articles[(page-1)*10 : page*10]
	} else {
		articles = articles[(page-1)*10:]
	}
	buf, _ := json.Marshal(articles)
	w.WriteHeader(http.StatusOK)
	w.Write(buf)

}

// GetArticleByID Method
func GetArticleByID(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	id := lib.GetID(r.URL.Path)
	article := model.QueryArticlebyID(id)
	buf, _ := json.Marshal(article)
	w.WriteHeader(http.StatusOK)
	w.Write(buf)
}

// GetArticleByTag Method
func GetArticleByTag(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	tagA := r.URL.Query()["tag"]
	pageA := r.URL.Query()["page"]
	if len(tagA) == 0 || len(pageA) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	tag := tagA[0]
	page, _ := strconv.Atoi(pageA[0])
	if page <= 0 {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	articles := model.QueryAllArticle()
	var result []model.Article
	var flag bool
	for _, article := range articles {
		flag = false
		for _, t := range article.Tag {
			if t == tag {
				flag = true
				break
			}
		}
		if flag {
			result = append(result, article)
		}
	}
	if (len(result)-1)/10 < page-1 {
		w.WriteHeader(http.StatusNotFound)
		return
	} else if len(articles) > 10 && len(articles) < page*10 {
		articles = articles[(page-1)*10 : page*10]
	} else {
		articles = articles[(page-1)*10:]
	}
	buf, _ := json.Marshal(result)
	w.WriteHeader(http.StatusOK)
	w.Write(buf)
}

// GetArticleByUser Method
func GetArticleByUser(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	userid := lib.GetID(r.URL.Path)
	pageA := r.URL.Query()["page"]
	if len(pageA) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	page, _ := strconv.Atoi(pageA[0])
	if page <= 0 {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	articles := model.QueryAllArticle()
	var result []model.Article
	for _, article := range articles {
		if article.User.ID == userid {
			result = append(result, article)
		}
	}
	if (len(result)-1)/10 < page-1 {
		w.WriteHeader(http.StatusNotFound)
		return
	} else if len(articles) > 10 && len(articles) < page*10 {
		articles = articles[(page-1)*10 : page*10]
	} else {
		articles = articles[(page-1)*10:]
	}
	buf, _ := json.Marshal(result)
	w.WriteHeader(http.StatusOK)
	w.Write(buf)
}

// UpdateArticle Method
func UpdateArticle(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	id := lib.GetID(r.URL.Path)
	queryArticle := model.QueryArticlebyID(id)
	if queryArticle.ID != id {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	queryArticle.Title = r.PostFormValue("title")
	queryArticle.Content = r.PostFormValue("content")
	queryArticle.Date = r.PostFormValue("date")
	queryArticle.Tag = strings.Split(r.PostFormValue("tag"), ",")
	err := model.UpdateArticle(queryArticle.ID, queryArticle)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
	} else {
		buf, _ := json.Marshal(queryArticle)
		w.WriteHeader(http.StatusOK)
		w.Write(buf)
	}
}

参考博客

https://blog.csdn.net/u013210620/article/details/78450474

完整代码

详见我们小组的完整项目代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值