当前位置: 首页 > 知识库问答 >
问题:

REST资源路径设计

终翔
2023-03-14

我正在开发一种Rest服务,我正在努力遵守罗伊·菲尔丁医生的惯例和指导原则。

我将我的服务想象成公开一组资源的endpoint。资源由URI标识,api客户端可以使用HTTP语义学(即不同的HTTP动词映射到URI上的相应操作)来操作资源。

指导方针指出,这些URI应该以分层的方式定义,以反映对象层次结构。这在资源创建中非常有用,因为在后端,我们需要数据来执行创建操作。然而,在进一步的操作中,URI中包含的许多信息甚至不会被服务使用,因为通常仅资源Id就足以唯一标识操作目标。

示例:考虑一个公开产品创建和管理的Api。还考虑产品与品牌相关联。在创建时,执行以下操作是有意义的:HTTP POST /Brand/{brand_id}/Products[包含创建产品所需输入的正文]

创建返回一个HTTP 201,该HTTP 201使用一个位置头创建,该位置头公开了新创建的产品的位置。

在进一步的操作中,客户端可以通过以下操作访问产品:HTTP PUT/Brand/{Brand\u id}/product/{product\u id}HTTP DELETE/Brand/{Brand\u id}/product/{product\u id}等

但是,由于产品id在产品范围内是通用的,因此可以这样执行以下操作: /Product/{product_id}出于一致性原因,我只保留 /Brand/{brand_id}前缀。事实上,服务正在忽略品牌id。你认为这是一个好的做法,并且为了维护一个清晰、明确的ServiceInterface定义是合理的吗?这样做有什么好处,这是应该走的路吗?

此外,任何关于URI定义最佳实践的建议都将受到赞赏。

提前感谢

共有2个答案

黎奇思
2023-03-14

我认为这是关键的评论:

产品与品牌相关联。

关联这个词告诉我你需要将资源链接在一起。所以,假设品牌和产品之间存在关联。正如您所描述的,每个资源都有自己的方法集(GET、PUT等),但表示应该有指向描述其关联的其他资源的链接。链接在哪里取决于关联的类型(一对一、一对多、多对一、多对多)和方向。

例如,假设此产品有一个api.example.com的规范请求:

GET /product/12345

它返回该产品的一些表示。为简单起见,我将使用XML作为表示,但它可以是XHTML、JSON或您需要的任何东西。所以,产品12345的简单表示:

HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8
Content-Length: ...

<?xml version="1.0"?>
<Product href="http://api.example.com/product/12345" rel="self" type="application/xml"/>
  <Name>Macaroni and Cheese</Name>
  <Brand href="http://api.example.com/brand/7329" type="application/xml"/>
  <Manufacturer href="http://api.example.com/manufacturer/kraft" rel="parent" type="application/xml"/>
</Product>

如您所见,我正在将链接嵌入到描述每个关系的产品12345的表示中。只要有可能,我就尽可能地遵循HATEOAS约束:

  • 当前资源和关联资源之间存在明确的链接

为了扩展一些高级概念,让我们假设产品具有其他关系。可能产品具有层次关系,或者产品取代了其他产品。所有这些复杂的关系都可以用链接来表示。因此,产品12345的高级表示:

HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8
Content-Length: ...

<?xml version="1.0"?>
<Product href="http://api.example.com/product/12345" rel="self" type="application/xml"/>
  <Name>Macaroni and Cheese</Name>
  <Brand href="http://api.example.com/brand/7329" rel="parent" type="application/xml"/>
  <Manufacturer href="http://api.example.com/manufacturer/kraft" type="application/xml"/>
  <!-- Other product data -->
  <Related>
    <Product href="http://api.example.com/product/29180" rel="prev" type="application/xml"/>
    <Product href="http://api.example.com/product/39201" rel="next" type="application/xml"/>
  </Related>      
</Product>

