RESTful 架构之RESTful API详解

什么是REST

REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移。 它首次出现在2000年Roy Fielding的博士论文中,Roy Fielding是HTTP规范的主要编写者之一。 他在论文中提到:“我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。REST指的是一组架构约束条件和原则。” 如果一个架构符合REST的约束条件和原则,我们就称它为RESTful架构。

REST本身并没有创造新的技术、组件或服务,而隐藏在RESTful背后的理念就是使用Web的现有特征和能力, 更好地使用现有Web标准中的一些准则和约束。虽然REST本身受Web技术的影响很深, 但是理论上REST架构风格并不是绑定在HTTP上,只不过目前HTTP是唯一与REST相关的实例。 所以我们这里描述的REST也是通过HTTP实现的REST。

产生背景

近年来移动互联网的发展,前端设备层出不穷(手机、平板、桌面电脑、其他专用设备…),因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信,于是RESTful诞生了,它可以通过一套统一的接口为 Web,iOS和Android提供服务。

URL设计

GET:读取(Read)
POST:新建(Create)
PUT:更新(Update)
PATCH:更新(Update),通常是部分更新
DELETE:删除(Delete)
在这里插入图片描述
以下是一个例子

@RestController 
@RequestMapping(value="/users")     // 通过这里配置使下面的映射都在/users下 
public class UserController { 
 
    // 创建线程安全的Map 
    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>()); 
 
    @RequestMapping(value="/", method=RequestMethod.GET) 
    public List<User> getUserList() { 
        // 处理"/users/"的GET请求,用来获取用户列表 
        // 还可以通过@RequestParam从页面中传递参数来进行查询条件或者翻页信息的传递 
        List<User> r = new ArrayList<User>(users.values()); 
        return r; 
    } 
 
    @RequestMapping(value="/", method=RequestMethod.POST) 
    public String postUser(@ModelAttribute User user) { 
        // 处理"/users/"的POST请求,用来创建User 
        // 除了@ModelAttribute绑定参数之外,还可以通过@RequestParam从页面中传递参数 
        users.put(user.getId(), user); 
        return "success"; 
    } 
 
    @RequestMapping(value="/{id}", method=RequestMethod.GET) 
    public User getUser(@PathVariable Long id) { 
        // 处理"/users/{id}"的GET请求,用来获取url中id值的User信息 
        // url中的id可通过@PathVariable绑定到函数的参数中 
        return users.get(id); 
    } 
 
    @RequestMapping(value="/{id}", method=RequestMethod.PUT) 
    public String putUser(@PathVariable Long id, @ModelAttribute User user) { 
        // 处理"/users/{id}"的PUT请求,用来更新User信息 
        User u = users.get(id); 
        u.setName(user.getName()); 
        u.setAge(user.getAge()); 
        users.put(id, u); 
        return "success"; 
    } 
 
    @RequestMapping(value="/{id}", method=RequestMethod.DELETE) 
    public String deleteUser(@PathVariable Long id) { 
        // 处理"/users/{id}"的DELETE请求,用来删除User 
        users.remove(id); 
        return "success"; 
    } 
 
}

状态码

在这里插入图片描述
在这里插入图片描述

服务器回应

API 返回的数据格式,不应该是纯文本,而应该是一个 JSON 对象,因为这样才能返回标准的结构化数据。所以,服务器回应的 HTTP 头的Content-Type属性要设为application/json。

客户端请求时,也要明确告诉服务器,可以接受 JSON 格式,即请求的 HTTP 头的ACCEPT属性也要设成application/json。下面是一个例子。

GET /orders/2 HTTP/1.1 
Accept: application/json

版本控制

第一种,强制使用统一API版本

整个项目使用一个API版本,不考虑兼容性,缺点

第二种,URI中显式添加版本号

把版本号嵌入到API中,例如developer.github.com/v3/media/,
访问操作对应版本号下的资源。这种显示的表示版本号的好处是可以很直观的
展示当前api版本号。缺点是违背RESTful架构的原则,理论上一个URI对应服
务器一个特定的资源,添加版本号则会混淆版本和资源的概念,而且会让整个
架构变得混乱,增加日后维护的成本。 还有一种是把版本号作为参数请求api
获取操作对应版本号的资源,例如www.demo.com/list?version=2。

第三种,添加头信息控制版本

在API请求header中添加Accept字段。
Accept的作用是客户端指出响应可以接受的媒体类型
如Accept:application/json; version=v2
具体格式也可以参考下面。

Accept: application/vnd.xxxx[.version].param[+json]
1
例如Accept: application/vnd.demo.app-v2+json
优点:遵循了REST的原则
缺点:不够直观

版本总结
通过上述简单的分析,每种版本控制都有不同的优缺点,我们可以选择合适自己的版本控制方式,个人认为小版本的更新可通过把版本号作为参数的方式或者通过accept字段标示版本号的方式判断,大的版本更新则通过URL上添加版本号控制

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

网络安全王家楠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值