37.2. 在 Java 中替换组
概述
Apache CXF (如 JAXB 规范中指定的)支持使用 Java 的原生类层次结构替换组,并结合 JAXBElement
类对通配符定义的支持。由于替换组的成员必须全部共享一个共同的基础类型,因此生成的类以支持元素的类型也共享一个通用基本类型。另外,Apache CXF 将 head 元素的实例映射到 JAXBElement<?扩展了 T>
属性。
生成的对象工厂方法
对象工厂生成来支持包含替换组的软件包有方法,对于替换组中的每个元素都有方法。对于替换组的每个成员,除 head 元素外,@XmlElementDecl
注解会减少对象工厂方法包含两个额外属性,如 表 37.1 “Declaring a JAXB Elements 的属性是 Substitution Group 的成员” 所述。
属性 | 描述 |
---|---|
| 指定定义 head 元素的命名空间。 |
|
指定 head 元素的 |
替换组的 @XmlElementDecl
的 head 元素的对象工厂方法仅包含 default 命名空间
属性和默认 name
属性。
除了元素实例化方法外,对象工厂还包含一个代表头元素的对象实例化的方法。如果替换组的成员是所有复杂的类型,则对象工厂还包含用于实例化各种复杂类型的实例的方法。
例 37.5 “Substitution Group 的对象因素方法” 显示 例 37.2 “使用复杂类型替换组” 中定义的替换组的对象工厂方法。
例 37.5. Substitution Group 的对象因素方法
public class ObjectFactory { private final static QName _Widget_QNAME = new QName(...); private final static QName _PlasticWidget_QNAME = new QName(...); private final static QName _WoodWidget_QNAME = new QName(...); public ObjectFactory() { } public WidgetType createWidgetType() { return new WidgetType(); } public PlasticWidgetType createPlasticWidgetType() { return new PlasticWidgetType(); } public WoodWidgetType createWoodWidgetType() { return new WoodWidgetType(); } @XmlElementDecl(namespace="...", name = "widget") public JAXBElement<WidgetType> createWidget(WidgetType value) { return new JAXBElement<WidgetType>(_Widget_QNAME, WidgetType.class, null, value); } @XmlElementDecl(namespace = "...", name = "plasticWidget", substitutionHeadNamespace = "...", substitutionHeadName = "widget") public JAXBElement<PlasticWidgetType> createPlasticWidget(PlasticWidgetType value) { return new JAXBElement<PlasticWidgetType>(_PlasticWidget_QNAME, PlasticWidgetType.class, null, value); } @XmlElementDecl(namespace = "...", name = "woodWidget", substitutionHeadNamespace = "...", substitutionHeadName = "widget") public JAXBElement<WoodWidgetType> createWoodWidget(WoodWidgetType value) { return new JAXBElement<WoodWidgetType>(_WoodWidget_QNAME, WoodWidgetType.class, null, value); } }
替换接口中的组
如果替换组的 head 元素用作操作消息之一中的消息部分,则生成的方法参数将是生成的类的对象,以支持该元素。它不一定是 JAXBElement< 扩展 T&
gt; 类的实例。运行时依赖于 Java 的原生类型层次结构来支持类型替换,Java 将捕获任何尝试使用不受支持的类型。
为确保运行时知道需要支持元素替换的所有类,SEI 被解码为 @XmlSeeAlso
注释。此注解指定运行时为 marshalling 所需的类列表。有关使用 @XmlSeeAlso
注释的更多信息,请参阅 第 32.4 节 “在 Runtime Marshaller 中添加类”。
例 37.7 “使用 Substitution Group 生成的接口” 显示为 例 37.6 “使用 Substution Group 的 WSDL 接口” 中显示的接口生成的 SEI。接口使用 例 37.2 “使用复杂类型替换组” 中定义的替换组。
例 37.6. 使用 Substution Group 的 WSDL 接口
<message name="widgetMessage"> <part name="widgetPart" element="xsd1:widget" /> </message> <message name="numWidgets"> <part name="numInventory" type="xsd:int" /> </message> <message name="badSize"> <part name="numInventory" type="xsd:int" /> </message> <portType name="orderWidgets"> <operation name="placeWidgetOrder"> <input message="tns:widgetOrder" name="order" /> <output message="tns:widgetOrderBill" name="bill" /> <fault message="tns:badSize" name="sizeFault" /> </operation> <operation name="checkWidgets"> <input message="tns:widgetMessage" name="request" /> <output message="tns:numWidgets" name="response" /> </operation> </portType>
例 37.7. 使用 Substitution Group 生成的接口
@WebService(targetNamespace = "...", name = "orderWidgets")
@XmlSeeAlso({com.widgetvendor.types.widgettypes.ObjectFactory.class})
public interface OrderWidgets {
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@WebResult(name = "numInventory", targetNamespace = "", partName = "numInventory")
@WebMethod
public int checkWidgets(
@WebParam(partName = "widgetPart", name = "widget", targetNamespace = "...")
com.widgetvendor.types.widgettypes.WidgetType widgetPart
);
}
例 37.7 “使用 Substitution Group 生成的接口” 中显示的 SEI 列出 @XmlSeeAlso
注解中的对象工厂。列出命名空间的对象工厂提供对该命名空间生成的所有类的访问。
用复杂类型替换组
当替换组的 head 元素用作复杂类型中的元素时,代码生成器将元素映射到 JAXBElement<?扩展了 T>
属性。它不会将它映射到包含所生成的类实例的属性,以支持替换组。
例如: 例 37.8 “使用 Substitution Group 的复杂类型” 中定义的复杂类型会导致 Java 类在 例 37.9 “使用 Substitution Group 进行复杂类型的 Java 类” 中显示。复杂类型使用 例 37.2 “使用复杂类型替换组” 中定义的替换组。
例 37.8. 使用 Substitution Group 的复杂类型
<complexType name="widgetOrderInfo">
<sequence>
<element name="amount" type="xsd:int"/>
<element ref="xsd1:widget"/>
</sequence>
</complexType>
例 37.9. 使用 Substitution Group 进行复杂类型的 Java 类
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "widgetOrderInfo", propOrder = {"amount","widget",}) public class WidgetOrderInfo { protected int amount; @XmlElementRef(name = "widget", namespace = "...", type = JAXBElement.class) protected JAXBElement<? extends WidgetType> widget; public int getAmount() { return amount; } public void setAmount(int value) { this.amount = value; } public JAXBElement<? extends WidgetType> getWidget() { return widget; } public void setWidget(JAXBElement<? extends WidgetType> value) { this.widget = ((JAXBElement<? extends WidgetType> ) value); } }
设置替换组属性
如何使用替换组来取决于将该组映射到直接 Java 类或 JAXBElement< 中的代码生成器?扩展了 T
> 类。当元素映射到生成值类的对象时,您可以使用对象的方式与作为类型层次结构一部分的其他 Java 对象搭配使用。您可以替换父类的任何子类。您可以检查对象,以确定其准确的类,并适当地广播对象。
JAXB 规格建议您使用对象工厂方法实例化所生成的类的对象。
当代码生成器创建 JAXBElement< 扩展了 T&
gt; 对象来保存替换组的实例时,您必须将元素的值嵌套在 JAXBElement< 中?扩展了 T>
对象。执行此操作的最佳方式是使用对象工厂提供的元素创建方法。它们提供了一种基于其值创建元素的简单方法。
例 37.10 “设置 Substitution 组的成员” 显示设置替换组实例的代码。
例 37.10. 设置 Substitution 组的成员
ObjectFactory of = new ObjectFactory(); PlasticWidgetType pWidget = of.createPlasticWidgetType(); pWidget.setShape = "round'; pWidget.setColor = "green"; pWidget.setMoldProcess = "injection"; JAXBElement<PlasticWidgetType> widget = of.createPlasticWidget(pWidget); WidgetOrderInfo order = of.createWidgetOrderInfo(); order.setWidget(widget);
例 37.10 “设置 Substitution 组的成员” 中的代码执行以下操作:
实例化对象工厂。
实例化 PlasticWidgetType
对象。
实例化 JAXBElement<PlasticWidgetType&
gt; 对象来容纳 plastic widget 元素。
实例化 WidgetOrderInfo
对象。
将 WidgetOrderInfo
对象的小部件设置为含有 plastic widget
元素的 JAXBElement
对象。
获取替换组属性的值
在从 JAXBElement< 中提取元素的值<中扩展了 T
> 对象时,对象工厂方法没有帮助。您必须使用 JAXBElement<?扩展了 T>
; 对象的 getValue ()
方法。以下选项决定了 getValue ()
方法返回的对象类型:
-
使用 all possible 类的
isInstance ()
方法来确定元素的值对象的类。 使用
JAXBElement<? 扩展 T
> 对象的getName ()
方法来确定元素的名称。getName ()
方法返回 QName。使用元素的本地名称,您可以为 value 对象确定正确的类。使用
JAXBElement<? 扩展 T
> 对象的getDeclaredType ()
方法来确定值对象的类。getDeclaredType ()
方法返回元素的值对象的Class
对象。警告无论 value 对象的实际类是什么,
getDeclaredType ()
方法可能会返回 head 元素的基础类。
例 37.11 “获得 Substitution 组成员的值” 显示从替换组检索值的代码。要确定元素的值对象的正确类,该示例使用了元素的 getName ()
方法。
例 37.11. 获得 Substitution 组成员的值
String elementName = order.getWidget().getName().getLocalPart(); if (elementName.equals("woodWidget") { WoodWidgetType widget=order.getWidget().getValue(); } else if (elementName.equals("plasticWidget") { PlasticWidgetType widget=order.getWidget().getValue(); } else { WidgetType widget=order.getWidget().getValue(); }