什么是RESTful

一. 什么是RESTful

  • REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
  • REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态
  • REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
  • 所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性
  • 对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)

二. RESTful API设计

  • API与用户的通信协议,总是使用HTTPs协议。
  • 域名 
    • https://api.example.com                         尽量将API部署在专用域名(会存在跨域问题)
    • https://example.org/api/                        API很简单
  • 版本
    • URL,如:https://api.example.com/v1/
    • 请求头                                                  跨域时,引发发送多次请求
  • 路径,视网络上任何东西都是资源,均使用名词表示(可复数)
    • https://api.example.com/v1/zoos
    • https://api.example.com/v1/animals
    • https://api.example.com/v1/employees
  • method
    • GET      :从服务器取出资源(一项或多项)
    • POST    :在服务器新建一个资源
    • PUT      :在服务器更新资源(客户端提供改变后的完整资源)
    • PATCH  :在服务器更新资源(客户端提供改变的属性)
    • DELETE :从服务器删除资源
  • 过滤,通过在url上传参的形式传递搜索条件
    • https://api.example.com/v1/zoos?limit=10:指定返回记录的数量
    • https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置
    • https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数
    • https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
    • https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件
  • 状态码

    <pre>
    

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 - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。

更多看这里:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

<div><span><img alt="复制代码" src="https://common.cnblogs.com/images/copycode.gif" /></span></div>
</div><div><span><a href="javascript:void(0);" onclick="copyCnblogsCode(this)"><img alt="复制代码" src="https://common.cnblogs.com/images/copycode.gif" /></a></span></div>
</div>
</li>
<li>错误处理,状态码是4xx时,应返回错误信息,error当做key。
<div>
<div>
<div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div>1</div><div>2</div><div>3</div></td><td><div><div><code>{</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>error: </code><code>&quot;Invalid API key&quot;</code></div><div><code>}</code></div></div></td></tr></tbody>
</table>
</div>
</div>
</div>
</li>
<li>返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范。
<div>
<div>
<div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div></td><td><div><div><code>GET </code><code>/</code><code>collection:返回资源对象的列表(数组)</code></div><div><code>GET </code><code>/</code><code>collection</code><code>/</code><code>resource:返回单个资源对象</code></div><div><code>POST </code><code>/</code><code>collection:返回新生成的资源对象</code></div><div><code>PUT </code><code>/</code><code>collection</code><code>/</code><code>resource:返回完整的资源对象</code></div><div><code>PATCH </code><code>/</code><code>collection</code><code>/</code><code>resource:返回完整的资源对象</code></div><div><code>DELETE </code><code>/</code><code>collection</code><code>/</code><code>resource:返回一个空文档</code></div></div></td></tr></tbody>
</table>
</div>
</div>
</div>
</li>
<li>Hypermedia API,RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。
<div>
<div>
<div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div></td><td><div><div><code>{</code><code>&quot;link&quot;</code><code>: {</code></div><div><code>&nbsp;&nbsp;</code><code>&quot;rel&quot;</code><code>:&nbsp;&nbsp; </code><code>&quot;collection https://www.example.com/zoos&quot;</code><code>,</code></div><div><code>&nbsp;&nbsp;</code><code>&quot;href&quot;</code><code>:&nbsp; </code><code>&quot;https://api.example.com/zoos&quot;</code><code>,</code></div><div><code>&nbsp;&nbsp;</code><code>&quot;title&quot;</code><code>: </code><code>&quot;List of zoos&quot;</code><code>,</code></div><div><code>&nbsp;&nbsp;</code><code>&quot;type&quot;</code><code>:&nbsp; </code><code>&quot;application/vnd.yourformat+json&quot;</code></div><div><code>}}</code></div></div></td></tr></tbody>
</table>
</div>
</div>
</div>
</li>

  摘自:http://www.ruanyifeng.com/blog/2014/05/restful_api.html

三. 基于Django实现

路由系统:

1
      <div>2</div><div>3</div></td><td><div><div><code>urlpatterns </code><code>=</code> <code>[</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>url(r</code><code>'^users'</code><code>, Users.as_view()),</code></div><div><code>]</code></div></div></td></tr>
</tbody>

CBV视图:

1
      <div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div>10</div><div>11</div><div>12</div><div>13</div><div>14</div><div>15</div><div>16</div><div>17</div></td><td><div><div><code>from</code> <code>django.views </code><code>import</code> <code>View</code></div><div><code>from</code> <code>django.http </code><code>import</code> <code>JsonResponse</code></div><div>&nbsp;</div><div><code>class</code> <code>Users(View):</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>def</code> <code>get(</code><code>self</code><code>, request, </code><code>*</code><code>args, </code><code>*</code><code>*</code><code>kwargs):</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>result </code><code>=</code> <code>{</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>'status'</code><code>: </code><code>True</code><code>,</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>'data'</code><code>: </code><code>'response data'</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>}</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>return</code> <code>JsonResponse(result, status</code><code>=</code><code>200</code><code>)</code></div><div>&nbsp;</div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>def</code> <code>post(</code><code>self</code><code>, request, </code><code>*</code><code>args, </code><code>*</code><code>*</code><code>kwargs):</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>result </code><code>=</code> <code>{</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>'status'</code><code>: </code><code>True</code><code>,</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>'data'</code><code>: </code><code>'response data'</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>}</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>return</code> <code>JsonResponse(result, status</code><code>=</code><code>200</code><code>)&nbsp;</code></div></div></td></tr>
</tbody>

四. 基于Django Rest Framework框架实现

1. 基本流程

url.py

1
      <div>2</div><div>3</div><div>4</div><div>5</div><div>6</div></td><td><div><div><code>from</code> <code>django.conf.urls </code><code>import</code> <code>url, include</code></div><div><code>from</code> <code>web.views.s1_api </code><code>import</code> <code>TestView</code></div><div>&nbsp;</div><div><code>urlpatterns </code><code>=</code> <code>[</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>url(r</code><code>'^test/'</code><code>, TestView.as_view()),</code></div><div><code>]</code></div></div></td></tr>
</tbody>

views.py

1
      <div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div>10</div><div>11</div><div>12</div><div>13</div><div>14</div><div>15</div><div>16</div><div>17</div><div>18</div><div>19</div><div>20</div><div>21</div></td><td><div><div><code>from</code> <code>rest_framework.views </code><code>import</code> <code>APIView</code></div><div><code>from</code> <code>rest_framework.response </code><code>import</code> <code>Response</code></div><div>&nbsp;</div><div>&nbsp;</div><div><code>class</code> <code>TestView(APIView):</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>def</code> <code>dispatch(</code><code>self</code><code>, request, </code><code>*</code><code>args, </code><code>*</code><code>*</code><code>kwargs):</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>&quot;&quot;&quot;</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>请求到来之后,都要执行dispatch方法,dispatch方法根据请求方式不同触发 get/post/put等方法</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code>&nbsp;</div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>注意:APIView中的dispatch方法有好多好多的功能</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>&quot;&quot;&quot;</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>return</code> <code>super</code><code>().dispatch(request, </code><code>*</code><code>args, </code><code>*</code><code>*</code><code>kwargs)</code></div><div>&nbsp;</div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>def</code> <code>get(</code><code>self</code><code>, request, </code><code>*</code><code>args, </code><code>*</code><code>*</code><code>kwargs):</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>return</code> <code>Response(</code><code>'GET请求,响应内容'</code><code>)</code></div><div>&nbsp;</div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>def</code> <code>post(</code><code>self</code><code>, request, </code><code>*</code><code>args, </code><code>*</code><code>*</code><code>kwargs):</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>return</code> <code>Response(</code><code>'POST请求,响应内容'</code><code>)</code></div><div>&nbsp;</div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>def</code> <code>put(</code><code>self</code><code>, request, </code><code>*</code><code>args, </code><code>*</code><code>*</code><code>kwargs):</code></div><div><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>return</code> <code>Response(</code><code>'PUT请求,响应内容'</code><code>)</code></div></div></td></tr>
</tbody>

上述是rest framework框架基本流程,重要的功能是在APIView的dispatch中触发。

2.  认证和授权

a. 用户url传入的token认证

urls.py
views.py

b. 请求头认证

urls.py
views.py

c. 多个认证规则

urls.py
views.py

d. 认证和权限

urls.py
views.py

e. 全局使用

上述操作中均是对单独视图进行特殊配置,如果想要对全局进行配置,则需要再配置文件中写入即可。

settings.py
urls.py
views.py

3. 用户访问次数/频率限制

a. 基于用户IP限制访问频率

urls.py
views.py

b. 基于用户IP显示访问频率(利于Django缓存)

settings.py
urls.py
views.py

c. view中限制请求频率

settings.py
urls.py
views.py

d. 匿名时用IP限制+登录时用Token限制

settings.py
urls.py
views.py

e. 全局使用

settings

4. 版本

a. 基于url的get传参方式

如:/users?version=v1

settings.py
urls.py
views.py

b. 基于url的正则方式

如:/v1/users/

settings.py
urls.py
views.py

c. 基于 accept 请求头方式

如:Accept: application/json; version=1.0

settings.py
urls.py
views.py

d. 基于主机名方法

如:v1.example.com

settings.py
urls.py
views.py

e. 基于django路由系统的namespace

如:example.com/v1/users/

settings.py
urls.py
views.py

f. 全局使用

settings.py

5. 解析器(parser)

根据请求头 content-type 选择对应的解析器就请求体内容进行处理。

a. 仅处理请求头content-type为application/json的请求体

urls.py
views.py

b. 仅处理请求头content-type为application/x-www-form-urlencoded 的请求体

urls.py
views.py

c. 仅处理请求头content-type为multipart/form-data的请求体

urls.py
views.py
upload.html

d. 仅上传文件

urls.py
views.py
upload.html

e. 同时多个Parser

当同时使用多个parser时,rest framework会根据请求头content-type自动进行比对,并使用对应parser

urls.py
views.py

f. 全局使用

settings.py
urls.py
views.py

注意:个别特殊的值可以通过Django的request对象 request._request 来进行获取

6. 序列化

序列化用于对用户请求数据进行验证和数据进行序列化。

a. 自定义字段

urls.py
views.py

b. 基于Model自动生成字段

urls.py
views.py

c. 生成URL

urls.py
views.py

d. 自动生成URL

urls.py
views.py

7. 分页

a. 根据页码进行分页

urs.py
views.py

b. 位置和个数进行分页

urls.py
views.py

c. 游标分页

urls.py
views.py

8. 路由系统

a. 自定义路由

urls.py
views.py

b. 半自动路由

urls.py
views.py

c. 全自动路由

urls.py
views.py

9. 视图

a. GenericViewSet

urls.py
views.py

b. ModelViewSet(自定义URL)

urls.py
views.py

c. ModelViewSet(rest framework路由)

urls.py
views.py

10. 渲染器

根据 用户请求URL 或 用户可接受的类型,筛选出合适的 渲染组件。
用户请求URL:

  • http://127.0.0.1:8000/test/?format=json
  • http://127.0.0.1:8000/test.json

用户请求头:

  • Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

a. json

访问URL:

  • http://127.0.0.1:8000/test/?format=json
  • http://127.0.0.1:8000/test.json
  • http://127.0.0.1:8000/test/
urls.py
views.py

b. 表格

访问URL:

  • http://127.0.0.1:8000/test/?format=admin
  • http://127.0.0.1:8000/test.admin
  • http://127.0.0.1:8000/test/
views.py

c. Form表单

访问URL:

  • http://127.0.0.1:8000/test/?format=form
  • http://127.0.0.1:8000/test.form
  • http://127.0.0.1:8000/test/
views.py

d. 自定义显示模板

访问URL:

  • http://127.0.0.1:8000/test/?format=html
  • http://127.0.0.1:8000/test.html
  • http://127.0.0.1:8000/test/
urls.py
views.py
userdetail.html

e. 浏览器格式API+JSON

访问URL:

  • http://127.0.0.1:8000/test/?format=api
  • http://127.0.0.1:8000/test.api
  • http://127.0.0.1:8000/test/
views.py

注意:如果同时多个存在时,自动根据URL后缀来选择渲染器。

面向前台

“刚才我们向前台点了一杯拿铁,这个过程可以用这段文字来描述”,说着,我在纸上写下了这段JSON,虽然她不知道什么叫JSON,但理解这段文字对于英语专业8级的她,实在再简单不过。

{"addOrder": {"orderName": "latte"}
}
复制代码

“我们通过这段文字,告诉前台,新增一笔订单,订单是一杯拿铁咖啡”,接着,前台给我们返回这么一串回复:

{"orderId": "123456"
}
复制代码

“订单ID?还是订单编号?”

“恩恩,就是订单编号”

“那我们就等着前台喊‘订单123456的客户可以取餐了’,然后就可以开吃了!”

“哈哈,你真聪明,不过,在这之前,假设我们有一张会员卡,我们想查询一下这张会员卡的余额,这时候,要向前台发起另一个询问”,我继续在纸上写着:

{"queryBalance": {"cardId": "886333"}
}
复制代码

“查询卡号为886333的卡的余额?”

“真棒!接着,查询的结果返回来了”

{"balance": "0"
}
复制代码

“切,没钱......”

“哈哈,没钱,现在我们要跟前台说,这杯咖啡不要了”,我在纸上写到:

{"deleteOrder": {"orderId": "123456"}
}
复制代码

“哼,这就把订单取消啦?”

面向资源

“现在这家咖啡店越做越大,来喝咖啡的人越来越多,单靠前台显然是不行的,店主决定进行分工,每个资源都有专人负责,我们可以直接面向资源操作。”

"面向资源?”

“是的,比如还是下单,请求的内容不变,但是我们多了一条消息”,我在纸上画出这次的模型:

/orders{"addOrder": {"orderName": "latte"}
}
复制代码

“多了一个斜杠和orders?这是什么意思?”

“这个表示我们这个请求是发给哪个资源的,订单是一种资源,我们可以理解为是咖啡厅专门管理订单的人,他可以帮我们处理所有有关订单的操作,包括新增订单、修改订单、取消订单等操作”

“Soga...”

“接着还是会返回订单的编号给我们”

{"orderId": "123456"
}
复制代码

“下面,我们还是要查询会员卡余额,这次请求的资源变成了cards”

/cards{"queryBalance": {"cardId": "886333"}
}
复制代码

“接下来是取消订单”

“这个我会”,说着,她抢走我手上的笔,在纸上写了起来:

/orders{"deleteOrder": {"orderId": "123456"}
}
复制代码

打上标签

“接下来,店主还想继续优化他的咖啡厅的服务流程,他发现负责处理订单的员工,每次都要去订单内容里面看是新增订单还是删除订单,还是其他的什么操作,十分不方便,于是规定,所有新增资源的请求,都在请求上面写上大大的‘POST’,表示这是一笔新增资源的请求”

“其他种类的请求,比如查询类的,用‘GET’表示,删除类的,用‘DELETE’表示”

“还有修改类的,修改分为两种,第一种,如果这个修改,无论发送多少次,最后一次修改后的资源,总是和第一次修改后的一样,比如将拿铁改为猫屎,那么用‘PUT’表示;第二种,如果这个修改,每次修改都会让这个资源和前一次的不一样,比如是加一杯咖啡,那么这种请求用‘PATCH’或者‘POST’表示”,一口气讲了这么多,发现她有点似懂非懂。

“来,我们再来重复上面那个过程,来一杯拿铁”,我边说边画着:

POST /orders{"orderName": "latte"
}
复制代码

"请求的内容简洁多啦,不用告诉店员是addOrder,看到POST就知道是新增",她听的很认真,理解的也很透彻。

"恩恩,返回的内容还是一样"

{"orderId": "123456"
}
复制代码

“接着是查询会员卡余额,这次也简化了很多”

GET /cards{"cardId": "886333"
}
复制代码

“这个请求我们还可以进一步优化为这样”

GET /cards/886333
复制代码

“Soga,直接把要查询的卡号写在后面了”

“没错,接着,取消订单”

DELETE /orders/123456
复制代码

完美服务

“忽然有一天,有个顾客抱怨说,他买了咖啡后,不知道要怎么取消订单,咖啡厅一个店员回了一句,你不会看我们的宣传单吗,上面不写着:

DELETE /orders/{orderId}
复制代码

顾客反问道,谁会去看那个啊,店员不服,又说到,你瞎了啊你......据说后面两人吵着吵着还打了起来...”

“噗,真是悲剧...”

“有了这次教训,店长决定,顾客下了单之后,不仅给他们返回订单的编号,还给顾客返回所有可以对这个订单做的操作,比如告诉用户如何删除订单。现在,我们还是发出请求,请求内容和上一次一样”

POST /orders{"orderName": "latte"
}
复制代码

“但是这次返回时多了些内容”

{"orderId": "123456","link": {"rel": "cancel","url": "/order/123456"}
}
复制代码

“这次返回时多了一项link信息,里面包含了一个rel属性和url属性,rel是relationship的意思,这里的关系是cancel,url则告诉你如何执行这个cancel操作,接着你就可以这样子来取消订单啦”

DELETE /orders/123456
复制代码

“哈哈,这服务真是贴心,以后再也不用担心店员和顾客打起来了”

“订单123456的客户可以取餐了”,伴随着咖啡厅的广播,我们吃起了下午茶,一杯拿铁,两支吸管......

什么是restful?怎样用通俗的语言解释restful?相关推荐

  1. 怎样用通俗的语言解释REST,以及RESTful?

    作者:覃超 链接:https://www.zhihu.com/question/28557115/answer/48094438 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...

  2. 到底什么是REST?怎么用通俗的语言解释REST以及RESTful?

    最近在学习Retrofit的时候,看到Square官方对Retrofit的描述: "A type-safe REST client for Android and Java" 即: ...

  3. 通俗的语言解释REST以及RESTful

    http是目前在互联网上使用最多的协议,没有之一. 可是http的创始人一直都觉得,在过去10几年来,所有的人都在错误的使用Http. 这句话怎么说呢? 如果说你要删除一个数据,以往的做法通常是 de ...

  4. 什么是MFA,用最通俗的语言解释

    背景 MFA是什么,是Multi-Factor Authentication,多因素鉴权 或 多因子鉴权(说成 "验证" 也行,"鉴权" 就是 "验证 ...

  5. Alternate Realities大赛作品引发的思考(一)——用通俗的语言解释shader的渲染过程

    背景 本科学了四年的数字媒体技术,如今对流行的shader技术,合成(compositing),渲染还是一窍不通. 基本写作业就是面向tutorial,没有办法响应需求,更没有办法形成自己的风格. 思 ...

  6. 用最通俗的语言讲一讲,什么是阻抗匹配?

    大家好,很高兴和各位一起分享我的第3篇原创文章,喜欢和支持我的工程师,一定记得给我点赞.收藏.分享. 加微信[xyzn3333]与作者沟通交流,免费获取更多单片机与嵌入式的海量电子资料. 欢迎关注[玩 ...

  7. java反射通俗解释,谁来帮用通俗易懂的语言解释下java的反射机制

    谁来帮用通俗易懂的语言解释下java的反射机制以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 谁来帮用通俗易懂的语言解释 ...

  8. 10分钟了解人工智能(最通俗的语言)

    最通俗的语言:15分钟了解人工智能:唯一优点,受众完全听懂 无人驾驶.智能家居.远程医疗--如今,人工智能(AI)技术已被广泛应用于金融.交通.医疗.安防.教育等领域,成为经济增长新动能 一 什么是人 ...

  9. restapi是什么意思_用人类语言解释:REST API 与 RESTful API

    API,应用程序接口,也可以叫应用程序界面,或者简称为应用接口.应用程序的设计可以相当复杂,但最终的用户并不需要知道应用程序的内部到底是如何工作的,你只需要给用户提供一些操作接口,再告诉用户怎么用这些 ...

最新文章

  1. CF587F Duff is Mad
  2. Java新手看招 常用开发工具介绍
  3. ae怎么做圆一圈圈扩散效果_轻备学院AE特效基础教程 - 如何制作一个带有动画效果村庄烟雾...
  4. Tomcat - 你该知道的Tomcat生产环境部署
  5. python open word_使用Python在OpenOffice / Microsoft Word中格式化输出
  6. jquery选择器:第一个子元素
  7. centos 下载oracle_Linux镜像下载大全
  8. Nacos版本升级1.1.3 >> 1.3.1 —>再升级至1.3.2
  9. python是基于什么原理_Python基于class()实现面向对象原理详解
  10. 想成为前端工程师,那么在大学期间应该如何规划?
  11. python 生成器装饰器_对Python生成器、装饰器、递归的使用详解
  12. 收据模板_使用智能收据简化支出报告
  13. 计算机查找的快捷键是,电脑快捷键快速查找
  14. LiLeiHanMeiMei的隐式马尔可夫爱情
  15. 2.1.1.15使用WIFI网卡1_准备工作及配置内核
  16. 福寿园首席员工系列报道:一雕一琢 人生定格
  17. linux 下网络编程 聊天室项目
  18. mac nginx 非brew安装_Mac 安装 nginx
  19. 【STM32学习笔记】(5)—— STM32工程添加源文件和头文件
  20. ES6中Set方法实现数组去重

热门文章

  1. CentOS中使用VeraCrypt:安装及创建整个加密硬盘
  2. centos7系统关机命令_centos关机命令
  3. uniapp使用Vant ui
  4. 计算机的两种启动引导方式,硬盘的两种分区和对应启动引导方式
  5. 1989-2015各国平均关税水平
  6. 《转》vue-cli的webpack模板项目配置文件注释
  7. Android--BroadcastReceiver
  8. 魔法(csdn编程挑战)
  9. 莫比乌斯进阶:bzoj 2693 jzptab(Mobius)
  10. 【JavaScript实现十进制转换成二进制】