REST,以及RESTful的讲解

<div class="blog-content-box">
    <div class="article-header-box">
        <div class="article-header">
            <div class="article-title-box">
                <span class="article-type type-1 float-left">原</span>                <h1 class="title-article">REST,以及RESTful的讲解</h1>
            </div>
            <div class="article-info-box">
                <div class="article-bar-top" style="height: 24px;">
                                                                                                                                            <span class="time">2018年04月21日 18:59:08</span>
                    <a class="follow-nickName" href="https://me.csdn.net/qq_21383435" target="_blank">九师兄-梁川川</a>
                    <span class="read-count">阅读数 86441</span><span class="article_info_click" style="position: static;">更多</span>
                                                                                                <div class="tags-box space">
                                <span class="label">个人分类:</span>
                                                                <a class="tag-link" href="https://blog.csdn.net/qq_21383435/article/category/7403173" target="_blank">协议                                                                    </a>
                            </div>
                                                                                    </div>
                <div class="operating">
                                    </div>
            </div>
        </div>
    </div>
    <article class="baidu_pl">
                <div id="article_content" class="article_content clearfix">
                                                <div class="article-copyright">
                <span class="creativecommons">
                <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
                    </a>
            <span>版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank"> CC 4.0 by-sa </a>版权协议,转载请附上原文出处链接和本声明。 </span>
               <div class="article-source-link2222">
                    本文链接:<a href="https://blog.csdn.net/qq_21383435/article/details/80032375">https://blog.csdn.net/qq_21383435/article/details/80032375</a>
                </div>
            </span>
                    </div>
                                                    <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css">
                                        <div id="content_views" class="markdown_views">
                    <!-- flowchart 箭头图标 勿删 -->
                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                    </svg>
                                            <p></p><div class="toc">
<ul>
<li><a href="#1传统下的api接口" rel="nofollow" data-token="5c26c15a690be328ae1672230be30d89" target="_self">1.传统下的API接口</a></li>
<li><a href="#对比" rel="nofollow" data-token="46807bfdce4a935fe1e337b53bda2d12" target="_self">对比</a></li>
<li><a href="#规则" rel="nofollow" data-token="20ac766e21e3aafda83428c47f20bd54" target="_self">规则</a></li>
<li><a href="#概念" rel="nofollow" data-token="89e0c573e07298aa610fd39c2910d24b" target="_self">概念</a></li>
<li><a href="#rest-系统的特征" rel="nofollow" data-token="55ca30bd85e79c0ad5e887be104c6993" target="_self">REST 系统的特征</a></li>
<li><a href="#演化" rel="nofollow" data-token="579230ac70e4658c946d98dc804590fe" target="_self">演化</a></li>
<li><a href="#优点缺点" rel="nofollow" data-token="9e6b648483cb76ff7dc4f94ec0faa25b" target="_self">优点&amp;缺点</a></li>
<li><a href="#是什么" rel="nofollow" data-token="cfe659be62ad85d2de46bc69ecb61483" target="_self">是什么?</a></li>
</ul>
</div>
<p></p>

<h1 id="1传统下的api接口"><a name="t0"></a>1.传统下的API接口</h1>

<p>  http是目前在互联网上使用最多的协议,没有之一。 <br>
  可是http的创始人一直都觉得,在过去10几年来,所有的人都在错误的使用Http.这句话怎么说呢? <br>
  如果说你要删除一个数据,以往的做法通常是 <code>delete/{id}</code>  <br>
  如果你要更新一个数据,可能是Post数据放Body,然后方法是 <code>update/{id}</code>, 或者是artichle/{id}?method=update  <br>
   <code>这种做法让Roy Fielding很暴燥,他觉得这个世界不该这样的,所有的人都在误解而且在严重错误的误解Http的设计初衷,好比是发明了火药却只用它来做烟花爆竹</code>。 <br>
   那么正确的使用方式是什么呢?如果你要看Rest各种特性,你恐怕真的很难理解Rest,<code>但是如果你看错误的使用http的人倒底儿了哪些错,什么是Rest就特别容易理解了</code>。  <br>
    <br>
<strong>七宗罪的第一条,混乱</strong>。  </p>

