在Spring Data Rest中选择性禁用HATEOAS格式

25

假设我有一个现有的应用程序,它有两个端点/people和/pants。调用 GET /people 返回:

[
    {
        "name":"john",
        "age":37,
        "pants":[
            {
                "color":"green",
                "brand":"levis",
                "size":"medium"
            },
            {
                "color":"indigo",
                "brand":"jncos",
                "size":"medium-with-huge-legs"
            }
        ]
    },
    {
        "name":"june",
        "age":23,
        "pants":[
            {
                "color":"pink",
                "brand":"gap",
                "size":"small"
            }
        ]
    }
]

如果我使用Spring Data Rest并调用GET /person,我会收到类似以下内容:

{
    "_links":{
        "next":{
            "href":"http://myapp.com/people?page=1&size=20"
        },
        "self":{
            "href":"http://myapp.com/people{&page,size,sort}",
            "templated":true
        },
        "search":{
            "href":"http://myapp.com/people/search"
        }
    },
    "_embedded":{
        "people":[
            {
                "name":"john",
                "age":37,
                "_links":{
                    "self":{
                        "href":"http://myapp.com/people/john"
                    },
                    "pants":{
                        "href":"http://myapp.com/people/john/pants"
                    }
                }
            },
            {
                "name":"june",
                "age":23,
                "_links":{
                    "self":{
                        "href":"http://myapp.com/people/june"
                    },
                    "pants":{
                        "href":"http://myapp.com/people/june/pants"
                    }
                }
            }
        ]
    }
}

假设已经有一些现有的客户端,我不想改变他们 - 在某些情况下(比如Accept="application/json"),有没有办法禁用响应中的超媒体部分,但对于其他情况(比如Accept="hal+json"),启用它们?

谢谢!

更新

好的-看起来令我烦恼的是,我想要做的事情并不受支持。我理解为什么Spring Data Rest强烈倾向于超媒体...但我不认为提供基于标题“禁用”超媒体的功能从而提供更多选项是件坏事。

尽管如此,我有点不确定如何通过自己的控制器实现这一点。如果我创建一个控制器并尝试使用produces = "application/json"覆盖/people RequestMapping,则可以使用Accept="application/json"获取“原始”json,但是如果我传递Accept="application/hal+json",我会收到406和“找不到可接受的表示”的错误。看起来SDR资源映射没有与内容类型映射...有任何建议吗?


是的,您需要使用不同的Accept头来完成它。 - Jonathan W
Jonathan,问题实际上并不在于如何知道何时返回非HATEOAS响应,而是如何使Spring Data Rest不生成响应中的超媒体元素。 - Ben M
1
我相信Spring Data REST在此使用了两个不同的HttpMessageConverters,并且它们是在一个链中。如果Accept头指示application/hal+json,则TypeConstrainedMappingJackson2HttpMessageConverter将处理它并生成HAL。然而,如果头只是'application/json',则常规的MappingJackson2HttpMessageConverter会启动,并且不会序列化为HAL。不确定这是否有帮助,但我会尝试调整后者的转换器以不返回超媒体链接。 - Jonathan W
1个回答

21
简短的回答是,如果没有HATEOAS,您无法使用spring-data-rest。如果您想要构建没有HATEOAS的Web服务,您将不得不编写自己的控制器(这些控制器仍然可以使用spring-data存储库)。
引用Oliver Gierke在这篇SO帖子中的话:
“事实上,我的整个观点是:服务器只是在做体面的REST。如果这会打破客户端,那么就需要修复(调整)客户端。因此,超媒体方面对于Spring Data REST来说是基本的,我们不会退出。这可能在您具体的情况下不太令人满意,但至少应该回答问题:)。 - Oliver Gierke”

25
我很惊讶你无法覆盖序列化器/消息转换器,以便不输出链接...看起来应该是可能的。 - Chris DaMour
9
我接受了这个答案,但是7年后,我仍然根本不同意Drotbohm对HATEOAS的坚持。我认为时间继续向我们展示,实际上非常非常少的消费者真正感兴趣或能够利用其提供的便利。 - Ben M
5
七年后,我同意你的观点。 :) - gyoder

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