今天才知道RESTful这个词,感觉好落后呀。自从5月份后很少学习新知识,这是个不好的信号。
RESTful是Representational State Transfer的缩写。怎么理解Representational State Transfer呢?
- 资源(Resources):
所谓资源,就是一个网络实体,或者说就是网络上的一个具体信息。它可以是一段音乐,一个图片,一首歌曲,一种服务,总之就是一个具体的存在。你可以使用URI(统一资源定位符)指向他们,每种资源都有一个特定的URI。要获取这个资源,只需访问这个URI就可以了。因此这个URI就成为一个独一无二的识别符。
- 表现层(Representation):
资源是一个信息实体,它可以有多种表现实体。我们把资源的具体呈现形式,称为表现层(Representation),例如:图片,txt, json等
URI只代表资源的实体,不代表它的形式。严格地说,有些网址最后的".html"后缀名是不必要的,因为这个后缀名表示格式,属于"表现层"范畴,而URI应该只代表"资源"的位置。它的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对"表现层"的描述。
- 状态转化(State Transfer)
访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。
互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。
客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源
以上引用:阮一峰 理解restful架构
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
经过3天研究发现restful很有意思,同时,我基本上填坑的,我是用go + PostgreSQL 语言写的,go我不是太会,PostgreSQL我从来没用过。本来是个很简单的玩意,硬是花了3天。go真心不好调试。
go RESTful 库:https://github.com/ant0ine/go-json-rest
go postgreSql driver: https://github.com/go-pg/pg
主要参考的就是这个例子:
1 package main 2 3 import ( 4 "fmt" 5 "github.com/ant0ine/go-json-rest/rest" 6 "log" 7 "net/http" 8 "sync" 9 ) 10 11 func main() { 12 13 users := Users{ 14 Store: map[string]*User{}, 15 } 16 17 api := rest.NewApi() 18 api.Use(rest.DefaultDevStack...) 19 router, err := rest.MakeRouter( 20 rest.Get("/users", users.GetAllUsers), 21 rest.Post("/users", users.PostUser), 22 rest.Get("/users/:id", users.GetUser), 23 rest.Put("/users/:id", users.PutUser), 24 rest.Delete("/users/:id", users.DeleteUser), 25 ) 26 if err != nil { 27 log.Fatal(err) 28 } 29 api.SetApp(router) 30 log.Fatal(http.ListenAndServe(":8080", api.MakeHandler())) 31 } 32 33 type User struct { 34 Id string 35 Name string 36 } 37 38 type Users struct { 39 sync.RWMutex 40 Store map[string]*User 41 } 42 43 func (u *Users) GetAllUsers(w rest.ResponseWriter, r *rest.Request) { 44 u.RLock() 45 users := make([]User, len(u.Store)) 46 i := 0 47 for _, user := range u.Store { 48 users[i] = *user 49 i++ 50 } 51 u.RUnlock() 52 w.WriteJson(&users) 53 } 54 55 func (u *Users) GetUser(w rest.ResponseWriter, r *rest.Request) { 56 id := r.PathParam("id") 57 u.RLock() 58 var user *User 59 if u.Store[id] != nil { 60 user = &User{} 61 *user = *u.Store[id] 62 } 63 u.RUnlock() 64 if user == nil { 65 rest.NotFound(w, r) 66 return 67 } 68 w.WriteJson(user) 69 } 70 71 func (u *Users) PostUser(w rest.ResponseWriter, r *rest.Request) { 72 user := User{} 73 err := r.DecodeJsonPayload(&user) 74 if err != nil { 75 rest.Error(w, err.Error(), http.StatusInternalServerError) 76 return 77 } 78 u.Lock() 79 id := fmt.Sprintf("%d", len(u.Store)) // stupid 80 user.Id = id 81 u.Store[id] = &user 82 u.Unlock() 83 w.WriteJson(&user) 84 } 85 86 func (u *Users) PutUser(w rest.ResponseWriter, r *rest.Request) { 87 id := r.PathParam("id") 88 u.Lock() 89 if u.Store[id] == nil { 90 rest.NotFound(w, r) 91 u.Unlock() 92 return 93 } 94 user := User{} 95 err := r.DecodeJsonPayload(&user) 96 if err != nil { 97 rest.Error(w, err.Error(), http.StatusInternalServerError) 98 u.Unlock() 99 return 100 } 101 user.Id = id 102 u.Store[id] = &user 103 u.Unlock() 104 w.WriteJson(&user) 105 } 106 107 func (u *Users) DeleteUser(w rest.ResponseWriter, r *rest.Request) { 108 id := r.PathParam("id") 109 u.Lock() 110 delete(u.Store, id) 111 u.Unlock() 112 w.WriteHeader(http.StatusOK) 113 }
这里有个巨坑,找了好久才发现:
1 type User struct { 2 Id string 3 Name string 4 }
这些变量必须大写,如果小写的,程序不会报错,但是没有结果。(我对json不太会,估计是这个问题)
还有就是go 封装的PostgreSQL driver,我已无力吐槽,API明显不给力,写的SQL各种出错,但是不知道错误原因,硬是各种看SQL怎么错了。