<p>   一万个人心里有一万个Url的命名规则,Url是统一资源定位符,重点是资源。而很多人却把它当成了万金油,每一个独立的虚拟的网页都可以随意使用,各种操作都能够迭加。这是混乱的来源之一。 <br>
比如:</p>

<pre class="prettyprint" name="code"><code class="hljs cs has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">https:<span class="hljs-comment">//localhost:8080/myweb/getUserById?id=1</span>
https:<span class="hljs-comment">//localhost:8080/myweb/user/getById?id=1</span>
https:<span class="hljs-comment">//localhost:8080/myweb/x/y?id=1</span><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li></ul></pre>

<p><strong>第二条,贪婪。</strong> </p>

<p>  <code>有状态</code>和<code>无状态</code>全部<code>混在一起</code>。特别是在购物车或者是登录的应用中,经常刷新就丢失带来的用户体验简直棒棒哒。每一个请求并不能单独的响应一些功能,很多的功能混杂在一起里。这是人性贪婪的本质,也是各种<code>Hack</code>的起源,只要能够把问题解决掉,总会有人用他认为最方便的方式去解决问题,比如说汽车门把手坏掉了直接系根绳子当把手,emmmm这样确实很棒啊。 <br>
   <br>
<strong>第三条,无序。</strong> </p>

<p>  返回的结果往往是很随意,各种错误信息本来就是用Http的状态码构成的,可是很多人还是喜欢把错误信息返回在返回值中。最常见的就是Code和Message,当然对于这一点,我个人是保留疑问的,我的观点是,Http本身的错误和服务器的内部错误还是需要在不断层面分开的,不能混在一起。可是在大神眼里并非如此。</p>

<p><code>那么怎么解决这些问题呢?</code> </p>

<p>强迫症患者的福音就是<code>先颁规则</code>,<code>第一个规则就是明确Url是什么,该怎么用</code>。就是所有的<code>Url本质</code>来讲,都应该<code>是一种资源</code>。一个独立的Url地址,就是对应一个独一无二的资源。怎么样?这种感觉是不是棒棒哒?一个冰淇淋,一个老师,一间房子,在Url上对应的都是一个资源,不会有多余的Url跟他对应,也不会表示有多个Url地址  <br>
  注意,这里点的是Url地址,并不是单独的参数,他就是一个<code>/room/{room_id}</code>这样的东西,举个栗子,<code>/room/3242 这就表示3242号房间</code>。这是一个清爽的世界啊,你想想,之前的Url是什么都要,我开房,可能是<code>/open/room/3242</code> 我要退房可能是<code>/exit/3242/room</code>,我要打理房间,可能是<code>room/3242?method=clean.</code>够了!这些乱七八糟的东西全够了,让世界回归清爽的本质,<code>一间房,就是/room/3242 没有别的Url地址了。</code> <br>
  在过去的混乱世界里,经常用的就是<code>Get和Post</code>。如果不是因为Get不支持大数据传输,我想连Post都不会有人使用。(想像一下Roy Fielding在愤怒的对着电脑屏幕喊,Http的Method一共有八个,你们为毛只逮着Get一只羊的毛薅薅薅薅薅)。</p>

<p>  而对资源最常见的操作是什么?<code>CRUD</code>,对不对,就是创建,读,更新,删除。再看Http的Method?是不是非常完美?其实也怪Fielding老爷子一开始命名不准确,如果刚开始就是把<code>Get方法叫做Read</code>,<code>Put方法叫做Update</code>,<code>Post叫做Create这该多好</code>。。。 <br>
  你用一个Get,大家又发现没什么限制没什么所谓,又很难理解Put和Post的差别,法无禁止即可为啊,呃,老爷子不要瞪我,我瞎说的。总之,这四种方法够不够你浪?你有本身找出来更多的对资源的操作来啊,我还有4个Method没用过呢。如果这4个真的不够了,有什么问题,大不了我再重新更改http协议啊。其实简单说,对于Rest理解到这里就够了。后续的东西,都是在这一条基础上空想出来的,比强迫症更强迫症,当然,无状态我是百分百支持的。以上的各种表述可能不太准确,也纯属是我的意淫和各种小道资料,并未考据,但是凭良心讲,我是早就看不惯黑暗年代里的Url命名风格了,所以当时最早接触到Rest的时候,瞬间就找到了真爱,我靠,这不就是我一直想要的答案吗?<code>但是我一直想的仅仅是命名规范,从来没有把自己的思考角度放在一个url就是一个资源,所有的操作都是对资源的更改而言的角度上啊。</code>所以你能理解到的程度,更多的就是在于你要弄清楚你要解决的什么问题,如果你的问题只是理解Rest,恐怕你很理解,如果你的问题是怎么解决Url混乱的问题,你反而很快能弄懂了~</p>

