如何最好地在XML中实现HATEOAS的链接关系?

HDa*_*ave 5 java rest domain-driven-design web-services jaxb

我们有一个Java服务器Web应用程序,其中系统的核心包含一个非常复杂的域模型,该模型是根据域驱动设计的原则设计的.在大多数情况下,这些域对象在应用程序的其他问题上影响很小.

我们现在希望在系统前放置一个REST Web服务API,我正在努力解决如何最好地实现我们自己的新媒体类型中的HATEOAS链接.例如,假设我们的域类foo具有带有JAX-B注释的id和name属性:

@XmlType(name = "foo")
public class FooImpl implements Foo {

    private String name;
    private String id;

    ...snip....

@XmlID
@XmlAttribute
@Override
public String getId() {
    return id;
}

    @XmlElement
    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(final String name) {
        this.name = name;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是我想要返回的XML看起来像这样:

<foo id="123" href="http://myserver.com/foos/123">
   <name>myFoo</name>
   <links>
          <link rel="previous" href="http://myserver.com/foos/122" type="application/mything+xml" />
          <link rel="next" href="http://myserver.com/foos/124" type="application/mything+xml" />
          <link rel="edit" href="http://myserver.com/foos/123" type="application/mything+xml" />
          <link rel="revise" href="http://myserver.com/foos/123" method="put" type="application/mything+xml" />
          <link rel="cancel" href="http://myserver.com/foos/123?op="cancel"" method="post" type="application/mything+xml" />
   </links>
</foo>
Run Code Online (Sandbox Code Playgroud)

最好的方法是什么,这样我没有使用这些媒体类型链接污染我的域设计,但仍然可以使用JAX-B的强大功能进行XML编组?以下是一些想法:

1)JAX-B适配器 - 我可以使用它们来修改实体的XML并插入链接.它可能吗?合理吗?任何例子?

2)DTO层 - 创建一个新的REST服务层,用于在DTO中转换我的域对象.到目前为止,我们已经能够避免DTO的麻烦.虽然这将为我们返回客户端提供完全的灵活性,但我也不打算在此处创建与域无关的客户端.

3)链接标题 - 我真的很喜欢这个想法,但我认为它不会起作用(单独使用),因为有时我们的资源包含子资源的集合.在这种情况下,子资源仍然必须编组为包含链接/ hrefs等的XML.因此,虽然链接头解决了顶级类型的问题,但它并不能解决整个问题.随便说不然!

是否有另一种方法可以帮助我避免DTO并对域模型保持透明?

Don*_*ows 2

问题在于,正确生成链接需要了解生成链接的上下文,这反过来意味着简单的 JAXB 拦截器无法完成这项工作:它们根本不知道要插入什么 URL。此外,生成下一个和上一个链接需要知道这些值是什么;说它们是连续的可能并不安全,因为这意味着当删除某些其他资源时,资源会更改其 URL,这将是疯狂的。

最安全、最简单的方法是使用包装类(带有 JAXB 序列化注释),它委托 DAO 层获取所需的信息。虽然这可能需要编写大量代码,但至少很容易正确编写这些代码。花哨的自动化装饰会困难得多。