不忘初心,砥砺前行
作者 | 陌无崖
转载请联系授权
定义
RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML或者JSON格式定义。主要适用于移动互联网业务接口的场景。主要动作类型为新增、变更、删除所使用的资源。
REST描述了一个架构样式的网络系统,倾向于用更加简单轻量的方法设计和实现。没有明确的标准,更像一种设计风格。
注:
REST本身不是架构,只是一种架构风格
原则
1、客户端和服务器之间的交互在请求之间是无状态的。
2、服务端公开资源(应用程序对象、数据库记录、算法等),每个资源都使用URI进行标识,得到一个唯一的地址。所有的资源都共享统一的接口。便于 在客户端和服务器之间传输。
注:
所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。你可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或独一无二的识别符。
资源是一中信息实体,可以有很多表现形式。URI只是代表资源的实体,不代表它的形式,有些网址后的.html是一种表现形式,URI只代表资源的位置,它的具体表现形式应该是在请求头信息中用Accept和Content-Type字段指定。
RESTful特点
1、每个URI代表一种资源;
2、客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作;
3、客户端与服务端之间的交互在请求之间是无状态的;
使用方式
传统
http://127.0.0.1/item/queryItem.action?id=1 查询,GET
http://127.0.0.1/item/saveItem.action 新增,POST
http://127.0.0.1/item/updateItem.action 更新,POST
http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST
RESTful
http://127.0.0.1/item/1 查询,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 删除,DELETE
注:
这就变成了使用同一个 URL ,通过约定不同的 HTTP 方法来实施不同的业务
![](https://i-blog.csdnimg.cn/blog_migrate/035f84bba54d00b56339fcecf967ed79.png)
基于Go设计我们的Restful
入门案例(创建待办事项)
package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
)
func main() {
router := mux.NewRouter().StrictSlash(true)
router.HandleFunc("/", Index)
router.HandleFunc("/todos", TodoIndex)
router.HandleFunc("/todos/{todoId}", TodoShow)
log.Fatal(http.ListenAndServe(":8080", router))
}
func Index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Welcome!")
}
func TodoIndex(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Todo Index!")
}
func TodoShow(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
todoId := vars["todoId"]
fmt.Fprintln(w, "Todo Show:", todoId)
}
注:vars := mux.Vars(r)
用来解析我们的r。
创建待办结构体
type Todo struct {
Name string `json:"name"`
Completed bool `json:"completed"`
Due time.Time `json:"due"`
}
type Todos []Todo
返回JSON数据
我们需要在函数中模拟静态的数据列表
func TodoIndex(w http.ResponseWriter, r *http.Request) {
todos := Todos{
Todo{Name: "Write presentation"},
Todo{Name: "Host meetup"},
}
json.NewEncoder(w).Encode(todos)
}
拆分代码
handler.go
func Index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Welcome!")
}
func TodoIndex(w http.ResponseWriter, r *http.Request) {
todos := Todos{
Todo{Name: "Write presentation"},
Todo{Name: "Host meetup"},
}
if err := json.NewEncoder(w).Encode(todos); err != nil {
panic(err)
}
}
func TodoShow(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
todoId := vars["todoId"]
fmt.Fprintln(w, "Todo show:", todoId)
}
route.go
type Route struct {
Name string
Method string
Pattern string
HandlerFunc http.HandlerFunc
}
type Routes []Route
func NewRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range routes {
router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(route.HandlerFunc)
}
return router
}
var routes = Routes{
Route{
"Index",
"GET",
"/",
Index,
},
Route{
"TodoIndex",
"GET",
"/todos",
TodoIndex,
},
Route{
"TodoShow",
"GET",
"/todos/{todoId}",
TodoShow,
},
}
todo.go
type Todo struct {
Name string `json:"name"`
Completed bool `json:"completed"`
Due time.Time `json:"due"`
}
type Todos []Todo
main.go
func main() {
router := NewRouter()
log.Fatal(http.ListenAndServe(":8080", router))
}
POST JSON
func TodoCreate(w http.ResponseWriter, r *http.Request) {
var todo Todo
//io.LimitReader。这样是保护服务器免受恶意攻击的好方法
body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
if err != nil {
panic(err)
}
if err := r.Body.Close(); err != nil {
panic(err)
}
if err := json.Unmarshal(body, &todo); err != nil {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(422) // unprocessable entity
if err := json.NewEncoder(w).Encode(err); err != nil {
panic(err)
}
}
//创建新纪录
t := RepoCreateTodo(todo)
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusCreated)
if err := json.NewEncoder(w).Encode(t); err != nil {
panic(err)
}
}
误区
1、URI包含动词。因为"资源"表示一种实体,所以应该是名词,URI不应该有动词,动词应该放在HTTP协议中;
2、URI中不应该加入版本号;
本文参考以下文章:
https://baike.baidu.com/item/RESTful
http://www.ruanyifeng.com/blog/2014/05/restful_api.html
http://www.ruanyifeng.com/blog/2011/09/restful.html
https://segmentfault.com/a/1190000014875956#articleHeader17
关注我试试回复以下关键词
go 微服务 ppt
大数据 书籍 资料
END
今日推荐阅读
RabbitMQ系列笔记广播模式和路由模式
RabbitMQ系列笔记入门篇
基于Nginx和Consul构建高可用及自动发现的Docker服务架构
▼关注我,一起成长
主要分享 学习心得、笔记、随笔▼
![](https://i-blog.csdnimg.cn/blog_migrate/33a8bdec738c7da7ae93f40d32e67ff0.png)