<h1 id="对比"><a name="t1"></a>对比</h1>

<pre class="prettyprint" name="code"><code class="hljs ruby has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;"><span class="hljs-symbol">https:</span>/<span class="hljs-regexp">/localhost:8080/myweb</span><span class="hljs-regexp">/getDogs --&gt; GET /rest</span><span class="hljs-regexp">/api/dogs</span> 获取所有小狗狗 
<span class="hljs-symbol">https:</span>/<span class="hljs-regexp">/localhost:8080/myweb</span><span class="hljs-regexp">/addDogs --&gt; POST /rest</span><span class="hljs-regexp">/api/dogs</span> 添加一个小狗狗 
<span class="hljs-symbol">https:</span>/<span class="hljs-regexp">/localhost:8080/myweb</span><span class="hljs-regexp">/updateDogs/</span><span class="hljs-symbol">:dog_id</span> --&gt; <span class="hljs-constant">PUT</span> /rest/api/dogs/<span class="hljs-symbol">:dog_id</span> 修改一个小狗狗 
<span class="hljs-symbol">https:</span>/<span class="hljs-regexp">/localhost:8080/myweb</span><span class="hljs-regexp">/deleteDogs/</span><span class="hljs-symbol">:dog_id</span> --&gt; <span class="hljs-constant">DELETE</span> /rest/api/dogs/<span class="hljs-symbol">:dog_id</span> 删除一个小狗狗<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre>

<p>左边是我们写的,而且后台我们可能会写出很多返回值,而且各种各样的,比如 <br>
<a href="https://localhost:8080/myweb/addDogs" rel="nofollow" data-token="32e4f1e18c7e266ea76fc6871652d29b">https://localhost:8080/myweb/addDogs</a></p>

<pre class="prettyprint" name="code"><code class="hljs  has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">操作成功 或者 1<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre>

<p>或者</p>

<pre class="prettyprint" name="code"><code class="hljs  has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">操作失败 或者 0<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre>

<p>这还要我们自己去解析,还要前端和后端去协商你返回的0是啥意识啊。但是REST返回值是标准的,比如</p>

<pre class="prettyprint" name="code"><code class="hljs http has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;"><span class="hljs-status">HTTP/1.1 <span class="hljs-number">200</span> OK</span>
<span class="hljs-attribute">Content-Type</span>: <span class="hljs-string">application/json</span>
<span class="hljs-attribute">Content-Length</span>: <span class="hljs-string">xxx</span>

<span class="json">{
   "<span class="hljs-attribute">url</span>" : <span class="hljs-value"><span class="hljs-string">"/api/categories/1"</span></span>,
   "<span class="hljs-attribute">label</span>" : <span class="hljs-value"><span class="hljs-string">"Food"</span></span>,
   "<span class="hljs-attribute">items_url</span>" : <span class="hljs-value"><span class="hljs-string">"/api/items?category=1"</span></span>,
   "<span class="hljs-attribute">brands</span>" : <span class="hljs-value">[
         {
            "<span class="hljs-attribute">label</span>" : <span class="hljs-value"><span class="hljs-string">"友臣"</span></span>,
            "<span class="hljs-attribute">brand_key</span>" : <span class="hljs-value"><span class="hljs-string">"32073"</span></span>,
            "<span class="hljs-attribute">url</span>" : <span class="hljs-value"><span class="hljs-string">"/api/brands/32073"</span>
         </span>}, {
            "<span class="hljs-attribute">label</span>" : <span class="hljs-value"><span class="hljs-string">"乐事"</span></span>,
            "<span class="hljs-attribute">brand_key</span>" : <span class="hljs-value"><span class="hljs-string">"56632"</span></span>,
            "<span class="hljs-attribute">url</span>" : <span class="hljs-value"><span class="hljs-string">"/api/brands/56632"</span>
         </span>}
         ...
   ]
</span>}</span><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li></ul></pre>

