我们有一个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,但仍然保持对域模型的透明度?
答案 0 :(得分:2)
问题是正确生成链接需要知道生成链接的上下文,这反过来意味着简单的JAXB拦截器不能完成这项任务:他们根本不知道要插入什么URL。更重要的是,生成下一个和上一个链接将需要知道这些值是什么;说它们是连续的可能并不安全,因为这意味着当一些其他资源被删除时,资源会改变其URL,这将是疯狂的。
最安全,最简单的方法是包装类(在其上使用JAXB序列化注释),它将代理到DAO层以获取所需的信息。虽然这可能是相当多的代码编写,但至少可以很容易地获得这样的代码。花哨的自动化装饰会更加困难。
答案 1 :(得分:0)
RESTEasy支持通过原子或标题链接的链接。您可以通过一些额外的注释来指向链接的服务。请参阅RESTEasy文档的第8章。