我何时在RESTful API中使用路径参数与查询参数?

时间:2015-06-21 18:19:12

标签: rest spring-mvc restful-url restful-architecture api-design

我想让我的RESTful API非常可预测。决定何时使用URI而不是使用查询参数来分段数据的最佳做法是什么。

对我来说,支持分页,排序和分组的系统参数在'?'之后是有意义的。但是像' status'等领域呢?和'地区'或其他细分您的收藏?如果那些也是查询参数,那么知道何时使用路径参数的经验法则是什么?

8 个答案:

答案 0 :(得分:137)

RESTful API设计的最佳实践是路径参数用于标识特定资源或资源,而查询参数用于对这些资源进行排序/过滤。

这是一个例子。假设您正在为名为Car的实体实现RESTful API端点。您可以像这样构建端点:

获取/cars
获取/cars/:id
发布/cars
PUT /cars/:id
删除/cars/:id

这样,在指定要获取的资源时,您只使用路径参数,但这不会以任何方式对资源进行排序/过滤。

现在假设您想添加在GET请求中按颜色过滤汽车的功能。因为颜色不是资源(它是资源的属性),所以您可以添加执行此操作的查询参数。您可以将该查询参数添加到 GET /cars 请求中,如下所示:

获取/cars?color=blue

此端点将被实施,以便仅返回蓝色汽车。

就语法而言,您的URL名称应全部为小写。如果您的实体名称通常是两个英文单词,您可以使用连字符分隔单词,而不是驼峰单词。

实施例。 /two-words

答案 1 :(得分:32)

思考这个问题的基本方法如下:

URI是唯一标识资源TYPE的特定实例的资源标识符。与生活中的其他一切一样,每个对象(某种类型的实例)都具有时间不变或时间的属性集。

在上面的示例中,汽车是一个非常有形的物体,其具有诸如品牌,型号和VIN之类的属性 - 永不改变,颜色,悬浮等可能随时间而变化。因此,如果我们使用可能随时间(时间)变化的属性对URI进行编码,我们最终可能会为同一个对象提供多个URI:

GET /cars/honda/civic/coupe/{vin}/{color=red}

多年以后,如果这辆同一辆车的颜色变为黑色:

GET /cars/honda/civic/coupe/{vin}/{color=black}

请注意,汽车实例本身(对象)没有改变 - 它只是改变的颜色。让多个URI指向同一个对象实例会强制您创建多个URI处理程序 - 这不是一个有效的设计,当然不直观。

因此,URI应该只包含永不改变的部分,并且将在其整个生命周期内继续唯一地标识该资源。应该为查询参数保留所有可能更改的内容,如下所示:

GET /cars/honda/civic/coupe/{vin}?color={black}

底线 - 认为多态性。

答案 2 :(得分:10)

在REST API中,您不应过分担心可预测的URI。 URI可预测性的这一建议暗示了对RESTful架构的误解。它假定客户端应该自己构建URI,而他们真的不应该这样做。

但是,我假设你没有创建一个真正的REST API,而是一个REST启发的' API(例如Google Drive一个)。在这些情况下,经验法则是“路径参数=资源识别'和'查询参数=资源排序'。那么,问题就变成了,您能否在没有状态/区域的情况下唯一地识别您的资源?如果是,那么也许它是一个查询参数。如果不是,那么它就是一个路径参数。

HTH。

答案 3 :(得分:1)

示例网址 /rest/{keyword}

此URL是路径参数的示例。我们可以使用@PathParam

获取此网址数据

示例网址 /rest?keyword=java&limit=10

此URL是查询参数的示例。我们可以使用@Queryparam

获取此网址数据

答案 4 :(得分:1)

我设计了一个主要资源为people的API。通常,用户会请求过滤people,因此,为了防止用户每次都调用/people?settlement=urban之类的内容,我实施了/people/urban,后来我可以轻松添加/people/rural。这也允许访问完整的/people列表,如果以后可以使用它。简而言之,我的理由是添加公共子集的路径

来自here

  

常见查询的别名

     

为了让普通消费者的API体验更加愉快,请考虑将一组条件打包成易于访问的RESTful路径。例如,上面最近关闭的故障单查询可以打包为GET /tickets/recently_closed

答案 5 :(得分:1)

考虑“路径”这个词 - 一种到达某个位置的方式。路径参数应描述如何访问您感兴趣的位置/资源。这包括目录、ID、文件等。

/vehicles/cars/vehicle-id-1

这里,vehicle-id-1 是一个路径参数。

考虑“查询”这个词 - 我认为它是在询​​问有关路径的问题,即我的路径是蓝色的,我的路径是否有 100 个结果。

/vehicles/cars/vehicle-id-1?color=blue&limit=100

这里的 color=bluelimit=100 是查询参数,它们有助于描述我们在获得资源后应该做什么:过滤掉蓝色的,并将它们限制为 100 个结果。

答案 6 :(得分:0)

一般来说,当存在明显的“等级”时,我倾向于使用路径参数。在资源中,例如:

/region/state/42

如果该单一资源具有状态,则可以:

/region/state/42/status

但是,如果' region'它实际上不是被暴露的资源的一部分,它可能属于查询参数之一 - 类似于分页(如你所提到的)。

答案 7 :(得分:0)

细分更加分层,而且非常好。但可以限制。

例如,如果您有一个包含三个细分的网址,每个网址都会传递不同的参数,以通过品牌,型号和颜色搜索汽车:

www.example.com/search/honda/civic/blue

这是一个非常漂亮的网址,最终用户更容易记住,但现在你的这种结构仍然存在。假设您想要在搜索中搜索所有蓝色汽车或所有本田思域?查询参数解决了这个问题,因为它给出了一个键值对。所以你可以通过:

www.example.com/search?color=blue
www.example.com/search?make=civic

现在,您可以通过它的键来引用该值 - 或者" color"或"制作"在您的查询代码中。

你可以通过使用更多的段来创建一种键值结构来解决这个问题:

www.example.com/search/make/honda/model/civic/color/blue

希望有道理..