正如大家可能已经注意到的那样,野外有许多虚假/基本的REST-API(实现HTTP-API并将其称为REST而不遵循超文本引擎应用程序状态要求,这导致在罗伊T.菲尔丁的著名言论,谁第一个指定的REST范式)的人.
我一直无法找到真正的超文本驱动的REST实现的任何实际示例,以及状态转换的相关应用程序特定的媒体类型定义.
是否有任何可公开访问的此类实现示例?
我目前正在为一个项目创建一个REST-API,并且正在阅读关于最佳实践的文章.许多人似乎反对DTO,只是暴露域模型,而其他人似乎认为DTO(或用户模型或任何你想称之为的)是不好的做法.就个人而言,我认为这篇文章很有意义.
但是,我也理解DTO的缺点,包括所有额外的映射代码,可能与其DTO对应物100%相同的域模型等等.
我们的API主要是为了让其他客户端可以使用数据而创建的,但是如果我们做得对,我们也希望尽可能将它用于我们自己的Web GUI.
问题是我们可能不希望将所有域数据公开给其他客户端用户.大部分数据只在我们自己的Web应用程序中才有意义.此外,我们可能不希望在所有方案中公开有关对象的所有数据,尤其是与其他对象的关系等.例如,如果我们公开特定对象的列表,我们不一定要暴露整个对象层次结构; 这样对象的孩子就不会暴露,但可以通过链接(hateoas)发现.
我该如何解决这个问题?我正在考虑在我们的域模型上使用Jackson mixins来控制在给定不同场景的情况下会暴露哪些数据.或者我们应该一直使用DTO - 即使考虑到它的缺点和争议?
我正在参与一个项目,其中一些高级团队成员认为REST API必须符合HATEOAS标准并实现所有Richardson的成熟度级别(http://martinfowler.com/articles/richardsonMaturityModel.html)!
AFAIK大多数REST实现都不符合HATEOAS标准,应该有更多人没有这样做的理由.我可以想到增加复杂性,缺乏框架(服务器和客户端),性能问题和......的原因.
你怎么看?你有没有在真实项目中使用HATEOAS的经验?
我认为我对REST的大量了解显然是错误的 - 而且我并不孤单.这个问题有很长的引导时间,但似乎是必要的,因为信息有点分散.如果你已经熟悉这个话题,最后会出现实际问题.
从Roy Fielding的第一段开始,REST API必须是超文本驱动的,很明显他认为他的工作被广泛误解:
我对使用REST API调用任何基于HTTP的接口的人数感到沮丧.今天的例子是SocialSite REST API.那就是RPC.它尖叫RPC.显示器上有很多耦合,它应该被赋予X等级.
Fielding继续列出REST API的几个属性.他们中的一些人似乎反对SO和其他论坛的常见做法和共同建议.例如:
应输入REST API,除了初始URI(书签)和适用于目标受众的标准化媒体类型集之外没有任何先验知识(即,任何可能使用API的客户都应该理解)....
REST API不能定义固定资源名称或层次结构(客户端和服务器的明显耦合)....
REST API应该花费几乎所有的描述性工作来定义用于表示资源和驱动应用程序状态的媒体类型,或者为现有标准媒体类型定义扩展关系名称和/或启用超文本的标记....
"超文本"的概念起着核心作用 - 远比URI结构或HTTP动词的含义更重要.其中一条评论中定义了"超文本":
当我[菲尔丁]说超文本时,我指的是信息和控制的同时呈现,使得信息成为用户(或自动机)获得选择和选择动作的可供性.超媒体只是对文本意味着在媒体流中包含时间锚点的扩展; 大多数研究人员都放弃了这一区
超文本不需要是浏览器上的HTML.机器在理解数据格式和关系类型时可以跟踪链接.
我猜这一点,但上面的前两点似乎表明,Foo资源的API文档看起来像下面这样导致客户端和服务器之间的紧密耦合,并且在RESTful系统中没有位置.
GET /foos/{id} # read a Foo
POST /foos/{id} # create a Foo
PUT /foos/{id} # update a Foo
Run Code Online (Sandbox Code Playgroud)
相反,应该强制代理发现所有Foos的URI,例如,针对/ foos发出GET请求.(那些URI可能会遵循上面的模式,但这不是重点.)响应使用的媒体类型能够传达如何访问每个项目以及可以用它做什么,从而产生上述第三点.因此,API文档应侧重于解释如何解释响应中包含的超文本.
此外,每次请求到Foo资源的URI时,响应都包含代理发现如何继续所需的所有信息,例如,通过其URI访问关联资源和父资源,或者在创建后采取措施/删除资源.
整个系统的关键在于响应由媒体类型中包含的超文本组成,该超文本本身传达给代理选项以进行处理.它与浏览器为人类工作的方式没有什么不同.
但这只是我在这个特殊时刻的最佳猜测.
菲尔丁发布了一个后续行动,他回应批评说他的讨论过于抽象,缺乏例子和行话丰富:
其他人会试图以更直接或适用于当今某些实际问题的方式破译我所写的内容.我可能不会,因为我太忙于处理下一个话题,准备会议,写另一个标准,到一些遥远的地方旅行,或者只是做一些让我觉得自己赚到了薪水的小事.
那么,REST专家的两个简单问题就是有一个实际的思维方式:你如何解释菲尔丁在说什么,以及在记录/实现REST API时如何将其付诸实践?
编辑:这个问题是一个例子,说明如果你没有关于你所谈论的内容的名称,学习一些东西是多么困难.在这种情况下,名称是"超媒体作为应用程序状态的引擎"(HATEOAS).
在使用HATEOAS设计RESTful Web服务时,将链接显示为完整URL(" http:// server:port/application/customers/1234 ")与仅路径("/ application /")的优缺点是什么?客户/ 1234" )?
对于我参与的SaaS创业公司,我正在构建一个RESTful Web API和几个使用它的不同平台上的客户端应用程序.我想我已经找到了API,但现在我转向客户了.正如我一直在阅读关于REST的内容,我发现 REST的一个关键部分是发现,但是对于发现的真正含义的两种不同解释似乎存在很多争论:
开发人员发现:开发人员将大量API详细信息硬编码到客户端,例如资源URI,查询参数,支持的HTTP方法以及他们通过浏览文档和试验API响应而发现的其他详细信息.这种类型的发现IMHO需要很酷的链接和API版本问题,并导致客户端代码与API的硬耦合.似乎没有比使用详细记录的RPC集合好多少.
运行时发现 - 客户端应用程序本身能够在很少或没有带外信息的情况下找出所需的一切(可能只是对API处理的媒体类型的了解.)链接可能很热.但是为了使API非常高效,似乎需要大量的查询参数链接模板,这会使带外信息重新出现.由于我还没有,我可能还有其他的困难.在发展中得到了这一点.但我确实喜欢松耦合的想法.
运行时发现似乎是REST的圣杯,但我看到很少讨论如何实现这样的客户端.几乎所有我发现的REST源似乎都假设开发人员发现.有人知道一些运行时发现资源吗?最佳做法?具有实际代码的示例或库?我正在为一个客户端使用PHP(Zend Framework).另一个是Objective-C(iOS).
鉴于开发人员社区中目前的一系列工具和知识,运行时发现是否是一个现实的目标?我可以编写我的客户端以不透明的方式处理所有URI,但如何最有效地执行此操作是一个问题,尤其是在低带宽连接上.无论如何,URI只是等式的一部分.如何在运行时上下文中链接模板?除了提出大量的OPTIONS请求之外,如何传达支持哪些方法呢?
我试图对HATEOAS有一个清晰而简洁的理解,我绝不是专家WRT REST.(我想我得到了它,感谢http://www.looah.com/source/view/2284).
任何人都可以建议一个同样令人敬畏的博客/文章WRT HATEOAS?
我正在设计一个基于JSON表示的RESTful API.为了遵守HATEOAS,我广泛使用资源之间的链接.因此,我遵循这个建议,以非常类似于ATOM链接的方式序列化链接.
现在我有时会发现识别正确链接关系类型的问题.当资源包含指向自身的链接时,self
关系是显而易见的.当资源是子资源的集合和聚合,或者包含许多指向相关资源的链接时,它会变得更加复杂.
以博客文章为例,考虑一个返回博客文章快照的资源 - 包括此博客文章的作者,标签和评论.显然,这个资源包含许多子资源,当然也应该提供单独的链接:
{
"blogpost":{
"link":{
"rel":"self",
"href":"http://blog/post/4711"
},
"author":{
"name":"Bob",
"link":{
"rel":"???",
"href":"http://author/uri"
}
},
"title":"foobar",
"content":"A long article here…",
"comments":[
{
"comment":"great article",
"link":{
"rel":"???",
"href":"http://blog/post/4711/comment/1"
},
"author":{
"name":"John Doe",
"link":{
"rel":"???",
"href":"http://author/uri"
}
}
}
],
"tags":[
{
"value":"foo",
"link":{
"rel":"???",
"href":"http://blog/post/4711/tag/foo"
}
}
]
}
}
Run Code Online (Sandbox Code Playgroud)
那么给定链接的适当关系是什么?我知道存在关系类型tag
,但不是我的所有资源都与现有的关系类型相匹配.或者self
在引用author/tag/comment时可以使用它,因为它与封闭的JSON(子)对象的上下文有关?什么是语义实体self
指的是什么?
RFC 5988声明:
链接的上下文是提要IRI或条目ID,具体取决于它出现的位置
我怎样才能用JSON来解释这个?每个新对象{…}
都是新的上下文吗?
谢谢!
假设我想创建一个类似于以下内容的XML响应:
<?xml version="1.0" encoding="utf?8"?>
<product xmlns="urn:com.acme.prods" xmlns:atom="http://www.w3.org/2005/xlink">
<id>1234</id>
<name>Red Stapler</name>
<price currency="EUR">3.14</price>
<atom:link rel="payment" type="application/com.acme.shop+xml"
href="http://acme.com/products/1234/payment" />
</product>
Run Code Online (Sandbox Code Playgroud)
给定一个类似于以下内容的域模型:
<?php
// Product.php
namespace Acme\Bundle\ProductBundle\Entity;
use Acme\Bundle\ProductBundle\Money\Money;
class Product
{
/**
* @var integer
*/
private $id;
/**
* @var string
*/
private $name;
/**
* @var Money
*/
private $price;
[..]
}
Run Code Online (Sandbox Code Playgroud)
和金钱类一样:
<?php
// Money.php
namespace Acme\Bundle\ProductBundle\Money;
class Money
{
/**
* @var string
*/
private $currency;
/**
*
*/
private $amount;
}
Run Code Online (Sandbox Code Playgroud)
现在,我的问题.创建如下所示的响应非常简单
<?xml version="1.0" encoding="utf?8"?>
<product>
<id>1234</id> …
Run Code Online (Sandbox Code Playgroud)