在这个例子中,我使用“prev”和“Next”来表示一个产品链。“prev”可以解释为“取代”,“Next”可以解释为“取代”。您可以使用“取代”和“取代”作为rel值,但常用“prev”和“Next”。这真的取决于您。

斜淳
2023-03-14

你是说:

指导方针指出,这些URI应该以分层的方式定义,以反映对象层次结构。

虽然通常是这样做的,但它与RESTful APIhtml" target="_blank">设计并不真正相关。罗伊·菲尔丁(RoyFielding)有一篇很好的文章,阐述了人们对REST的常见误解。他甚至说:

REST API不能定义固定的资源名称或层次结构(客户端和服务器的明显耦合)。

应该在没有超出初始URI的先验知识的情况下输入REST API...

因此,不要在URL中编码应该在资源中传递的信息。即使您用人工和非感官URI替换所有URL,RESTful API也应该可以工作。(我和任何人一样喜欢可以理解的URI,但作为一种检查你“恢复状态”的心理练习,这很好。)

为对象“层次结构”建模URI的问题是,层次结构通常不像看起来那么明显。(教师、课程和学生之间的对象层次是什么?)。通常,对象处于一个关系网中,并不清楚地属于另一个对象之下。一个产品可能属于一个品牌,但您可能有多个供应商(涵盖多个品牌的产品子集)。REST很好地表达了复杂的关系网。整个internet/web都是这样工作的。

不要在层次结构中对关系进行编码,只需在资源中定义一个指向相关对象的超链接即可。

对于您的具体示例,我将使用POST/product/创建新产品,并在创建产品时在资源表示中提供指向您的/品牌/xzy的链接。

如果您想知道为特定品牌定义了哪些产品,只需在返回的GET/brand/xzy表示中包含一个链接列表。如果您希望有一个表示此关系的显式资源,您仍然可以将GET/brand/{id}/products定义为URL(或/brandproducts/xzy或/34143453),并将其作为品牌资源中的链接返回。

不要过多考虑URI的设计,更多地考虑您在资源中提供的信息。确保它提供了指向您的客户端在从您的API接收后可能想要查看或操作的所有资源表示的链接。

 类似资料:
  • 问题内容: 我目前有一个带注释的存储库。我要添加以下内容: 这可以正常工作,但默认情况下的路径为。 如何删除零件而只有路径? 问题答案: 不幸的是,这是不可能的。我对Spring Data Rest源代码进行了一些研究。 在中有用于URI构建的常量: 而 这里 是处理按服务要求与操作方法的注释。因此,如您所见,该部分是硬编码的,无法更改。

  • 本文将介绍 Weex 中 uri(url) 的用法。包括使用图像、字体等资源,处理相对路径以及如何访问本地及打包的资源文件。 Schemes 本地资源 Weex SDK 提供 local scheme 来访问打包在应用程序中的资源,此 scheme 无法在 H5 环境下使用。目前,开发者可以在 image 组件和字体文件中使用本地资源。 在 iOS 中,Weex 会在 bundle resourc

  • 我有一个文件夹和包结构,如下所示 null null 致以最诚挚的问候 编辑:使用windows可能有不同的语法

  • 上面是我的程序,错误显示为: 可能的问题是什么?请帮忙,因为我是新来的 我面临着同样的问题,我该如何解决?

  • 默认情况下,vue-loader 使用 css-loader 和 Vue 模版编译器自动处理样式和模版文件。在编译过程中,所有的资源路径例如 <img src="...">、background: url(...) 和 @import 会作为模块依赖。 例如,url(./image.png) 会被转换为 require('./image.png'),而 <img src="../image.png

  • 构建目录 将前端构建配置文件所在的目录视为构建目录,也视为当前项目的根目录。 - dest - src |-- coolie.config.js 此时,coolie.config.js所在的目录src即为项目根目录,用 webstorm 可以非常好的标记项目根目录。 glob 路径 *:多个文件 **:多层级目录 更多 coolie 前端构建的配置文件以下配置是支持 glob 路径的: js.m