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

时间:2012-01-16 18:19:16

标签: java web-services rest jaxb domain-driven-design

我们有一个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;
    }
}

但我想要返回的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>

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

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

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

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

是否有其他方法可以帮助我避免DTO,但仍然保持对域模型的透明度?

2 个答案:

答案 0 :(得分:2)

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

最安全,最简单的方法是包装类(在其上使用JAXB序列化注释),它将代理到DAO层以获取所需的信息。虽然这可能是相当多的代码编写,但至少可以很容易地获得这样的代码。花哨的自动化装饰会更加困难。

答案 1 :(得分:0)

RESTEasy支持通过原子或标题链接的链接。您可以通过一些额外的注释来指向链接的服务。请参阅RESTEasy文档的第8章。