springhateoas_没有链接的HATEOAS

springhateoas

springhateoas

是的,我知道这个标题听起来很愚蠢,但是找不到更合适的名称。 因此,让我解释一下为什么我认为HATEOAS API中的链接并不总是那么有用。

如果您不知道HATEOAS是什么,建议您先阅读《超媒体REST API简介》

具有HATEOAS支持的REST API提供了两个用于将客户端和服务器分离的主要功能:

  1. 超媒体避免了客户端需要硬编码和构造URI。 这有助于服务器在将来发展REST-API。
  2. 链接的可用性告诉客户端可以对资源执行哪些操作。 这样可以避免服务器逻辑需要在客户端上重复。例如,假设客户需要决定是否在订单旁边显示付款按钮。 这样做的逻辑可能是:
    if (order.status == OPEN and order.paymentDate == null) {
        show payment button
    }

    使用HATEOAS,客户无需了解此逻辑。 支票变成:

    if (order.links.getByRel("payment") != null) {
        show payment button
    }

    服务器现在可以更改规则,该规则决定何时可以付款,而无需客户端更新。

这些功能的有用程度取决于您的应用程序,系统架构和客户端。

对于大多数使用CRUD操作的应用程序,第二点可能没什么大不了的。 但是,如果您的REST API服务于更复杂的域,则它可能非常有用。

第一点取决于您的客户,并在一定程度上取决于您的整体系统架构。 如果为公共客户端提供API,则至少某些客户端很有可能会硬编码请求URI,而不会使用您提供的链接。 在这种情况下,您会失去发展API的能力而不会破坏(至少一些)客户端。

如果您的客户不直接使用您的API响应,而是公开自己的API,那么他们也不太可能跟随您返回的链接。 例如,在使用Backend for Frontend模式时很容易发生这种情况。

考虑以下示例系统体系结构:

后端服务由其他两个系统使用。 两种系统都提供与系统特定后端通信的用户界面。 REST用于所有通信。

假设用户使用Android应用程序(1)执行操作。 该应用程序向移动后端(2)发送请求。 然后,移动后端可以与后端服务(3)通信以执行请求的操作。 在将响应发送回Anroid-App之前,移动后端还可以预处理,映射或聚合从后端服务检索到的数据。

现在回到HATEOAS。

如果此示例体系结构中的后端服务(3)提供了Hypermedia REST API,则客户端几乎无法利用HATEOAS相关的链接。

让我们看一下显示系统通信的序列图以查看问题:

后端服务(3)提供一个API入口点,该入口返回所有可用操作及其请求URI的列表。 移动后端(2)定期向该API入口点发送请求,并在本地缓存链接列表。

现在,假设Android-App(1)的用户想要访问特定的订单。 为了检索所需的信息,Anroid-App向移动后端(2)发送请求。 该请求的URI可能先前已从Mobile-Backends API入口点(未显示)中检索到。

为了从后端服务检索请求的订单,移动后端使用缓存链接列表中的订单详细信息链接。 后端服务返回带有HATEOAS链接的响应。 在此,订单付款链接指示可以付款。 现在,移动后端将响应转换为自己的返回格式,并将其发送回Android-App。

移动后端也可能返回HATEOAS响应。 因此,需要将来自后端服务的链接URI映射到适当的移动后端URI。 因此,Mobile-Backend会检查Backend-Service响应中是否存在订单付款链接。 如果是这种情况,它将在自己的响应中添加一个订单付款链接。

请注意,Mobile-Backend仅使用Backend-Service响应的关系( rel字段)。 URI被丢弃。

现在,用户想要支付订单。 Android-App使用先前检索到的订单付款链接将请求发送到移动后端。 现在,移动后端已失去上一个后端服务响应的上下文。 因此,它必须在缓存的链接列表中查找订单付款链接。 该过程以与上一个请求相同的方式继续

在此示例中,Android-App能够利用HATEOAS相关链接。 但是,Mobile-Backend无法使用Backend-Service响应返回的链接URI(API入口点除外)。 如果移动后端正在提供HATEOAS功能,则后端服务的链接关系可能会很有用。 始终从缓存的API入口点响应中查找后端服务请求的URI。

交流动作而不是链接

不幸的是,链接的构建并不总是那么简单,可能会花费一些额外的时间。 如果您知道客户不会使用这些链接,那么这将是浪费时间。

避免客户端上的逻辑重复的最简单方法是忽略链接,并在REST响应中使用简单的动作数组:

GET /orders/123
{
    "id": 123,
    "price": "$41.24 USD"
    "status": "open",
    "paymentDate": null,
    "items": [
        ...
    ]
    "actions": ["order-cancel", "order-payment", "order-update"]
}

这样,我们无需构造链接就可以传达可能的动作。 在这种情况下,响应告诉我们客户可以执行取消付款更新操作。

请注意,这甚至可能不会增加客户端和服务器之间的耦合。 客户端仍然可以在API入口点中查找那些动作的URI,而无需对URI进行硬编码。

一种替代方法是使用标准链接元素,而只是跳过href属性:

GET /orders/123
{
    "id": 123,
    "price": "$41.24 USD"
    "status": "open",
    "paymentDate": null,
    "items": [
        ...
    ]
    "links": [
        { "rel": "order-cancel" },
        { "rel": "order-payment" },
        { "rel": "order-update" },
    ]
}

但是,返回没有链接URI的links元素可能会有些混乱。

显然,您将通过两种描述的方法离开标准路径。 另一方面,如果不需要链接,则可能也不想使用标准化的HATEOAS响应格式(例如HAL )。

翻译自: https://www.javacodegeeks.com/2020/12/hateoas-without-links.html

springhateoas

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值