2

自 2005 年以来,我逐步构建了一个相当大的 POJO 域模型。我们还在同一时间框架内逐步开发了 XSD。目前,我以以下方式使用 xmlbeans 来生成要通过 HTTP 发送的 xml,并作为 WebService 响应的一部分。

  1. 使用 xmlbeans 从 XSD 生成绑定代码
  2. 写了很多从我的域 POJO 填充绑定代码的映射器(也是相反的)
  3. 将其编组为 XML
  4. 对于 Web 服务,我们使用Axis 1.4,它可以使用 xmlbeans 生成的序列化/反序列化工厂。这允许我们在两个端点上重用相同的代码:XML over HTTP 和 SOAP/HTTP

现在,我们想开始使用 JAXB,因为它是成熟的、标准的、支持多租户(至少是 Moxy 实现),而且作为 xmlbeans 的一部分已经没有多少工作要做了。所以我的问题是

  1. 如何在不生成绑定代码的情况下使用 JAXB。即我不想再编写或维护映射代码(第 2 步)。我想知道我是否可以以某种方式使用 JAXB 直接解组到我的域 POJO?
  2. 如何将此与我的 WebService 集成?我的 web 服务使用相同的模式并且不想复制映射。
  3. 还有其他最佳实践建议吗?
  4. 我应该注意的任何陷阱/经验教训?
4

1 回答 1

2

注意: 我是EclipseLink JAXB (MOXy)负责人,也是JAXB (JSR-222)专家组的成员。

1 - 如何在不生成绑定代码的情况下使用 JAXB。即我不想再编写或维护映射代码(第 2 步)。我想知道我是否可以以某种方式使用 JAXB 直接解组到我的域 POJO?

使用您自己的域对象的关键是基于路径的映射。如果没有这个,绑定框架使用的模型必须非常类似于 XML 文档。下面是一个我想给出的示例,其中一个简单的地址对象映射到Google Geocoding API V2的结果。

package blog.geocode;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement(name="kml")
@XmlType(propOrder={"country", "state", "city", "street", "postalCode"})
public class Address {

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:SubAdministrativeArea/ns:Locality/ns:Thoroughfare/ns:ThoroughfareName/text()")
    private String street;

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:SubAdministrativeArea/ns:Locality/ns:LocalityName/text()")
    private String city;

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:AdministrativeAreaName/text()")
    private String state;

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:CountryNameCode/text()")
    private String country;

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:SubAdministrativeArea/ns:Locality/ns:PostalCode/ns:PostalCodeNumber/text()")
    private String postalCode;

}

下面是一个示例的链接,其中相同的对象模型映射到 Google 和 Yahoo 天气服务:


2 - 如何将它与我的 WebService 集成?我的 web 服务使用相同的模式并且不想复制映射。

如果 Axis 支持多个 JAXB 提供程序,那么您应该能够在没有太多配置的情况下利用 MOXy。可能只需jaxb.properties在与域模型相同的包中添加文件即可。


3 - 还有其他最佳实践建议吗?

如果您想避免将任何编译时依赖项添加到您的域模型中,那么您可能需要考虑将元数据表示为 XML。


更新

以下是您通过评论提出的问题的答案:

我知道 Web 服务 API 的一个限制是它们与“xjc 生成的工厂”相悖。在这种情况下,我相信我不能再使用 XPath 映射。如果我错了,请纠正我。另外,如果我使用注释,我还需要使用 xjc 吗?

我不确定 CXF,但标准 JAX-WS 实现允许您从自己的域模型开始,或通过 XJC 生成一个。以下是在 JAX-WS 环境中使用 Java 对象时使用 MOXy 的几个示例:


我认为这是使用 XPath 以外的另一种选择,如果我需要支持多租户,这也是唯一的选择。

外部映射文档不是 XPath 的替代品,它只是另一种指定元数据的方式。有些人更喜欢这种方法,如果他们不想在类上引入任何 MOXy 依赖项,这些依赖项将用于更多的对象到 XML 或对象到 JSON 的转换。对于多租户,我经常注释所有共享属性,然后为每个租户创建一个映射文档来映射扩展。


此外,如果我走 XPath 路线或选择 XML 中的元数据,是否会对性能产生影响?

使用基于路径的映射对性能没有任何影响。JAXBContext这一切都在初始化时得到优化。当引导外部绑定文档时,JAXBContext创建速度会稍微慢一些,因为需要做更多的工作,但由于 JAXB/MOXy 是异常配置,因此这些文档往往很小。对使用外部映射文档的Marshaller/没有影响。Unmarshaller

于 2012-07-31T20:00:26.767 回答