<p><code>格式固定,第一行永远是操作失败或者成功的状态码,第二行是返回的类型,第三行内容的长度,第五行开始是内容。</code></p>

<p><code>这样我只需写一个程序解析返回的信息就可以了,可以重用,但是我们上面传统的不仅仅要协商,还有有不同的解析程序,稍微改变,就不能正常使用了。所以rest的明显更加通用。</code></p>

<p>列子2</p>

<pre class="prettyprint" name="code"><code class="hljs livecodeserver has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;"><span class="hljs-number">1</span>、获取文章

请求:
GET /blog/<span class="hljs-built_in">post</span>/{postId} HTTP/<span class="hljs-number">1.1</span>

响应:
HTTP/<span class="hljs-number">1.1</span> <span class="hljs-number">200</span> OK
{
    <span class="hljs-string">"title"</span>: <span class="hljs-string">"foobar"</span>,
    <span class="hljs-string">"content"</span>: <span class="hljs-string">"foobar"</span>,
    <span class="hljs-string">"comments"</span>: [<span class="hljs-string">""</span>, <span class="hljs-string">""</span>, <span class="hljs-string">""</span>]
}

<span class="hljs-number">2</span>、发布文章

请求:
POST /blog/<span class="hljs-built_in">post</span> HTTP/<span class="hljs-number">1.1</span>
{
    <span class="hljs-string">"title"</span>: <span class="hljs-string">"foobar"</span>,
    <span class="hljs-string">"content"</span>: <span class="hljs-string">"foobar"</span>,
    <span class="hljs-string">"comments"</span>: [<span class="hljs-string">""</span>, <span class="hljs-string">""</span>, <span class="hljs-string">""</span>]
}

响应:
HTTP/<span class="hljs-number">1.1</span> <span class="hljs-number">201</span> CREATED<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li></ul></pre>

<h1 id="规则"><a name="t2"></a>规则</h1>

<pre class="prettyprint" name="code"><code class="hljs ruleslanguage has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">GET    用来获取资源,
POST  用来新建资源(也可以用于更新资源),
PUT    用来更新资源,
<span class="hljs-keyword">DELETE</span>  用来删除资源<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre>

<p>例子</p>

<pre class="prettyprint" name="code"><code class="hljs avrasm has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">DELETE http://api<span class="hljs-preprocessor">.qc</span><span class="hljs-preprocessor">.com</span>/v1/friends: 删除某人的好友 (在http parameter指定好友id)
POST http://api<span class="hljs-preprocessor">.qc</span><span class="hljs-preprocessor">.com</span>/v1/friends: 添加好友UPDATE 
<span class="hljs-label">http:</span>//api<span class="hljs-preprocessor">.qc</span><span class="hljs-preprocessor">.com</span>/v1/profile: 更新个人资料
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre>

<h1 id="概念"><a name="t3"></a>概念</h1>

<p><strong><code>REST 是面向资源的,这个概念非常重要,而资源是通过 URI 进行暴露。</code></strong> <br>
URI 的设计只要负责把资源通过合理方式暴露出来就可以了。对资源的操作与它无关,操作是通过 HTTP动词来体现,所以REST 通过 URI 暴露资源时,会强调不要在 URI 中出现动词。</p>

<p>比如:左边是错误的设计,而右边是正确的</p>

<pre class="prettyprint" name="code"><code class="hljs coffeescript has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">GET /rest/api/getDogs -<span class="hljs-function">-&gt;</span> GET /rest/api/dogs 获取所有小狗狗 
GET /rest/api/addDogs -<span class="hljs-function">-&gt;</span> POST /rest/api/dogs 添加一个小狗狗 
GET <span class="hljs-regexp">/rest/api/editDogs/</span>:dog_id -<span class="hljs-function">-&gt;</span> PUT <span class="hljs-regexp">/rest/api/dogs/</span>:dog_id 修改一个小狗狗 
GET <span class="hljs-regexp">/rest/api/deleteDogs/</span>:dog_id -<span class="hljs-function">-&gt;</span> DELETE <span class="hljs-regexp">/rest/api/dogs/</span>:dog_id 删除一个小狗狗<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre>

