我想让我的RESTfulAPI具有很强的可预测性。决定何时使用URI而不是使用查询参数来进行数据分段的最佳实践是什么?支持分页、排序和分组的系统参数放在'?'后面对我来说是有意义的,但是像'status'和'region'这样的字段或者其他分割集合的属性呢?如果这些也是查询参数,那么知道何时使用路径参数的经验法则是什么?
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
/cars
/cars/:id
/cars?color=blue
&
/cars?color=blue&brand=ferrari
/two-words
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}
底线--考虑多态性。
t3irkdon3#
在REST API中,您不应该过度关注可预测的URI。URI可预测性的建议本身就暗示了对REST架构的误解。它假设客户端应该自己构造URI,而实际上他们不应该这样做。但是,我假设您创建的不是真正的RESTAPI,而是“REST启发”API(例如Google Drive)。在这些情况下,经验法则是'path params = resource identification'和'query params = resource sorting'。因此,问题就变成了,您是否可以在没有状态/区域的情况下唯一标识您的资源?如果是,则可能是一个查询参数。如果否,则它是路径参数。
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
希望这是有意义的..
wlp8pajw5#
有一次我设计了一个API,它的主要资源是people。通常用户会请求经过过滤的people,因此,为了防止用户每次都调用类似/people?settlement=urban的东西,我实现了/people/urban,它后来使我能够轻松地添加/people/rural。而且,这允许访问完整的/people列表,如果它以后有任何用处的话。简而言之,我的推理是给公共子集添加一条路径,从这里:
people
/people?settlement=urban
/people/urban
/people/rural
/people
为了使API体验对普通消费者来说更加舒适,可以考虑将条件集打包到易于访问的RESTful路径中。
xa9qqrwz6#
考虑单词“path”-一种到达位置的方式。路径参数应该描述如何到达你感兴趣的位置/资源。这包括目录、ID、文件等。
/vehicles/cars/vehicle-id-1
这里,vehicle-id-1是路径参数。考虑一下“查询”这个词--我把它看作是问一个关于路径的问题,也就是说,我的路径是蓝色的吗?我的路径有100个结果吗?
vehicle-id-1
/vehicles/cars/vehicle-id-1?color=blue&limit=100
这里的color=blue和limit=100是查询参数,它们帮助描述在访问到资源后我们应该做什么:过滤掉蓝色的结果,并将它们限制在100个结果以内。
color=blue
limit=100
nzrxty8p7#
一般来说,当资源中存在明显的“层次结构”时,我倾向于使用路径参数,例如:
/region/state/42
如果该单一资源具有状态,则可以:
/region/state/42/status
但是,如果'region'不是所公开资源的一部分,它可能属于查询参数之一-类似于分页(如您所提到的)。
jdzmm42g8#
示例URL:/rest/{keyword}
/rest/{keyword}
这个URL是一个路径参数的例子,我们可以使用@PathParam来得到这个URL的数据。
@PathParam
示例URL:/rest?keyword=java&limit=10
/rest?keyword=java&limit=10
这个URL是查询参数的一个例子,我们可以使用@Queryparam来获取这个URL的数据。
@Queryparam
8条答案
按热度按时间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
v6ylcynt2#
思考这个问题的基本方法如下:
URI是唯一标识资源类型的特定示例的资源标识符。与生活中的其他事物一样,每个对象(某个类型的示例)都有一组不随时间变化或暂时的属性。
在上面的例子中,汽车是一个非常有形的对象,它有制造商、型号和VIN等属性--这些属性永远不会改变,而颜色、悬挂等属性可能会随时间而改变。因此,如果我们用可能随时间(暂时)而改变的属性对URI进行编码,我们可能会为同一个对象生成多个URI:
多年以后,如果这辆车的颜色变成黑色:
注意,car示例本身(对象)并没有改变--只是颜色改变了。让多个URI指向同一个对象示例将迫使您创建多个URI处理程序--这不是一个高效的设计,当然也不直观。
因此,URI应该只包含永远不会变更的部分,而且在资源的整个存留期内,都会持续唯一识别该资源。所有可能变更的部分都应该保留给查询参数,例如:
底线--考虑多态性。
t3irkdon3#
在REST API中,您不应该过度关注可预测的URI。URI可预测性的建议本身就暗示了对REST架构的误解。它假设客户端应该自己构造URI,而实际上他们不应该这样做。
但是,我假设您创建的不是真正的RESTAPI,而是“REST启发”API(例如Google Drive)。在这些情况下,经验法则是'path params = resource identification'和'query params = resource sorting'。因此,问题就变成了,您是否可以在没有状态/区域的情况下唯一标识您的资源?如果是,则可能是一个查询参数。如果否,则它是路径参数。
8mmmxcuj4#
细分更具有层次性和“漂亮”,但可能具有限制性。
例如,如果您有一个包含三个段的url,每个段传递不同的参数,以便通过品牌、型号和颜色搜索汽车:
这是一个非常漂亮的url,更容易被最终用户记住,但现在你的这种结构卡住了。假设你想使它在搜索中用户可以搜索所有的蓝色汽车,或所有的本田公民?一个查询参数解决了这个问题,因为它给予了一个键值对。所以你可以传递:
现在,您可以通过它的键(查询代码中的“color”或“make”)来引用该值。
您可以通过使用更多的段来创建一种键值结构来解决此问题,如:
希望这是有意义的..
wlp8pajw5#
有一次我设计了一个API,它的主要资源是
people
。通常用户会请求经过过滤的people
,因此,为了防止用户每次都调用类似/people?settlement=urban
的东西,我实现了/people/urban
,它后来使我能够轻松地添加/people/rural
。而且,这允许访问完整的/people
列表,如果它以后有任何用处的话。简而言之,我的推理是给公共子集添加一条路径,从这里:
常见查询的别名
为了使API体验对普通消费者来说更加舒适,可以考虑将条件集打包到易于访问的RESTful路径中。
xa9qqrwz6#
考虑单词“path”-一种到达位置的方式。路径参数应该描述如何到达你感兴趣的位置/资源。这包括目录、ID、文件等。
这里,
vehicle-id-1
是路径参数。考虑一下“查询”这个词--我把它看作是问一个关于路径的问题,也就是说,我的路径是蓝色的吗?我的路径有100个结果吗?
这里的
color=blue
和limit=100
是查询参数,它们帮助描述在访问到资源后我们应该做什么:过滤掉蓝色的结果,并将它们限制在100个结果以内。nzrxty8p7#
一般来说,当资源中存在明显的“层次结构”时,我倾向于使用路径参数,例如:
如果该单一资源具有状态,则可以:
但是,如果'region'不是所公开资源的一部分,它可能属于查询参数之一-类似于分页(如您所提到的)。
jdzmm42g8#
示例URL:
/rest/{keyword}
这个URL是一个路径参数的例子,我们可以使用
@PathParam
来得到这个URL的数据。示例URL:
/rest?keyword=java&limit=10
这个URL是查询参数的一个例子,我们可以使用
@Queryparam
来获取这个URL的数据。