RESTful API系列 - RESTful API是什么以及其设计要点

简介: 目录REST API是什么?No.1 数据跟界面解耦合No.2 无状态No.3 可缓存No.4 统一接口/标准化接口No.5 分层次系统风格No.6 按需编码(可选)

REST API是什么?

REST中文意思是REpresentational(代表性的)State(状态)Transfer(传输),比较拗口,这个概念是Roy fielding提出的一种应用在分布式系统的架构风格。


很多时候不小心写错了,我们会看到Restful API,碰到这样写法,严格说是错误的。


简单理解,RESTful API就是尽量满足以下六个设计原则来进行实现的接口,它们是:


数据跟界面解耦

无状态

可缓存

统一接口/标准化接口

分层次系统风格

按需编码(可选)

这么多个原则,换个简化的说法,即是,更清晰更标准化更易扩展的接口。


还是很抽象的感觉?


下面举几个例子一一阐述这些原则。


No.1 数据跟界面解耦合

这个很好理解,接口要朝着提供视图需要的数据的方向来设计,定制。


比如我们在做查询用户接口数据/api/user/001的响应时,应该仅仅返回一个用户的json数据

{
  "name":"levin",
  "photo":"baidu.com/ll/png234u1o343.png"
}

视图代码如下(以web页面为例子,界面代码通常是一些标签包围起来的代码块)

<div>
    <div>Name:<span>{{name}}</span></div>
    <div>Photo:<img src="{{photo}}"/></div>
</div>

而不是设计一个接口直接生成(当然这个原则并不能阻止部分程序员直接生成带数据的视图,最好不要这样做,让数据和界面分开可以有更高复用性)

<div>
   <div>Name:<span>levin</div>
   <div>Photo:<img src="baidu.com/ll/png234u1o343.png"/></div>
</div>

No.2 无状态

首先,无状态就是请求这个接口的时候,处理该请求的服务在未获取数据时,该服务是没有地方存储待获取的数据的。

举个例子,还是/api/user/001 这个接口,背后的伪代码可以如下:

let dataService = new DistributedDataService()
@Get("/api/user/{id}")
function getUser(id){
  return dataService.queryUser(id)
}

这个接口的实现调用了dataService去查询用户编号是001的信息。

服务本身是没有存储任何状态的,数据可以从数据库或者缓存中获取,这就是保证服务的无状态。

什么情况是有状态呢?

举个例子,伪代码如下:

//local data cache    
let dataService = LocalDataService()
@Get("/api/user/{id}")
function getUser(id){
    return dataService.queryUser(id)
}
@Delete("/api/user/{id}")
function getUser(id){
    return dataService.deleteUser(id)
}

这里使用的dataService是LocalDataService(本地的数据服务),通常单进程运行是没有任何问题的。因为无论如何操作,只要LocalDataService支持线程安全(这个需要开新的一篇来讲),它的状态严格上说不会有问题。


但在分布式系统中,普遍做法是部署多个服务器多实例,而且他们同时提供/api/user/001接口的服务。


这时候问题就来了,每个服务进程都拥有一个localDataService。


当调用来DELETE /api/user/001,只有一个服务的localDataService状态更改了(少了001用户)。


其他实例的本地数据仍有001用户,下一次查询的结果会有两种,一种结果是返回用户没找到,另一个结果是返回001用户,这就跟我们预期的不一致,导致了业务错误。


No.3 可缓存

应用缓存是一种提高性能的手段。这里官方也没有特别说明,其实符合普遍对资源的缓存的理解。


针对某个接口,可以设置请求头Cache-Control, 可以是no-cache 或者max-age= 60 (某个数值)去告诉接口请求方可以缓存该接口数据多久。


举个例子,我们进入百度搜索RFC 7234(http协议关于缓存的标准)可以看到“消息头”里面关于缓存的设置,百度把一些不经常变化的资源标记了很大值,告诉火狐浏览器,下次不需要重新下载该资源。


https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/soutu/js/tu_68114f1.js


image.png

刷新页面,我们可以拿上面缓存的url进行搜索,这里显示已经缓存了。

image.png

No.4 统一接口/标准化接口

官网提了,接口定义需要满足4个约束:资源标示、通过呈现方式来操作资源、资源自描述、以及使用超媒体作为应用状态。


举个例子,像设计 /api/user/ 这个接口,如何符合第四原则满足统一标准化接口?


首先,/api/user 这个uri定位了用户资源相关的信息操作,然后可以用GET来查询用户信息,DELETE来删除用户信息。


再说资源自描述,我们查询 /api/user/1001, 获得一下响应消息:

{
   "id":"1001",
   "name":"levin",
   "country": "China"
} 

像这样的就是资源自描述,这个响应告诉了我们用户信息的属性,结构。我们查询其他人像小明,也是获取类似的反馈。


至于超媒体作为应用状态,这个不需要多说,简单理解为多种格式的响应消息作为状态即可。


这个设计原则,更多约束目标系统的REST API更加容易操作,可见可读性。