<p><strong><code>REST很好地利用了HTTP本身就有的一些特征,如HTTP动词、HTTP状态码、HTTP报头等等</code></strong> <br>
REST API 是基于 HTTP的,所以你的API应该去使用 HTTP的一些标准。这样所有的HTTP客户端(如浏览器)才能够直接理解你的API(当然还有其他好处,如利于缓存等等)。REST 实际上也非常强调应该利用好 HTTP本来就有的特征,而不是只把 HTTP当成一个传输层这么简单了。</p>

<pre class="prettyprint" name="code"><code class="hljs http has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;"><span class="hljs-status">HTTP/1.1 <span class="hljs-number">200</span> OK</span>
<span class="hljs-attribute">Content-Type</span>: <span class="hljs-string">application/json</span>
<span class="hljs-attribute">Content-Length</span>: <span class="hljs-string">xxx</span>

<span class="json">{
   "<span class="hljs-attribute">url</span>" : <span class="hljs-value"><span class="hljs-string">"/api/categories/1"</span></span>,
   "<span class="hljs-attribute">label</span>" : <span class="hljs-value"><span class="hljs-string">"Food"</span></span>,
   "<span class="hljs-attribute">items_url</span>" : <span class="hljs-value"><span class="hljs-string">"/api/items?category=1"</span></span>,
   "<span class="hljs-attribute">brands</span>" : <span class="hljs-value">[
         {
            "<span class="hljs-attribute">label</span>" : <span class="hljs-value"><span class="hljs-string">"友臣"</span></span>,
            "<span class="hljs-attribute">brand_key</span>" : <span class="hljs-value"><span class="hljs-string">"32073"</span></span>,
            "<span class="hljs-attribute">url</span>" : <span class="hljs-value"><span class="hljs-string">"/api/brands/32073"</span>
         </span>}, {
            "<span class="hljs-attribute">label</span>" : <span class="hljs-value"><span class="hljs-string">"乐事"</span></span>,
            "<span class="hljs-attribute">brand_key</span>" : <span class="hljs-value"><span class="hljs-string">"56632"</span></span>,
            "<span class="hljs-attribute">url</span>" : <span class="hljs-value"><span class="hljs-string">"/api/brands/56632"</span>
         </span>}
         ...
   ]
</span>}</span><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li></ul></pre>

<p>看这个响应,包含了http里面的状态码等信息。还会有http的一些报头。</p>

<pre class="prettyprint" name="code"><code class="hljs lasso has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">Authorization 认证报头 
<span class="hljs-keyword">Cache</span><span class="hljs-attribute">-Control</span> 缓存报头 
Cnotent<span class="hljs-attribute">-Type</span>  消息体类型报头 
<span class="hljs-attribute">...</span><span class="hljs-attribute">...</span><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre>

<h1 id="rest-系统的特征"><a name="t4"></a>REST 系统的特征</h1>

<ol>
<li><strong><code>客户-服务器(Client-Server)</code></strong>,提供服务的服务器和使用服务的客户需要被隔离对待。</li>
<li><strong><code>无状态(Stateless)</code></strong>,<code>来自客户的每一个请求必须包含服务器处理该请求所需的所有信息</code>。换句话说,服务器端不能存储来自某个客户的某个请求中的信息,并在该客户的其他请求中使用。 </li>
<li><strong><code>可缓存(Cachable)</code></strong>,服务器必须让客户知道请求是否可以被缓存。(Ross:更详细解释请参考 理解本真的REST架构风格 以及 StackOverflow 的这个问题 中对缓存的解释。) </li>
<li><strong><code>分层系统(Layered System)</code></strong>,服务器和客户之间的通信必须被这样标准化:允许服务器和客户之间的中间层(Ross:代理,网关等)可以代替服务器对客户的请求进行回应,而且这些对客户来说不需要特别支持。 </li>
<li><strong><code>统一接口(Uniform Interface)</code></strong>,客户和服务器之间通信的方法必须是统一化的。(Ross:GET,POST,PUT.DELETE, etc) </li>
<li><strong><code>支持按需代码(Code-On-Demand,可选)</code></strong>,服务器可以提供一些代码或者脚本(Ross:Javascrpt,flash,etc)并在客户的运行环境中执行。这条准则是这些准则中唯一不必必须满足的一条。(Ross:比如客户可以在客户端下载脚本生成密码访问服务器。) </li>
</ol>

