37.3. 小部件供应商示例

37.3.1. 小部件顺序接口

本节演示了 Apache CXF 中用于解决真实应用的替换组示例。使用 例 37.2 “使用复杂类型替换组” 中定义的 widget 替换组来开发服务和消费者。该服务提供两个操作: checkWidgetplaceWidgetOrder例 37.12 “小部件顺序接口” 显示排序服务的接口。

例 37.12. 小部件顺序接口

<message name="widgetOrder">
  <part name="widgetOrderForm" type="xsd1:widgetOrderInfo"/>
</message>
<message name="widgetOrderBill">
  <part name="widgetOrderConformation"
        type="xsd1:widgetOrderBillInfo"/>
</message>
<message name="widgetMessage">
  <part name="widgetPart" element="xsd1:widget" />
</message>
<message name="numWidgets">
  <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"/>
  </operation>
  <operation name="checkWidgets">
    <input message="tns:widgetMessage" name="request" />
    <output message="tns:numWidgets" name="response" />
  </operation>
</portType>

例 37.13 “widget Ordering SEI” 显示为接口生成的 Java SEI。

例 37.13. widget Ordering SEI

@WebService(targetNamespace = "http://widgetVendor.com/widgetOrderForm", 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 = "http://widgetVendor.com/types/widgetTypes")
        com.widgetvendor.types.widgettypes.WidgetType widgetPart
    );

    @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
    @WebResult(name = "widgetOrderConformation", targetNamespace = "", partName = "widgetOrderConformation")
    @WebMethod
    public com.widgetvendor.types.widgettypes.WidgetOrderBillInfo placeWidgetOrder(
        @WebParam(partName = "widgetOrderForm", name = "widgetOrderForm", targetNamespace = "")
        com.widgetvendor.types.widgettypes.WidgetOrderInfo widgetOrderForm
    ) throws BadSize;
}
注意

因为该示例只显示使用替换组,所以并没有显示一些业务逻辑。

37.3.2. checkWidgets Operation

概述

checkWidgets 是一个简单操作,其参数是替换组的头成员。此操作演示了如何处理作为替换组的成员的单个参数。使用者必须确保 参数是替换组群的有效成员。该服务必须正确确定在请求中发送替换组的成员。

消费者实施

生成的方法签名使用 Java 类来支持替换组的 head 元素类型。由于替换组的成员元素是与 head 元素类型相同的类型,或者由 head 元素类型派生的 Java 类,生成的 Java 类从生成的 Java 类中继承为支持 head 元素的 Java 类。Java 类型层次结构原生支持使用子类来代替父类。

由于 Apache CXF 如何生成替换组和 Java 类型层次结构的类型,客户端可以在不使用任何特殊代码的情况下调用 checkWidgets()。当开发逻辑来调用 checkWidgets() 时,您可以传递一个类的对象,以支持 widget 替换组。

例 37.14 “消费者检查 检查Widgets() 显示调用 checkWidgets() 的使用者。

例 37.14. 消费者检查 检查Widgets()

System.out.println("What type of widgets do you want to order?");
System.out.println("1 - Normal");
System.out.println("2 - Wood");
System.out.println("3 - Plastic");
System.out.println("Selection [1-3]");
String selection = reader.readLine();
String trimmed = selection.trim();
char widgetType = trimmed.charAt(0);
switch (widgetType)
{
  case '1':
  {
    WidgetType widget = new WidgetType();
    ...
    break;
  }
  case '2':
  {
    WoodWidgetType widget = new WoodWidgetType();
    ...
    break;
  }
  case '3':
  {
    PlasticWidgetType widget = new PlasticWidgetType();
    ...
    break;
  }
  default :
    System.out.println("Invaid Widget Selection!!");
}

proxy.checkWidgets(widgets);

服务实施

该服务的 checkWidgets() 实施会将一个小部件描述作为 widget Type 对象获取,检查小部件清单,并返回库存中的小部件数量。由于用于实施替换组的所有类都会从同一基础类继承,因此您可以在不使用任何 JAXB 特定的 API 的情况下实施 checkWidgets()

生成的所有类,以支持 widget 的 replace 组的成员扩展 widget Type 类。由于这一事实,您可以使用 instanceof 确定传递的小部件类型,只需在适当的时将 widgetPart 对象转换为更严格的类型。具有正确类型对象后,您可以检查正确类型的小部件。

例 37.15 “checkWidgets()的服务实施” 显示可能的实施。

例 37.15. checkWidgets()的服务实施

public int checkWidgets(WidgetType widgetPart)
{
  if (widgetPart instanceof WidgetType)
  {
    return checkWidgetInventory(widgetType);
  }
  else if (widgetPart instanceof WoodWidgetType)
  {
    WoodWidgetType widget = (WoodWidgetType)widgetPart;
    return checkWoodWidgetInventory(widget);
  }
  else if (widgetPart instanceof PlasticWidgetType)
  {
    PlasticWidgetType widget = (PlasticWidgetType)widgetPart;
    return checkPlasticWidgetInventory(widget);
  }
}

37.3.3. placeWidgetOrder Operation

概述

placeWidgetOrder 使用两个包含替换组的复杂类型。此操作演示了如何在 Java 实施中使用此类结构。使用者和服务都必须获取和设置替换组的成员。

消费者实施

若要调用 placeWidgetOrder(),消费者必须构建包含 widget 替换组的一个元素的小部件顺序。在顺序中添加小部件时,使用者应使用为替换组的每个元素生成的对象工厂方法。这样可确保运行时和服务可以正确处理顺序。例如,如果将某一顺序放在了白板的小部件中,则使用 ObjectFactory.createPlasticWidget() 方法在添加元素前创建该元素。

