我想让我的RESTful API非常可预测。决定何时使用URI而不是使用查询参数分割数据的最佳实践是什么?
对我来说,支持分页、排序和分组的系统参数在'?'之后是有意义的。但是,像“status”和“region”这样的字段或其他属性如何划分您的集合呢?如果这些是查询参数,什么是关于知道什么时候使用路径参数的经验法则?
我想让我的RESTful API非常可预测。决定何时使用URI而不是使用查询参数分割数据的最佳实践是什么?
对我来说,支持分页、排序和分组的系统参数在'?'之后是有意义的。但是,像“status”和“region”这样的字段或其他属性如何划分您的集合呢?如果这些是查询参数,什么是关于知道什么时候使用路径参数的经验法则?
当前回答
一般来说,当资源中存在明显的“层次结构”时,我倾向于使用路径参数,例如:
/region/state/42
如果该单一资源具有状态,则可以:
/region/state/42/status
但是,如果‘region’实际上不是所公开的资源的一部分,它可能属于查询参数之一——类似于分页(如您所提到的)。
其他回答
细分更有层次,更“漂亮”,但可能会有限制。
例如,如果你有一个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
希望这有意义。
示例URL: /rest/{keyword}
该URL是路径参数的示例。我们可以使用@PathParam来获取这个URL数据。
示例URL: /rest?关键词= java&limit = 10
该URL是查询参数的示例。我们可以使用@Queryparam来获取这个URL数据。
思考这个问题的基本思路是:
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}
底线——多态。
考虑一下“路径”这个词——到达某地的一种方式。路径参数应该描述如何到达您感兴趣的位置/资源。这包括目录、id、文件等。
/vehicles/cars/vehicle-id-1
其中vehicle-id-1为路径参数。
考虑一下“查询”这个词——我认为它是在问一个关于路径的问题,例如,我的路径是蓝色的吗,我的路径是否有100个结果。
/vehicles/cars/vehicle-id-1?color=blue&limit=100
这里color=blue和limit=100是查询参数,它们帮助描述我们在获得资源后应该做什么:过滤掉蓝色的,并将它们限制为100个结果。
一般来说,当资源中存在明显的“层次结构”时,我倾向于使用路径参数,例如:
/region/state/42
如果该单一资源具有状态,则可以:
/region/state/42/status
但是,如果‘region’实际上不是所公开的资源的一部分,它可能属于查询参数之一——类似于分页(如您所提到的)。