<p><strong>详细解释</strong> </p>

<p><strong><code>无状态(Stateless)</code></strong></p>

<p>   所谓无状态的,即所有的资源,都可以通过URI定位,而且这个定位与其他资源无关,也不会因为其他资源的变化而改变。有状态和无状态的区别,举个简单的例子说明一下。如查询员工的工资,如果查询工资是需要登录系统,进入查询工资的页面,执行相关操作后,获取工资的多少,则这种情况是有状态的,<code>因为查询工资的每一步操作都依赖于前一步操作,只要前置操作不成功,后续操作就无法执行;</code>如果输入一个url即可得到指定员工的工资,则这种情况是无状态的,因为获取工资不依赖于其他资源或状态,且这种情况下,员工工资是一个资源,由一个url与之对应,可以通过HTTP中的GET方法得到资源,这是典型的RESTful风格。</p>

<p><img src="https://img-blog.csdn.net/20180421191940578?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIxMzgzNDM1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt="这里写图片描述" title=""> </p>

<p><img src="https://img-blog.csdn.net/20180421191951608?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIxMzgzNDM1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt="这里写图片描述" title=""> </p>

<p><strong><code>统一接口(Uniform Interface)</code></strong></p>

<p>  RESTful架构风格规定,数据的元操作,即CRUD(create, read, update和delete,即数据的增删查改)操作,分别对应于HTTP方法:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源,这样就统一了数据操作的接口,仅通过HTTP方法,就可以完成对数据的所有增删查改工作。</p>

<p>即:</p>

<pre class="prettyprint" name="code"><code class="hljs sql has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">GET(<span class="hljs-operator"><span class="hljs-keyword">SELECT</span>):从服务器取出资源(一项或多项)。
POST(<span class="hljs-keyword">CREATE</span>):在服务器新建一个资源。
PUT(<span class="hljs-keyword">UPDATE</span>):在服务器更新资源(客户端提供完整资源数据)。
PATCH(<span class="hljs-keyword">UPDATE</span>):在服务器更新资源(客户端提供需要修改的资源数据)。
<span class="hljs-keyword">DELETE</span>(<span class="hljs-keyword">DELETE</span>):从服务器删除资源。</span><div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre>

<h1 id="演化"><a name="t5"></a>演化</h1>

<p><a href="https://zhuanlan.zhihu.com/p/30396391?group_id=937244108725641216" rel="nofollow" data-token="7c826865827f089e688c3ced30ad8a56">https://zhuanlan.zhihu.com/p/30396391?group_id=937244108725641216</a></p>

<h1 id="优点缺点"><a name="t6"></a>优点&amp;缺点</h1>

<p><code>优点</code>是因为他对uri进行了限制,只用于定义资源。这样看起来比较容易理解。尤其是对简单的对象的增删改查,很好理解。</p>

<p><code>缺点</code>是因为这种限制,导致设计uri变得复杂了。尤其是复杂的关系,操作,资源集合,<code>硬性套用rest原则设计非常困难</code>。在rest基础上的HATEOAS,返回的json里增加了相应的关系和url。这也同样带来问题。好处是对简单的关系,的确可以通过url进一步处理。但对复杂的关系和操作,HATEOAS并不能胜任描述。<code>反而在单纯的数据中增加了一堆垃圾信息。</code></p>

<h1 id="是什么"><a name="t7"></a>是什么?</h1>

<p>REST是一个<code>标准,一种规范</code>,遵循REST风格可以使开发的接口通用,便于调用者理解接口的作用。</p>

<p>参考: <br>
<a href="https://www.zhihu.com/question/28557115" rel="nofollow" data-token="e9eb7ea0179f8a6a48ca1673ea880faf">https://www.zhihu.com/question/28557115</a> <br>
<a href="https://blog.igevin.info/posts/restful-architecture-in-general/" rel="nofollow" data-token="e32bc7730c5ca62071bdefbd30d274ea">https://blog.igevin.info/posts/restful-architecture-in-general/</a></p>                                    </div>
                <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-e44c3c0e64.css" rel="stylesheet">
                    </div>
    </article>
</div>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值