首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何设计HTTP端点,搜索单个资源实例并将其与另一个连接实例一起返回

如何设计HTTP端点,搜索单个资源实例并将其与另一个连接实例一起返回
EN

Software Engineering用户
提问于 2017-01-23 05:31:59
回答 3查看 1K关注 0票数 3

我有一个返回单元素集合的端点(我不只是返回对象实例以保持与资源即集合约定的一致性,所以只返回一个实例)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
GET /devices?serialNumber=12345
[
    {
        "id": 1, 
        "serialNumber": "12345"
    }
]

新的需求出现了:一些设备成对连接,在搜索与设备12345配对的设备78901时,我需要检索这两种设备(最好是在单个HTTP调用中)。我最好的选择是什么?我试过:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
GET /devices?serialNumber=12345
[
    {
        "id": 1, 
        "serialNumber": "12345"
    },
     {
        "id": 2, 
        "serialNumber": "78901"
    }
]

但这打破了语义(一个S/N的I过滤器设备资源“列表”,突然出现另一个具有不同S/N的设备)

然后我试了一下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
GET /devices?serialNumber=12345
[
    {
        "id": 1, 
        "serialNumber": "12345"
        "connected": 
        {
            "id": 2, 
            "serialNumber": "78901"
        }
    }
]

但是递归嵌套资源仍然感觉不太好,因为这与域模型的表达方式完全不同。是否有更好的方法来设计这个端点而不公开它们如何连接的细节?有一些业务逻辑非常复杂,与端点使用者无关,她只需要知道是否有配对的设备。

EN

回答 3

Software Engineering用户

回答已采纳

发布于 2017-01-23 05:58:23

但是递归嵌套资源仍然感觉不太好,因为这与域模型的表达方式完全不同。

没有充分的理由将您的API资源表示形式强烈地耦合到域模型中。他们以不同的需求为不同的客户服务,他们的设计模式也完全不同。

我建议您添加对查询参数?includeConnectedDevices=true的支持。那你就可以

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
GET /devices?serialNumber=12345
[
    {
        "id": 1, 
        "serialNumber": "12345"
    }
]

GET /devices?serialNumber=12345&includeConnectedDevices=true
[
    {
        "id": 1, 
        "serialNumber": "12345",
        "connected": 
        {
            "id": 2, 
            "serialNumber": "78901"
        }
    }
]

客户可以选择是否关心连接的设备(S)。作为一种奖励,您可以使用任意数量的连接。

不管你做什么,你都应该考虑包括一个或多个链接,从一个设备到它的连接设备(S)。这可能在标题中,或者作为实体的属性,或者您将响应包装在一个信封中。下面的链接比构建URL要好得多。那看起来可能像/devices?connectedTo=12345

票数 4
EN

Software Engineering用户

发布于 2017-01-23 06:00:08

您可以使用哈特奥链接您的资源,因此不必返回以下内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
GET /devices?serialNumber=12345
[
    {
        "id": 1, 
        "serialNumber": "12345"
    },
    {
        "id": 2, 
        "serialNumber": "78901"
    }
]

您可以返回如下内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
GET /devices?serialNumber=12345
    {
        "id": 1, 
        "serialNumber": "12345",
        "links":[
            {
               rel:"connected",
               "id":2,
               "serialNumber": "78901"
            }
        ]
    }

更新

@Ewan是完全正确的,应该是这样的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 GET /devices?serialNumber=12345
    {
        "id": 1, 
        "serialNumber": "12345",
        "links":[
            {
               "rel":"connected",
               "href":"http://yourserver.com/yourapp/devices?serialNumber=78901"
            }
        ]
    }

**第二次更新**(在喝了我早上的咖啡后)

如果您查看这些注释,您会发现,虽然最初的答案符合您的所有要求(我赞同@Eric关于“这不需要一个HTTP请求”),但是第一个更新是“标准”(至少其中一种)方法。IMHO您应该使用HATEOAS或HAL,或者其他一些众所周知的替代方法,而不是执行嵌套资源的操作。

票数 0
EN

Software Engineering用户

发布于 2017-01-23 19:54:24

出现了新的要求:一些设备成对连接,在搜索设备12345 (与设备78901配对时)时,我需要检索这两个设备(最好是在单个HTTP调用中)。我最好的选择是什么?

这将取决于你的约束。

有一种方法非常简单:认识到新的需求描述了设备12345的新视图。也就是说,它描述了一个新文档,这是描述新资源的另一种方式。

因此,为这个新报告找出一个名称,然后将该名称与您的URI拼写标准一起使用,以找到一种合理的方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
GET /devicePairs?eitherDevice=12345 ...

注意:向查询字符串添加另一个参数的艾瑞克的建议就是这种方法的一个例子--发明了一个新的URI来覆盖新的用例。

另一方面,如果新的要求是扩展现有表示,以便在可用时包含新信息,则不需要创建新的URI,但应该使用附加数据扩展现有表示。

这又取决于是否有支持扩展的媒体类型。简单的部分是输入数据;更难的部分是确保现有客户端不会中断。

您需要的基本契约是表示中的可选字段的概念,以及消费者必须忽略他们不承认的字段的概念。原子联合规范是这个思想的一个很好的参考实现。

在普通的旧JSON中,这可能看起来像

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
    "id": 1, 
    "serialNumber": "12345",
    "connectedTo" : "78901"
}

或者,您可能更倾向于在表示中明确扩展的概念。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
    "id": 1, 
    "serialNumber": "12345",
     extensions : {
        "connectedTo" : "78901"
     }
}

有很多不同的方法,你可以拼写这一点,但它真正的意义是确保您的表示是向后兼容的。

如果您的解决方案使用超媒体,则可以为扩展提供链接。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
    "id": 1, 
    "serialNumber": "12345",
     connectedTo : {
        "serialNumber" : "78901",
        "href" : "/devices?serialNumber=78901"
     }
}   

链接很适合扩展点,因此您可能会将其反转。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
    "id": 1, 
    "serialNumber": "12345",
     links : [
         {
             rel : "connectedTo",
             href : "/devices/78901"
             serialNumber : "78901"
         }
     ]
} 

继续移动表示,您最终会得到类似于硬件JSON API的东西。

票数 0
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/340737

复制
相关文章

相似问题

添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文