No.5 分层次系统风格

这里就是架构的分层,每层内的组件不允许看到与其不直接交互的层,也就是说,非直接交互的层对当前层内的组件不可访问。


image.png

比如上图,A <->B<->C,三层架构中,AB紧邻,BC紧邻,这样分层避免了AC直接交流,A层的变动不会对C层造成影响。


这样设计可以更好的让层与层之间互相解耦,让每一层专注做单层的功能(当然分层数过多也有坏处)。


No.6 按需编码(可选)

服务器可以提供一些代码或者脚本并在客户的运行环境中执行, 比如一些JS脚本供客户端下载调用。


像过去Java服务器端可以生成Applet脚本供客户端执行。


说到这里跟按需编码(CodeOnDemand), 好像表达的意思不太贴切,我们只需要明白这个设计原则是为了提高客户端的扩展性即可。



上面说那么多,其实RESTful API本质是通过走HTTP协议来呈现接口。


通过uri为系统交互的接口,比直接代码调用代码更加简化,而且脱离了语言约束。


更多细节参考:


https://restfulapi.net/


https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control


https://www.rfc-editor.org/info/rfc7234


https://www.rfc-editor.org/rfc/inline-errata/rfc2616.html


目录
相关文章
|
3天前
|
安全 Java API
RESTful API设计与实现:Java后台开发指南
【4月更文挑战第15天】本文介绍了如何使用Java开发RESTful API,重点是Spring Boot框架和Spring MVC。遵循无状态、统一接口、资源标识和JSON数据格式的设计原则,通过创建控制器处理HTTP请求,如示例中的用户管理操作。此外,文章还提及数据绑定、验证、异常处理和跨域支持。最后,提出了版本控制、安全性、文档测试以及限流和缓存的最佳实践,以确保API的稳定、安全和高效。
|
15天前
|
前端开发 Java API
构建RESTful API:Java中的RESTful服务开发
【4月更文挑战第3天】本文介绍了在Java环境中构建RESTful API的重要性及方法。遵循REST原则,利用HTTP方法处理资源,实现CRUD操作。在Java中,常用框架如Spring MVC简化了RESTful服务开发,包括定义资源、设计表示层、实现CRUD、考虑安全性、文档和测试。通过Spring MVC示例展示了创建RESTful服务的步骤,强调了其在现代Web服务开发中的关键角色,有助于提升互操作性和用户体验。
构建RESTful API:Java中的RESTful服务开发
|
19天前
|
XML JSON 安全
谈谈你对RESTful API设计的理解和实践。
RESTful API是基于HTTP协议的接口设计,通过URI标识资源,利用GET、POST、PUT、DELETE等方法操作资源。设计注重无状态、一致性、分层、错误处理、版本控制、文档、安全和测试,确保易用、可扩展和安全。例如,`/users/{id}`用于用户管理,使用JSON或XML交换数据,提升系统互操作性和可维护性。
14 4
|
28天前
|
缓存 前端开发 API
构建高效可扩展的RESTful API:后端开发的最佳实践
【2月更文挑战第30天】 在现代Web应用和服务端架构中,RESTful API已成为连接前端与后端、实现服务间通信的重要接口。本文将探讨构建一个高效且可扩展的RESTful API的关键步骤和最佳实践,包括设计原则、性能优化、安全性考虑以及错误处理机制。通过这些实践,开发者可以确保API的健壮性、易用性和未来的可维护性。
|
29天前
|
API 开发者 UED
深入探讨RESTful API设计原则及最佳实践
在当今互联网时代,RESTful API已成为各种软件系统之间进行通信的重要方式。本文将从资源定义、URI设计、HTTP方法选择、状态码规范等方面深入探讨RESTful API设计的原则与最佳实践,帮助开发者更好地构建高效、健壮的API。
|
30天前
|
JSON Java API
Springboot项目中如何设计一个规范的统一的Restful API 响应框架?
Springboot项目中如何设计一个规范的统一的Restful API 响应框架?
22 1
|
1月前
|
XML JSON API
通过Flask框架创建灵活的、可扩展的Web Restful API服务
通过Flask框架创建灵活的、可扩展的Web Restful API服务
|
1月前
|
JSON API 数据库
解释如何在 Python 中实现 Web 服务(RESTful API)。
解释如何在 Python 中实现 Web 服务(RESTful API)。
23 0
|
1月前
|
缓存 安全 测试技术
构建高效的RESTful API:后端开发的实践指南
【2月更文挑战第17天】在数字化转型的浪潮中,RESTful API已成为连接不同软件组件、实现数据交互的核心桥梁。本文将深入探讨如何构建一个高效、可扩展且安全的RESTful API,涉及设计原则、开发流程以及性能优化等关键方面。我们将透过实际案例,展示如何在保证简洁性和灵活性的同时,满足日益增长的业务需求和技术挑战。
|
2月前
|
IDE Java API
使用Java Web技术构建RESTful API的实践指南
使用Java Web技术构建RESTful API的实践指南