resful api
什么是resful api
resful api是一套规范,可规范我们如何对服务器上的资源进行操作
http method
在介绍resful api之前,我们需要了解一下HTTP Method,因为resful api和它密不可分
最常见的就是GET和POST,最早在HTTP0.9版本只有一个GET方法,该方法是一个幂等方法,用于获取服务器上的资源,也就是在浏览器中直接输入网址,然后回车请求的方法
在HTTP1.0版本中又增加了HEAD和POST方法
其中常用的是POST方法,一般用于给服务端提交一些资源,导致服务器的资源发生变化
后来发现方法不够用,一口气增加到9个方法,新增的方法有:
- HEAD
- OPTIONS
- PUT
- DELETE
- TRACE
- PATCH
- CONNECT
GET方法:
可请求一个指定资源的表示形式,使用GET的请求应该只用于获取数据
HEAD方法:
请求一个与GET请求的响应相同的响应,但是没有响应体
POST方法:
将实体提交到指定的资源,通常导致服务器上的状态变化或副作用
PUT方法:
请求有效载荷替换目标资源的所有当前表示
DELETE方法:
删除指定资源
CONNECT方法:
建立一个到由目标资源标识的服务器的隧道
OPTIONS方法:
描述目标资源的通信选项
TRACE方法:
沿着到目标资源的路径执行一个消息环回测试
PATCH方法:
对资源应用部分修改
HTTP针对每个方法都给出了明确的定义,我们应该尽可能的遵循HTTP的规范,这样我们在开发中才能更好的协作,因为它是一套通用的规范,大家都在遵守
理解了HTTP的方法,就能更好的理解RESFUL API
RESFUL API规范就是基于这些HTTP方法规范我们对服务器资源的操作
同时规范了URL的样式和HTTP STATUS CODE
resful api 主要使用下面5种http方法
服务器上的资源通过特定的url表示,接下来通过下面的一些示例让我们更好的理解resful api
#GET方法示例
#获取所有用户的信息
HTTP GET https://www.xxx.com/users
#获取用户id为123的用户
HTTP GET https://www.xxx.com/users/123
#POST方法示例,这个示例创建了一个用户
#通过POST方法给服务器提供创建这个用户的所有信息
#需要注意的是url中的users复数
HTTP POST https://www.xxx.com/users
#PUT方法示例,
#更新单个服务器资源:更新用户id为123的资源
HTTP PUT https://www.xxx.com/users/123
#如果要更新一个用户的部分信息,用PATCH更为合适
#DELETE方法示例,
#删除用户id为123的资源
HTTP DELETE https://www.xxx.com/users/123
resful api实例之标准库
go语言很大的一个优势就是很容易开发出网络后台服务,而且性能快、效率高
常见的resful api服务: 处理很多http服务,然后吧处理的消息返回给使用者
下面我们来看一个简单http实现:
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/users",handleUsers)
http.ListenAndServe(":8080",nil)
}
func handleUsers(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w,"ID:1,Name:张三")
fmt.Fprintf(w,"ID:2,Name:李四")
fmt.Fprintf(w,"ID:3,Name:王五")
}
当在浏览器访问 http://127.0.0.1:8080/users 时,可以看到我们可以获取所有的用户信息
但是它并不是resful风格的api,因为我们还可以用POST,PUT,DELETE等所有的方法来获取所有的用户信息
下面我们对代码进行修改,使其符合resful风格的规范
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/users",handleUsers)
http.ListenAndServe(":8080",nil)
}
func handleUsers(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w,"ID:1,Name:张三")
fmt.Fprintf(w,"ID:2,Name:李四")
fmt.Fprintf(w,"ID:3,Name:王五")
default:
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w,"NOT FOUND")
}
}
这时你会发现只有GET才能访问了
在项目中最常见的是使用json格式传输信息,也就是我们提供的resful api要返回json内容给使用者
我们再来改造下代码:
package main
import (
"encoding/json"
"fmt"
"net/http"
)
type User struct {
ID int
Name string
}
//数据源,类似于mysql中的数据
var users = []User{
{ID:1,Name: "张三"},
{ID:2,Name: "李四"},
{ID:3,Name: "王五"},
}
func main() {
http.HandleFunc("/users",handleUsers)
http.ListenAndServe(":8080",nil)
}
func handleUsers(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
users, err:= json.Marshal(users)
if err!=nil{
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w,"{\"message\":\""+err.Error()+"\"}")
}else {
w.WriteHeader(http.StatusOK)
w.Write(users)
}
default:
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w,"{\"message\":\"NOT FOUND\"}")
}
}
此时,再去访问浏览器
resful api实例之开源库-gin
可以看到标准包net/http
非常强大,但是还是有一些不足,如下:
基于以上不足,出现了很多优秀的开源的web框架,比如gin,mux,beego
今天介绍的是使用最多的gin框架
gin框架简介: gin框架是一个在github上开源的web框架,封装了很多web开发需要的通用功能,性能非常高,可以容易的写出性能高效的RESFUL API
使用gin框架需要先下载安装:
go get -u github.com/gin-gonic/gin
然后在go语言代码中导入即可使用
import "github.com/gin-gonic/gin"
gin http demo
package main
import (
"github.com/gin-gonic/gin"
"log"
)
func main() {
//gin.SetMode(gin.ReleaseMode)
router := gin.New()
router.GET("/", index)
log.Println("server is running at http://127.0.0.1:3333")
router.Run(":3333")
}
func index(c *gin.Context) {
//db operation
c.JSON(200, gin.H{
"code": "2000",
"msg": "ok",
"likes": []string{"apple", "pear", "orange"},
})
}
下面就用gin框架重写上面的示例
查询所有用户
package main
import (
"github.com/gin-gonic/gin"
)
type User struct {
ID int
Name string
}
//数据源,类似于mysql中的数据
var users = []User{
{ID:1,Name: "张三"},
{ID:2,Name: "李四"},
{ID:3,Name: "王五"},
}
func main() {
r:= gin.Default()
r.GET("/users",handleUsers)
r.Run(":8080")
}
func handleUsers(c *gin.Context) {
c.JSON(200,users)
}
相对于标准库,gin更加简洁
查询特定用户
现在我们已经掌握了如何使用gin框架创建一个简单的resful api且可返回所有的用户信息,那如何获取特定用户的信息呢?
HTTP GET http://127.0.0.1:8080/users/123
package main
import (
"github.com/gin-gonic/gin"
"strconv"
"strings"
)
type User struct {
ID int
Name string
}
//数据源,类似于mysql中的数据
var users = []User{
{ID:1,Name: "张三"},
{ID:2,Name: "李四"},
{ID:3,Name: "王五"},
}
func main() {
r:= gin.Default()
r.GET("/users/:id",handleUsers)
r.Run(":8080")
}
func handleUsers(c *gin.Context) {
id:=c.Param("id") //注意:param里的参数要和路径里的参数保持一致 =》 "/users/:id"
var user User
found:=false
//模拟数据库的sql查询
for _, u:= range users{
if strings.EqualFold(id,strconv.Itoa(u.ID)){
user = u
found = true
break
}
}
if found{
c.JSON(200,user)
}else {
c.JSON(404,gin.H{
"message":"用户不存在",
})
}
}
运行,并用浏览器打开:
再访问一个不存在的id
新增一个用户
根据resful api规范,实现新增使用的是POST方法
并且URL的格式为:http://127.0.0.1:8080/users
向URL发送数据,即可新增一个用户,然后返回创建的用户信息
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
type User struct {
ID int
Name string
}
//数据源,类似于mysql中的数据
var users = []User{
{ID:1,Name: "张三"},
{ID:2,Name: "李四"},
{ID:3,Name: "王五"},
}
func main() {
r:= gin.Default()
r.POST("/users",createUser)
r.Run(":8080")
}
func createUser(c *gin.Context) {
name:=c.DefaultPostForm("name","")
if name!=""{
u:=User{
ID: len(users)+1,
Name: name,
}
users = append(users,u)
c.JSON(http.StatusCreated,u)
}else {
c.JSON(http.StatusOK,gin.H{
"message":"请输入用户名称",
})
}
}
启动服务,然后通过terminal发送POST请求
curl -X POST -d 'name=scott' http://127.0.0.1:8080/users
练习
在做项目时,会有增删改查,现在已经有了增查,还差改删,想一想如何实现下面的功能:
- 1,修改一个用户的名字
- 2,删除一个用户
总结
go语言已经提供了比较强大的SDK,可以很容易的开发网络服务的应用,而借助第三方的web框架可让这件事情更容易、更高效
在做项目开发的时候,要善于借助已有的轮子,不要重复造轮子