让我们假设我想设计一个REST api,它讲述歌曲,专辑和艺术家(实际上我是这样的,就像我之前的1312414人一样)。
歌曲资源始终与其所属的专辑相关联。相反,专辑资源与其包含的所有歌曲相关联。这些关联通过链接在资源表示中表示。
因此,表示看起来像这样:
{
song: 'xyz',
links: [
{ rel: 'album', url: '.../albums/abc' }
]
}
{
album: 'abc',
links: [
{ rel: 'song', url: '.../songs/xyz' },
{ rel: 'song', url: '...' },
{ rel: 'song', url: '...' },
{ rel: 'song', url: '...' }
]
}
鉴于,我希望这一点成立(也许问题在于“给定”),那么我如何设计我的API,以便创建专辑或歌曲资源不会对以前存在的副作用歌曲或专辑资源?
这是某种鸡/蛋问题。如果我首先创建歌曲资源(POST / songs /)然后创建专辑资源(POST /专辑/),则歌曲资源会在专辑创建过程中被修改(根据REST原则这是不好的),因为该关联两个资源之间正在服务器上更新。同样,对于我首先创建专辑的场景,第二首歌曲。
我想我可以通过避免服务器上的副作用并将管理双向关系的负担传递给客户端来避免整个问题。
另外,我不希望专辑和歌曲作为一个整体原点创作。
我现在唯一能想到的是,通过使用表示来响应资源创建,将上述副作用包含在我的API的语义中,该表示包含已作为结果修改的资源的链接列表请求。这使得副作用显而易见,但仍然不安宁。
答案 0 :(得分:1)
没有任何关于REST的说法,操纵一个资源的状态不能改变另一个资源的状态。关于最接近的REST得到的是幂等行为的概念,它只表示重复它们将导致相同的状态。
因此,在您的情况下,Song
资源无法有效地将其自身添加到Album
资源中。 Album
资源能够说Song
资源是其中的一部分,也没有任何内在错误。
现在,根据您的业务需求,您可能想要a。)更改您表示歌曲/专辑的方式或b。)允许歌曲/专辑以m / m方式而不是1/1相关。原因在于,根据您的数据结构和选择系统中的资源(即可寻址单位),您实际上是在建模不同的数据关系,我认为这是您面临的问题的症结所在。
在系统中使用Songs
和Albums
个独立资源时,强制执行更严格的关系(如1/1而不是m / m)需要在内容类型中添加更多工作和规范。你必须处理两个不同的专辑都认为它们包含一首歌的情况,但1/1关系不允许这样。
如果您有一个Album
对象显式包含或拥有 Song
个对象,那么问题就少了,因为{{ 1}}只能操纵它自己的歌曲,而不能操纵任何其他Album
的歌曲。然而,此更改了数据模型,因为Album
不再是一等公民,而是在拥有它们的相册下面。
这是整个问题的关键点...... 你必须决定谁拥有这种关系。
双方(Songs
和Album
)拥有它并没有错。这对于m / m关系非常有效,但对于1/1关系,这需要更多的管理开销(即其他实际拥有关系的东西)。
但是,如果你想要一个没有所有开销的1/1关系,你必须让一个参与实体拥有这个关系,这意味着只有一个改变它的途径......通过拥有实体。