使用Spring客户端浏览HATEOAS

4
我们有一个使用Spring JPA的API,通过REST方式提供对数据库中某些数据的访问。我们以HATEOAS形式公开此API(使用Spring实现)。
现在我们正在考虑是坚持使用这种方法还是手动编写自己的REST接口。我已经阅读了很多关于HATEOAS的文章,但不确定使用它的重大优势是什么。当然,我知道可以使用链接浏览它,但我仍然必须知道每个级别的链接是否存在,对吗?
为了说明我的问题,假设我有以下结构:
server.com/
- /store
- /users/

server.com/users
- /managers/
- /other/

server.com/managers
- list of entities with ids

我希望使用这个API并获取所有“manager”实体(位于server.com/users/managers下)。

当使用Spring Boot链接时,正确的方法是什么?

选项一:

  RequestEntity<Void> request = RequestEntity.get("server.com/users/managers").accept(HAL_JSON).build();
  final Resource<Manager> managers = restTemplate.exchange(request, new ResourcesType<Manager>() {
        }).getBody();

选项二:
   // global endpoint
   RequestEntity<Void> request = RequestEntity.get("server.com").accept(HAL_JSON).build();
   final Resource<Object> rootLinks = restTemplate.exchange(request, new ResourceType<Object>() {
        }).getBody();

    Links links = new Links(rootLinks.getLinks());
    final Link userLink = links.getLink("users").expand();

    // users endpoint
    request = RequestEntity.get(URI.create(userLink.getHref())).accept(HAL_JSON).build();
    final Resource<Object> managerLinks = restTemplate.exchange(request, new ResourceType<Object>() {
        }).getBody();

    links = new Links(managerLinks.getLinks());
    final Link managerLink = links.getLink("managers").expand();

    // managers endpoint
    request = RequestEntity.get(URI.create(managerLink.getHref())).accept(HAL_JSON).build();
    final Resources<Manager> resourceAccounts = restTemplate.exchange(request, new ResourcesType<Manager>() {
        }).getBody();

第一种方法似乎很直接,我可以通过单个请求获取所有实体。然而,如果我只使用这种方法,我无法看到Hateoas的好处。Spring文档指出,不建议使用硬编码链接。
第二种方法似乎更符合Hateoas的风格,但它需要创建三个请求才能访问资源,而我已经知道了该资源的位置。这也不太对。
我知道这可能是一个愚蠢的问题,但有人能解释一下我明显忽略的Hateoas背后的伟大思想吗?

我不明白为什么需要知道"managers"是"users"的子路径("users/managers")。我认为你应该直接从根节点("global")公开链接到"users/managers"(以及所有其他经常使用的资源)。这样,您可以重新排列URL(例如"staff/managers")而不更改客户端。正如一位同事曾经说过的那样:"不要过多考虑URL结构,更多地关注资源类型"。 - Harald K
那么,Hateoas 的目的是在你不知道 API 任何信息时帮助导航?这个 API 主要通过我们系统中的其他服务进行编程访问(没有人类交互)。我猜在这里 Hateoas 没有用处...但你总是必须至少了解一些结构,对吧?我只是感觉自己完全没有理解 Hateoas 的重点。 - Smajl
这里仍然很有用。REST API通常不是(直接)供人类使用的。你肯定需要了解API的一些内容。关键是,你需要知道资源类型及其关系,而不是它们的URL结构。虽然我不是专家,所以暂时不会回答你的问题。;-) - Harald K
为什么你不会使用 _Spring Traverson_? - Ivan Aracki
@Raca 是的,我刚刚发现了 Traverson - 它看起来很不错。但它仍然会执行三个 http 请求,对吧? - Smajl
显示剩余2条评论
1个回答

0

使用HATEOAS,服务器可以通过提供的链接指导客户端。服务器和客户端之间的契约是链接的关系类型和媒体类型。通过在同一资源表示上提供或不提供链接,服务器可以向客户端提供信息,例如资源是否处于启用或未启用编辑状态,或用户是否被授权对资源进行某些操作等。服务器可以更改URL而不违反合同。


我已经知道了。我的问题是:“如果您以编程方式访问服务器程序,并且已经知道目标URI,这有什么好处??您仍然必须至少了解'rel'字符串。我只是不明白这如何对我有所帮助。” - Smajl
如果你控制一个服务器和一个客户端,那么你知道某些资源的URL,但你不知道服务器可以通过提供或不提供链接来给出的其他信息。如果服务器端不受你的控制,那么资源的URL可能会发生变化,这将破坏你的客户端。如果你需要性能优化,你可以像@haraldK所写的那样,直接从根("全局")端点暴露一个链接给"用户/管理者"(以及所有其他经常使用的资源)。 - Denis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接