文章收藏在回车教室
序言在学习RESTful 风格接口之前,纵然你不知道它是什么,但你肯定会好奇它能办理什么问题?有什么运用处景?听完下面描述我想你就会明白:
在互联网并没有完备盛行的初期,移动端也没有那么盛行,页面要乞降并发量也不高,那时候人们对接口的哀求没那么高,一些动态页面(jsp)就能知足绝大多数的利用需求。
但是随着互联网和移动设备的发展,人们对Web运用的利用需求也增加,传统的动态页面由于低效率而逐渐被HTML+JavaScript(Ajax)的前后端分离所取代,并且安卓、IOS、小程序等形式客户端层出不穷,客户真个种类涌现多元化,而客户端和做事端就须要接口进行通信,但接口的规范性就又成了一个问题:
以是一套构造清晰、符合标准、易于理解、扩展方便让大部分人都能够理解接管的接口风格就显得越来越主要,而RESTful风格的接口(RESTful API)刚好有以上特点,就逐渐被实践运用而变得盛行起来。
现在,RESTful是目前最盛行的接口设计规范,在很多公司有着广泛的运用,个中Github 的API设计便是很标准的RESTful API,你可以参考学习。
在开拓实践中我们很多人可能还是利用传统API进行要求交互,很多人实在并不特殊理解RESTful API,对RESTful API的认知可能会勾留在:
面向资源类型的是一种风格(误区)接口传递参数利用斜杠(/)分割而不用问号(?)传参。而实在一个很大的误区不要认为没有查询字符串便是RESTful API,也不要认为用了查询字符串就不是RESTful API,更不要认为用了JSON传输的API便是RESTful API。
本教程将带你理解RESTful并用SpringBoot实战RESTful API,在实现本案例前,你须要担保你的电脑上
拥有IDEA用来编写项目代码拥有Postman仿照要求进行测试拥有关系数据库MySQL 5.7拥有navicat对MySQL进行管理一、REST先容REST涉及一些观点性的东西可能比较多,在实战RESTful API之前,要对REST干系的知识有个别系的认知。
REST的出身REST(英文:Representational State Transfer,简称REST,直译过来表现层状态转换)是一种软件架构风格、设计风格,而不是标准,只是供应了一组设计原则和约束条件。它紧张用于客户端和做事器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
它首次涌如今 2000 年 Roy Thomas Fielding 的博士论文中,这篇论定亲义并详细先容了表述性状态转移(Representational State Transfer,REST)的架构风格,并且描述了 如何利用 REST 来辅导当代 Web 架构的设计和开拓。用他自己的原话说:
我写这篇文章的目的是:在符合架构事理条件下,理解和评估基于网络的运用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。
须要把稳的是REST并没有一个明确的标准,而更像是一种设计的风格,知足这种设计风格的程序或接口我们称之为RESTful(从单词字面来看便是一个形容词)。以是RESTful API 便是知足REST架构风格的接口。
Fielding博士当时提出的是REST架构在良久的韶光内并没有被关注太多,而近些年REST在海内才变得越来越盛行。下面开始详细学习REST架构特色。
REST架构特色既然知道REST和RESTful的联系和差异,现在就要开始好好理解RESTful的一些约束条件和规则,RESTful是一种风格而不是标准,而这个风格大致有以下几个紧张特色:
以资源为根本 :资源可以是一个图片、音乐、一个XML格式、HTML格式或者JSON格式等网络上的一个实体,除了一些二进制的资源外普通的文本资源更多以JSON为载体、面向用户的一组数据(常日从数据库中查询而得到)。统一接口: 对资源的操作包括获取、创建、修正和删除,这些操作恰好对应HTTP协议供应的GET、POST、PUT和DELETE方法。换言而知,利用RESTful风格的接口但从接口上你可能只能定位其资源,但是无法知晓它详细进行了什么操作,须要详细理解其发生了什么操作动作要从其HTTP要求方法类型上进行判断。详细的HTTP方法和方法含义如下:
GET(SELECT):从做事器取出资源(一项或多项)。POST(CREATE):在做事器新建一个资源。PUT(UPDATE):在做事器更新资源(客户端供应完全资源数据)。PATCH(UPDATE):在做事器更新资源(客户端供应须要修正的资源数据)。DELETE(DELETE):从做事器删除资源。当然也有很多在详细利用的时候利用PUT表示更新。从要求的流程来看,RESTful API和传统API大致架构如下:
URI指向资源:URI = Universal Resource Identifier 统一资源标志符,用来标识抽象或物理资源的一个紧凑字符串。URI包括URL和URN,在这里更多时候可能代指URL(统一资源定位符)。RESTful是面向资源的,每种资源可能由一个或多个URI对应,但一个URI只指向一种资源。
无状态:做事器不能保存客户真个信息, 每一次从客户端发送的要求中,要包含所有必须的状态信息,会话信息由客户端保存, 做事器端根据这些状态信息来处理要求。 当客户端可以切换到一个新状态的时候发送要求信息, 当一个或者多个要求被发送之后, 客户端就处于一个状态变迁过程中。 每一个运用的状态描述可以被客户端用来初始化下一次的状态变迁。
REST架构限定条件Fielding在论文中提出REST架构的6个限定条件,也可称为RESTful 6大原则, 标准的REST约束应知足以下6个原则:
客户端-做事端(Client-Server): 这个更专注客户端和做事真个分离,做事端独立可更好做事于前端、安卓、IOS等客户端设备。
无状态(Stateless):做事端不保存客户端状态,客户端保存状态信息每次要求携带状态信息。
可缓存性(Cacheability) :做事端需回答是否可以缓存以让客户端甄别是否缓存提高效率。
统一接口(Uniform Interface):通过一定原则设计接口降落耦合,简化系统架构,这是RESTful设计的基本出发点。当然这个内容除了上述特点提到部分详细内容比较多详细理解可以参考这篇REST论文内容。
分层系统(Layered System):客户端无法直接知道连接的到终端还是中间设备,分层许可你灵巧的支配做事端项目。
按需代码(Code-On-Demand,可选):按需代码许可我们灵巧的发送一些看似分外的代码给客户端例如JavaScript代码。
REST架构的一些风格和限定条件就先先容到这里,后面就对RESTful风格API详细先容。
二、RESTful API设计规范既然理解了RESTful的一些规则和特性,那么详细该怎么去设计一个RESTful API呢?要从URL路径、HTTP要求动词、状态码和返回结果等方面详细考虑。至于其他的方面例如缺点处理、过滤信息等规范这里就不详细先容了。
URL设计规范URL为统一资源定位器 ,接口属于做事端资源,首先要通过URL这个定位到资源才能去访问,而常日一个完全的URL组成由以下几个部分构成:
URI=scheme"://"host":"port"/"path["?"query]["#"fragment]
scheme: 指底层用的协议,如http、https、ftphost: 做事器的IP地址或者域名port: 端口,http默认为80端口path: 访问资源的路径,便是各种web 框架中定义的route路由query: 查询字符串,为发送给做事器的参数,在这里更多发送数据分页、排序等参数。fragment: 锚点,定位到页面的资源
我们在设计API时URL的path是须要负责考虑的,而RESTful对path的设计做了一些规范,常日一个RESTful API的path组成如下:
/{version}/{resources}/{resource_id}
version:API版本号,有些版本号放置在头信息中也可以,通过掌握版本号有利于运用迭代。resources:资源,RESTful API推举用小写英文单词的复数形式。resource_id:资源的id,访问或操作该资源。
当然,有时候可能资源级别较大,其下还可细分很多子资源也可以灵巧设计URL的path,例如:
/{version}/{resources}/{resource_id}/{subresources}/{subresource_id}
此外,有时可能增编削查无法知足业务哀求,可以在URL末端加上action,例如
/{version}/{resources}/{resource_id}/action
个中action便是对资源的操作。
从大体样式理解URL路径组成之后,对付RESTful API的URL详细设计的规范如下:
不用大写字母,所有单词利用英文且小写。连字符用中杠"-"而不用下杠"_"精确利用 "/"表示层级关系,URL的层级不要过深,并且越靠前的层级该当相对越稳定结尾不要包含正斜杠分隔符"/"URL中不涌现动词,用要求办法表示动作资源表示用复数不要用单数不要利用文件扩展名HTTP动词在RESTful API中,不同的HTTP要求方法有各自的含义,这里就展示GET,POST,PUT,DELETE几种要求API的设计与含义剖析。针对不同操作,详细的含义如下:
GET/collection:从做事器查询资源的列表(数组)GET/collection/resource:从做事器查询单个资源POST/collection:在做事器创建新的资源PUT/collection/resource:更新做事器资源DELETE/collection/resource:从做事器删除资源
在非RESTful风格的API中,我们常日利用GET要乞降POST要求完成增编削查以及其他操作,查询和删除一样平常利用GET办法要求,更新和插入一样平常利用POST要求。从要求办法上无法知道API详细是干嘛的,所有在URL上都会有操作的动词来表示API进行的动作,例如:query,add,update,delete等等。
而RESTful风格的API则哀求在URL上都以名词的办法涌现,从几种要求办法上就可以看出想要进行的操作,这点与非RESTful风格的API形成光鲜比拟。
在谈及GET,POST,PUT,DELETE的时候,就必须提一下接口的安全性和幂等性,个中安全性是指方法不会修正资源状态,即读的为安全的,写的操作为非安全的。而幂等性的意思是操作一次和操作多次的终极效果相同,客户端重复调用也只返回同一个结果。
上述四个HTTP要求方法的安全性和幂等性如下:
状态码和返回数据做事端处理完成后客户端也可能不知道详细成功了还是失落败了,做事器相应时,包含状态码和返回数据两个部分。
状态码
我们首先要精确利用各种状态码来表示该要求的处理实行结果。状态码紧张分为五大类:
1xx:干系信息2xx:操作成功3xx:重定向4xx:客户端缺点5xx:做事器缺点
每一大类有多少小类,状态码的种类比较多,而紧张常用状态码罗列不才面:
200 OK - [GET]:做事器成功返回用户要求的数据,该操作是幂等的(Idempotent)。201 CREATED - [POST/PUT/PATCH]:用户新建或修正数据成功。202 Accepted - []:表示一个要求已经进入后台排队(异步任务)204 NO CONTENT - [DELETE]:用户删除数据成功。400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的要求有缺点,做事器没有进行新建或修正数据的操作,该操作是幂等的。401 Unauthorized - []:表示用户没有权限(令牌、用户名、密码缺点)。403 Forbidden - [] 表示用户得到授权(与401缺点相对),但是访问是被禁止的。404 NOT FOUND - []:用户发出的要求针对的是不存在的记录,做事器没有进行操作,该操作是幂等的。406 Not Acceptable - [GET]:用户要求的格式不可得(比如用户要求JSON格式,但是只有XML格式)。410 Gone -[GET]:用户要求的资源被永久删除,且不会再得到的。422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个工具时,发生一个验证缺点。500 INTERNAL SERVER ERROR - []:做事器发生缺点,用户将无法判断发出的要求是否成功。
返回结果
针对不同操作,做事器向用户返回数据,而各个团队或公司封装的返回实体类也不同,但都返回JSON格式数据给客户端。
第三关 一个RESTful API案例上面讲了RESTful理论知识,下面动手实现一个小案例吧!
在本案例的实战中,我们访问的RESTful接口都是对数据库真实的操作,新建数据库,创建一个数据库和表(根据自己喜好)。
选择Maven依赖的时候,只须要勾选个中Spring的Web模块、MySQL驱动以及MyBatis框架。
本案例的POJO创建Dog.java实体工具,其详细布局为:
packagecom.restfuldemo.pojo;publicclassDog{privateintid;//唯一id标识privateStringname;//名称privateintage;//年事//省略getset}
上面创建好了项目,我们就开始构建RESTful风格的API。在详细构建RESTful API的时候,须要对各种要求有更细致的认知,当然,本案例在实现各种要求的时候为了演示的便捷并没有完备遵照RESTful API规范,例如版本号等信息这里就不添加了,案例更侧重于利用SpringBoot实现这个接口。
本案例实现对dog资源的增编削查,如下是非RESTful 和RESTful接口比拟:
其余在利用postman进行发送要求的时候,有三种常用的文件类型通报到后端:
form-data : 便是form表单中的multipart/form-data,会将表单数据处理为一条信息,用特定标签符将一条条信息分割开,而这个文件类型常日用来上传二进制文件。
x-www-form-urlencoded:便是application/x-www-form-urlencoded,是form表单默认的encType,form表单会将表单内的数据转换为键值对,这种格式不能上传文件。
raw:可以上传任意格式的文本,可以上传Text,JSON,XML等,但目前大部分还是上传JSON格式数据。当后端须要吸收JSON格式数据处理的时候,可以采取这种格式来测试。
由于GET要求查询参数在URL上,其他类型要求利用x-www-form-urlencoded办法向后端传值。
GET POST PUT DELETE要求GET要求用来获取资源:GET要求会向数据库发索取数据的要求,从而来获取资源,该要求就像数据库的select操作一样,只是用来查询数据,不会影响资源的内容。无论进行多少次操作,结果都是一样的。
并且GET要求会把要求的参数附加在URL后面,但是不同的浏览器对其有不同的大小长度限定。
在本案例中,我们设计两个GET要求的API。GET /dogs :用来返回dog资源的列表。GET /dogs/{dogid} :用来查询此id的单个dog资源。
POST要求用来新增一个资源 : POST要求向做事器发送数据,但是该要求会改变数据的内容(新添),就像数据库的insert操作一样,会创建新的内容。且POST要求的要求参数都是要求体中,其大小是没有限定的。
在本案例中,我们设计以下POST要求的API。POST /dogs :做事端新增一个dog资源。
PUT要求用来更新资源,PUT要求是向做事器端发送数据的, 与POST要求不同的是,PUT要求侧重于数据的修正 ,就像数据库中update一样,而POST要求侧重于数据的增加。
在本案例中,我们设计以下POST要求的API。PUT /dogs/{dogid} :用来更新此id的单个dog资源。
DELETE 要求用来删除资源,DELETE要求用场和它字面意思同等,用来删除资源。和数据库中delete相对应。
在本案例中,我们设计以下DELETE要求的API。DELETE /dogs/{dogid} :用来删除此id的单个dog资源。
对应的Mapper文件为:
packagecom.restfuldemo.mapper;importcom.restfuldemo.pojo.Dog;importorg.apache.ibatis.annotations.;importjava.util.List;@MapperpublicinterfaceDogMapper{@Select("selectfromdog")List<Dog>getAllDog();@Select("selectfromdogwhereid=#{id}")DoggetDogById(@Param("id")intid);@Insert("insertintodog(name,age)values(#{name},#{age})")booleanaddDog(Dogdog);@Update("updatedogsetname=#{name},age=#{age}whereid=#{id}")booleanupdateDog(Dogdog);@Delete("deletefromdogwhereid=#{id}")booleandeleteDogById(intid);}
对应controller文件为:
packagecom.restfuldemo.controller;importcom.restfuldemo.mapper.DogMapper;importcom.restfuldemo.pojo.Dog;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.;importjava.util.Arrays;importjava.util.List;@RestControllerpublicclassTestController{@Autowired(required=false)DogMapperdogMapper;@GetMapping("dogs")publicList<Dog>getDogs(){returndogMapper.getAllDog();}@GetMapping("dogs/{id}")publicDoggetDogById(@PathVariable("id")intid){Dogdog=dogMapper.getDogById(id);returndog;}@PostMapping("dogs")publicbooleanaddDog(Dogdog){returndogMapper.addDog(dog);}@PutMapping("dogs/{id}")publicbooleanupdateDog(@PathVariable("id")intid,@RequestParam("name")Stringname,@RequestParam("age")intage){Dogdog=dogMapper.getDogById(id);dog.setName(name);dog.setAge(age);returndogMapper.updateDog(dog);}@DeleteMapping("dogs/{id}")publicbooleandeleteDog(@PathVariable("id")intid){returndogMapper.deleteDogById(id);}}
经由笔者测试统统都是ok的,如果要项目源文件请联系笔者发你哈!
RESTful风格的API 固然很好很规范,但大多数互联网公司并没有按照或者完备按照其规则来设计,由于REST是一种风格,而不是一种约束或规则,过于空想的RESTful API 会付出太多的本钱。
比如RESTful API也有一些缺陷
比如操作办法繁琐,RESTful API常日根据GET、POST、PUT、DELETE 来区分操作资源的动作,而HTTP Method 本身不可直接见,是隐蔽的,而如果将动作放到URL的path上反而清晰可见,更利于团队的理解和互换。并且有些浏览器对GET,POST之外的要求支持不太友好,还须要分外额外的处理。过分强调资源,而实际业务API可能有各种需求比较繁芜,单单利用资源的增编削查可能并不能有效知足利用需求,强行利用RESTful风格API只会增加开拓难度和本钱。以是,当你或你们的技能团队在设计API的时候,如果利用场景和REST风格很匹配,那么你们可以采取RESTful 风格API。但是如果业务需求和RESTful风格API不太匹配或者很麻烦,那也可以不用RESTful风格API或者可以借鉴一下,毕竟无论那种风格的API都是为了方便团队开拓、协商以及管理,不能墨守成规。
到这里RESTful API的先容和实战就结束啦,本篇首先从RESTful的一些特点进行先容,再到SpringBoot实战RESTful API,末了也说了一些RESTful API并不完美的地方,相信睿智的你对RESTful 一定有了很深刻的理解。在往后项目的API设计上定能有所优化。
不同的人对RESTful API可能有着不同的理解,但存在即合理,RESTful API有着其光鲜的上风和特点,目前也是一种API设计的紧张选型之一,以是节制和理解RESTful API还是相称主要的!
到这里,感谢大家的不雅观看,也希望头条的朋友们能够给个关注、点赞、和评论转发,毕竟原创不易,您切实其实定才是我坚持下去的动力!
公众号:bigsai 头条号:程序员bigsai