Spring MVC 在RESTful API中,何时使用路径参数和查询参数?

jexiocij  于 2022-11-14  发布在  Spring
关注(0)|答案(8)|浏览(199)

我想让我的RESTfulAPI具有很强的可预测性。决定何时使用URI而不是使用查询参数来进行数据分段的最佳实践是什么?
支持分页、排序和分组的系统参数放在'?'后面对我来说是有意义的,但是像'status'和'region'这样的字段或者其他分割集合的属性呢?如果这些也是查询参数,那么知道何时使用路径参数的经验法则是什么?

vi4fp9gy

vi4fp9gy1#

TL;DR:RESTful API设计的最佳实践是路径参数用于标识特定的一个或多个资源,而查询参数用于排序/筛选这些资源

下面是一个示例。假设您正在为一个名为Car的实体实现REST风格的API端点。您可以如下构建端点:
获取/cars
掘地工具/cars/:id
开机自检/cars
放置/cars/:id
删除/cars/:id
通过这种方式,您仅在指定要获取的资源时使用路径参数,但这不会以任何方式对资源进行排序/筛选。
现在,假设您希望在GET请求中添加按颜色过滤汽车的功能。因为颜色不是资源(它是资源的属性),所以您可以添加一个查询参数来执行此操作。您可以将该查询参数添加到**GET /cars**请求中,如下所示:
掘地工具/cars?color=blue
将实现此端点,以便仅返回蓝色汽车。
我们可以使用&符号添加更多滤波参数:
掘地工具/cars?color=blue&brand=ferrari
就语法而言,您的URL名称应该全部小写。如果您的实体名称通常是英语的两个字,您应该使用勒胡号来分隔字,而不是驼峰式大小写。
例如/two-words

v6ylcynt

v6ylcynt2#

思考这个问题的基本方法如下:
URI是唯一标识资源类型的特定示例的资源标识符。与生活中的其他事物一样,每个对象(某个类型的示例)都有一组不随时间变化或暂时的属性。
在上面的例子中,汽车是一个非常有形的对象,它有制造商、型号和VIN等属性--这些属性永远不会改变,而颜色、悬挂等属性可能会随时间而改变。因此,如果我们用可能随时间(暂时)而改变的属性对URI进行编码,我们可能会为同一个对象生成多个URI:

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

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

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

注意,car示例本身(对象)并没有改变--只是颜色改变了。让多个URI指向同一个对象示例将迫使您创建多个URI处理程序--这不是一个高效的设计,当然也不直观。
因此,URI应该只包含永远不会变更的部分,而且在资源的整个存留期内,都会持续唯一识别该资源。所有可能变更的部分都应该保留给查询参数,例如:

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

底线--考虑多态性。

t3irkdon

t3irkdon3#

在REST API中,您不应该过度关注可预测的URI。URI可预测性的建议本身就暗示了对REST架构的误解。它假设客户端应该自己构造URI,而实际上他们不应该这样做。
但是,我假设您创建的不是真正的RESTAPI,而是“REST启发”API(例如Google Drive)。在这些情况下,经验法则是'path params = resource identification'和'query params = resource sorting'。因此,问题就变成了,您是否可以在没有状态/区域的情况下唯一标识您的资源?如果是,则可能是一个查询参数。如果否,则它是路径参数。

8mmmxcuj

8mmmxcuj4#

细分更具有层次性和“漂亮”,但可能具有限制性。
例如,如果您有一个包含三个段的url,每个段传递不同的参数,以便通过品牌、型号和颜色搜索汽车:

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

这是一个非常漂亮的url,更容易被最终用户记住,但现在你的这种结构卡住了。假设你想使它在搜索中用户可以搜索所有的蓝色汽车,或所有的本田公民?一个查询参数解决了这个问题,因为它给予了一个键值对。所以你可以传递:

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

现在,您可以通过它的键(查询代码中的“color”或“make”)来引用该值。
您可以通过使用更多的段来创建一种键值结构来解决此问题,如:

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

希望这是有意义的..

wlp8pajw

wlp8pajw5#

有一次我设计了一个API,它的主要资源是people。通常用户会请求经过过滤的people,因此,为了防止用户每次都调用类似/people?settlement=urban的东西,我实现了/people/urban,它后来使我能够轻松地添加/people/rural。而且,这允许访问完整的/people列表,如果它以后有任何用处的话。简而言之,我的推理是给公共子集添加一条路径,
从这里:

常见查询的别名

为了使API体验对普通消费者来说更加舒适,可以考虑将条件集打包到易于访问的RESTful路径中。

xa9qqrwz

xa9qqrwz6#

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

/vehicles/cars/vehicle-id-1

这里,vehicle-id-1是路径参数。
考虑一下“查询”这个词--我把它看作是问一个关于路径的问题,也就是说,我的路径是蓝色的吗?我的路径有100个结果吗?

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

这里的color=bluelimit=100是查询参数,它们帮助描述在访问到资源后我们应该做什么:过滤掉蓝色的结果,并将它们限制在100个结果以内。

nzrxty8p

nzrxty8p7#

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

/region/state/42

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

/region/state/42/status

但是,如果'region'不是所公开资源的一部分,它可能属于查询参数之一-类似于分页(如您所提到的)。

jdzmm42g

jdzmm42g8#

示例URL:/rest/{keyword}

这个URL是一个路径参数的例子,我们可以使用@PathParam来得到这个URL的数据。

示例URL:/rest?keyword=java&limit=10

这个URL是查询参数的一个例子,我们可以使用@Queryparam来获取这个URL的数据。

相关问题