Java 对于需要返回两组不同响应的HTTP GET REST响应,正确的设计原则是什么
我想了解在按照REST设计HTTP GET响应时应遵循的正确方法。我有以下要求Java 对于需要返回两组不同响应的HTTP GET REST响应,正确的设计原则是什么,java,rest,server,Java,Rest,Server,我想了解在按照REST设计HTTP GET响应时应遵循的正确方法。我有以下要求 class Employee { private long employeedID; private String name; private Date dob; private String address; private String department; } 根据REST建模,httpget/employees将返回所有雇员的数组。类似地,HTTP GET/employees
class Employee {
private long employeedID;
private String name;
private Date dob;
private String address;
private String department;
}
根据REST建模,httpget/employees将返回所有雇员的数组。类似地,HTTP GET/employees/1将返回Id为1的员工
现在有一个UI驱动的工作流,我只需要显示每个员工的姓名和employeeID。因此,来自HTTP GET/employees的现有响应是重量级的(其他字段被不必要地传输)。因此,我希望将响应限制为仅包含每个员工的姓名和employeeID
我正在评估以下选项
方法1:
使用Content-Type HTTP头指示发出HTTP GET/employees请求的客户端在响应中需要一个经过修剪的属性列表。也就是说,在内容类型中有一些自定义字符串(即application.summary+json),这将导致响应中只包含2个属性
方法2:
使用额外的查询参数作为HTTP GET/employess?isSummary=true。在本例中,在服务器端,根据isSummary参数的值,我只能为每个员工返回2个属性
方法3:
创建一个新的REST端点本身,该端点本身支持精简响应,即HTTP GET/employees/summaryDetails
在这种情况下,在上述端点中只返回2个属性
在这三种方法中,哪种方法与其他方法最接近
谢谢我认为方法2领域的某种东西是实现这一目标的方法。从根本上说,您仍然在访问相同的搜索和结果集,并且它是相同的资源(员工)。因此,方法3并不真正合适 也就是说,有各种各样的方法可以进行。一种方法是使用一个表示投影的查询字符串参数—有点像SQL投影。比如:
GET /employees?fields=ID,name
我使用过一些这样工作的API,它们工作得很好。列出的每种方法的问题是,它使API复杂化,并且可能违反了REST最基本的原则,即可发现性。该响应不提供任何上述API存在的线索。您必须阅读文档(恐怖!)。REST的基本规则是:超文本作为应用程序状态的引擎
所以,如果你想要一个最大的REST的API,考虑下面的,遵循以下标准: 这:
收益率:[ {
"employeeID": 1,
"name": "Joe",
"_links": [ {
"rel": "self",
"href": "http://foo.bar/employees/1"
}, {
"rel": "details",
"href": "http://foo.bar/employees/1/details"
} ]
}, {
"employeeID": 2,
"name": "Sam",
"_links": [ {
"rel": "self",
"href": "http://foo.bar/employees/2"
}, {
"rel": "details",
"href": "http://foo.bar/employees/2/details"
} ]
} ]
{
"employeeID": 1,
"name": "Joe",
"_links": [ {
"rel": "self",
"href": "http://foo.bar/employees/1"
}, {
"rel": "details",
"href": "http://foo.bar/employees/1/details"
} ]
}
{
"employeeID": 1,
"name": "Joe",
"dob": "1985-04-23",
"address": "123 Main St",
"department": "Department of Redundant Links",
"_links": [ {
"rel": "self",
"href": "http://foo.bar/employees/1"
}, {
"rel": "details",
"href": "http://foo.bar/employees/1/details"
} ]
}
链接如下:
HTTP GET /employees/1
收益率:
[ {
"employeeID": 1,
"name": "Joe",
"_links": [ {
"rel": "self",
"href": "http://foo.bar/employees/1"
}, {
"rel": "details",
"href": "http://foo.bar/employees/1/details"
} ]
}, {
"employeeID": 2,
"name": "Sam",
"_links": [ {
"rel": "self",
"href": "http://foo.bar/employees/2"
}, {
"rel": "details",
"href": "http://foo.bar/employees/2/details"
} ]
} ]
{
"employeeID": 1,
"name": "Joe",
"_links": [ {
"rel": "self",
"href": "http://foo.bar/employees/1"
}, {
"rel": "details",
"href": "http://foo.bar/employees/1/details"
} ]
}
{
"employeeID": 1,
"name": "Joe",
"dob": "1985-04-23",
"address": "123 Main St",
"department": "Department of Redundant Links",
"_links": [ {
"rel": "self",
"href": "http://foo.bar/employees/1"
}, {
"rel": "details",
"href": "http://foo.bar/employees/1/details"
} ]
}
以下是另一个链接:
HTTP GET /employees/1/details
收益率:
[ {
"employeeID": 1,
"name": "Joe",
"_links": [ {
"rel": "self",
"href": "http://foo.bar/employees/1"
}, {
"rel": "details",
"href": "http://foo.bar/employees/1/details"
} ]
}, {
"employeeID": 2,
"name": "Sam",
"_links": [ {
"rel": "self",
"href": "http://foo.bar/employees/2"
}, {
"rel": "details",
"href": "http://foo.bar/employees/2/details"
} ]
} ]
{
"employeeID": 1,
"name": "Joe",
"_links": [ {
"rel": "self",
"href": "http://foo.bar/employees/1"
}, {
"rel": "details",
"href": "http://foo.bar/employees/1/details"
} ]
}
{
"employeeID": 1,
"name": "Joe",
"dob": "1985-04-23",
"address": "123 Main St",
"department": "Department of Redundant Links",
"_links": [ {
"rel": "self",
"href": "http://foo.bar/employees/1"
}, {
"rel": "details",
"href": "http://foo.bar/employees/1/details"
} ]
}
想要获得灵感,请查看可能是我见过的最好的答案。这个答案是在下面的评论中作为讨论的后续添加的 基本上,是的,我反对HATEOAS。为什么?总的来说,这个想法是好的,但是:
/data/{id}/Add/
,它将通过\u链接
元字段进行记录。这不是应该怎么做的。通过这种方式,您可以始终添加一个新端点和适当的链接,并以大量没有人能够理解或验证的端点结束。例如,此链接返回基本数据集:
"http://foo.bar/employees/1"
这将返回更多详细信息:
"http://foo.bar/employees/1/details"
如果我需要其他细节的子集呢?我要添加一个新端点吗?和。。如果有多个不同的客户端需要相互排斥的
数据子集?每个客户端都有一个专用的端点?这是一场噩梦当资源的版本发生更改(添加或删除新字段)时,应使用标题,而不需要特定字段或资源的子集。所以在我看来,这不是一条路 方法#3 这是一个完全不好的主意,因为在这个答案的介绍中提到的原因 方法#2 我知道这是一条路要走。正如@leeor所回答的,这是一种流行的、被接受的、灵活的模式
您可以通过添加名为
视图
的查询参数来扩展它,该参数是一个枚举(简单
,扩展
,完整
),表示预定义视图的列表。这是避免添加新端点的方法。而是添加并记录(!)新视图。如果视图
和字段
是互斥的,或者它们的处理顺序由您决定。查询字符串是解决方法。这是放置过滤参数的一般位置Swell,我投票表决这里讨论的#1内容协商:我错过了更新,目前我们产品中的REST API符合Richardson的2级;s成熟度模型。我理解这会取消API被称为真正RESTful的资格。没有计划