例 37.16 “设置子组成员” 显示用于设置 widget OrderInfo 对象的 widget 属性的使用者代码。

例 37.16. 设置子组成员

ObjectFactory of = new ObjectFactory();

WidgetOrderInfo order = new of.createWidgetOrderInfo();
...
System.out.println();
System.out.println("What color widgets do you want to order?");
String color = reader.readLine();
System.out.println();
System.out.println("What shape widgets do you want to order?");
String shape = reader.readLine();
System.out.println();
System.out.println("What type of widgets do you want to order?");
System.out.println("1 - Normal");
System.out.println("2 - Wood");
System.out.println("3 - Plastic");
System.out.println("Selection [1-3]");
String selection = reader.readLine();
String trimmed = selection.trim();
char widgetType = trimmed.charAt(0);
switch (widgetType)
{
  case '1':
  {
    WidgetType widget = of.createWidgetType();
    widget.setColor(color);
    widget.setShape(shape);
    JAXB<WidgetType> widgetElement = of.createWidget(widget); order.setWidget(widgetElement);
    break;
  }
  case '2':
  {
    WoodWidgetType woodWidget = of.createWoodWidgetType();
    woodWidget.setColor(color);
    woodWidget.setShape(shape);
    System.out.println();
    System.out.println("What type of wood are your widgets?");
    String wood = reader.readLine();
    woodWidget.setWoodType(wood);
    JAXB<WoodWidgetType> widgetElement = of.createWoodWidget(woodWidget); order.setWoodWidget(widgetElement);
    break;
  }
  case '3':
  {
    PlasticWidgetType plasticWidget = of.createPlasticWidgetType();
    plasticWidget.setColor(color);
    plasticWidget.setShape(shape);
    System.out.println();
    System.out.println("What type of mold to use for your
                        widgets?");
    String mold = reader.readLine();
    plasticWidget.setMoldProcess(mold);
    JAXB<WidgetType> widgetElement = of.createPlasticWidget(plasticWidget); order.setPlasticWidget(widgetElement);
    break;
  }
  default :
    System.out.println("Invaid Widget Selection!!");
    }

服务实施

placeWidgetOrder() 方法以 小部件OrderInfo 对象的形式收到一个顺序,处理该顺序,并以 小部件OrderBillInfo 对象的形式向使用者返回计费。订购可以采用普通小部件、一个白板小部件或一个 wooden 小部件。排序小部件的类型由哪些对象类型存储在 widgetOrderForm 对象的 widget 属性中。widget 属性是一个替换组,可以包含 widget 元素、woodWidget 元素或 plasticWidget 元素。

实施必须确定哪些元素按顺序存储。这可以使用 JAXBElement< 来完成?如何扩展 T& gt; 对象的 getName() 方法,以确定该元素的 QName。然后,可以使用 QName 确定替换组中的哪个元素的顺序。知道 bill 中的元素后,您可以将其值提取到正确的对象类型。

例 37.17 “placeWidgetOrder()的实施” 显示可能的实施。

例 37.17. placeWidgetOrder()的实施

public com.widgetvendor.types.widgettypes.WidgetOrderBillInfo placeWidgetOrder(WidgetOrderInfo widgetOrderForm)
{
  ObjectFactory of = new ObjectFactory();

  WidgetOrderBillInfo bill = new WidgetOrderBillInfo()

   // Copy the shipping address and the number of widgets
   // ordered from widgetOrderForm to bill
   ...

  int numOrdered = widgetOrderForm.getAmount();

  String elementName = widgetOrderForm.getWidget().getName().getLocalPart();
  if (elementName.equals("woodWidget")
  {
    WoodWidgetType widget=order.getWidget().getValue();
    buildWoodWidget(widget, numOrdered);

    // Add the widget info to bill
    JAXBElement<WoodWidgetType> widgetElement = of.createWoodWidget(widget);
    bill.setWidget(widgetElement);

    float amtDue = numOrdered * 0.75;
    bill.setAmountDue(amtDue);
  }
  else if (elementName.equals("plasticWidget")
  {
    PlasticWidgetType widget=order.getWidget().getValue();
    buildPlasticWidget(widget, numOrdered);

    // Add the widget info to bill
    JAXBElement<PlasticWidgetType> widgetElement = of.createPlasticWidget(widget);
    bill.setWidget(widgetElement);

    float amtDue = numOrdered * 0.90;
    bill.setAmountDue(amtDue);
  }
  else
  {
    WidgetType widget=order.getWidget().getValue();
    buildWidget(widget, numOrdered);

    // Add the widget info to bill
    JAXBElement<WidgetType> widgetElement = of.createWidget(widget);
    bill.setWidget(widgetElement);

    float amtDue = numOrdered * 0.30;
    bill.setAmountDue(amtDue);
  }

  return(bill);
}

例 37.17 “placeWidgetOrder()的实施” 中的代码执行以下操作:

实例化对象工厂以创建元素。

实例化 小部件OrderBillInfo 对象以容纳 bill。

获取排序的小部件数量。

获取按顺序存储的元素的本地名称。

检查该元素是否为 woodWidget 元素。

将元素的值从顺序提取到正确类型的对象。

创建一个 JAXBElement<T&gt; 对象,并放入 bill 中。

设置 bill 对象的 widget 属性。

设置 bill 对象的 amountDue 属性。