前天做技術(shù)交流,有一位同仁針對(duì)下面的一段AXIS客戶端代碼提出了這樣的問(wèn)題:QName qname=new QName("SparePartDetails","SparePartBean");這2個(gè)參數(shù)是什么意義?
1 String endpointURL = "http://localhost:8080/ws/services/SparePartService";
2 String methodName = "getSparepart";
3
4 Service service = new Service();
5 Call call = (Call) service.createCall();
6 call.setTargetEndpointAddress(new java.net.URL(endpointURL));
7 call.setOperationName(new QName("SparePartService", methodName));
8
9 call.addParameter("sku", XMLType.XSD_STRING, ParameterMode.IN);
10
11 QName qname = new QName("SparePartDetails", "SparePartBean");
12 Class cls = org.bluebear.ws.advanced.customdatatype.SparePartBean.class;
13 call.registerTypeMapping(cls, qname, BeanSerializerFactory.class, BeanDeserializerFactory.class);
14 call.setReturnType(qname);
15
16 Object[] params = new Object[] { "222222" };
17 SparePartBean spBean = (SparePartBean) call.invoke(params);
18
19 System.out.println(spBean);
當(dāng)時(shí)有的同仁回答說(shuō)是根據(jù)WSDD中的beanMapping中的定義來(lái)確定的。這句話本身沒(méi)有錯(cuò),可是如果Service是.Net的語(yǔ)言寫的呢?或者Service不是通過(guò)AXIS來(lái)發(fā)布的呢?是否也有WSDD?
1 <service name="SparePartService" provider="java:RPC">
2 <parameter name="className"
3 value="org.bluebear.ws.advanced.customdatatype.service001.SparePartService" />
4 <parameter name="allowMethods"
5 value="getSparePart" />
6 <beanMapping qname="blueBearNS:SparePartBean"
7 xmlns:blueBearNS="SparePartDetails"
8 languageSpecificType="java:org.bluebear.ws.advanced.customdatatype.SparePartBean" />
9 </service>
這個(gè)問(wèn)題存留于我的腦海中。對(duì)于客戶端而言,只是需要知道如何將返回的SOAP XML 信息轉(zhuǎn)換成相應(yīng)的JavaBean就可以了。對(duì)于Service而言,只是需要將JavaBean轉(zhuǎn)換成SOAP XML。所以客戶端的代碼應(yīng)該和SOAP XML一致。為此我特地研究了2個(gè)方面的問(wèn)題:
1. QName的Constructor
/**
* <p><code>QName</code> constructor specifying the Namespace URI
* and local part.</p>
*
* <p>If the Namespace URI is <code>null</code>, it is set to
* {@link javax.xml.XMLConstants#NULL_NS_URI
* XMLConstants.NULL_NS_URI}. This value represents no
* explicitly defined Namespace as defined by the <a
* href="http://www.w3.org/TR/REC-xml-names/#ns-qualnames">Namespaces
* in XML</a> specification. This action preserves compatible
* behavior with QName 1.0. Explicitly providing the {@link
* javax.xml.XMLConstants#NULL_NS_URI
* XMLConstants.NULL_NS_URI} value is the preferred coding
* style.</p>
*
* <p>If the local part is <code>null</code> an
* <code>IllegalArgumentException</code> is thrown.
* A local part of "" is allowed to preserve
* compatible behavior with QName 1.0. </p>
*
* <p>When using this constructor, the prefix is set to {@link
* javax.xml.XMLConstants#DEFAULT_NS_PREFIX
* XMLConstants.DEFAULT_NS_PREFIX}.</p>
*
* <p>The Namespace URI is not validated as a
* <a href="http://www.ietf.org/rfc/rfc2396.txt">URI reference</a>.
* The local part is not validated as a
* <a href="http://www.w3.org/TR/REC-xml-names/#NT-NCName">NCName</a>
* as specified in <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces
* in XML</a>.</p>
*
* @param namespaceURI Namespace URI of the <code>QName</code>
* @param localPart local part of the <code>QName</code>
*
* @throws IllegalArgumentException When <code>localPart</code> is
* <code>null</code>
*
* @see #QName(String namespaceURI, String localPart, String
* prefix) QName(String namespaceURI, String localPart, String
* prefix)
*/
public QName(final String namespaceURI, final String localPart) {
this(namespaceURI, localPart, XMLConstants.DEFAULT_NS_PREFIX);
}
從上面的解釋中可以看出,QName的Constructor第一個(gè)參數(shù)是XML的namespace,第二個(gè)參數(shù)是該namepace下的一個(gè)名字。所以對(duì)于客戶端的代碼而言,QName qname=new QName("SparePartDetails","SparePartBean");所定義的這兩個(gè)參數(shù)第一個(gè)是SparetDetails是namespace,第二個(gè)SparePartBean是JavaBean轉(zhuǎn)成XML,在XML中的名字。這個(gè)問(wèn)題在Web Service中的WSDL中得到了驗(yàn)證。
2. WSDL代碼
通過(guò)地址:http://localhost:8080/ws/services/SparePartService?wsdl ,即可看到。其中在wsdl:types節(jié)點(diǎn)的信息如下:
<wsdl:types>
<schema targetNamespace="SparePartDetails" xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<complexType name="SparePartBean">
<sequence>
<element name="description" nillable="true" type="soapenc:string"/>
<element name="price" type="xsd:float"/>
<element name="sku" nillable="true" type="soapenc:string"/>
</sequence>
</complexType>
</schema>
</wsdl:types>
其中詳細(xì)描述了SparePartDetails namespace下面存在一個(gè)因?yàn)镾partPartBean的XML 數(shù)據(jù)類型。這里詳細(xì)描述了當(dāng)JavaBean轉(zhuǎn)成XML的時(shí)候,XML的數(shù)據(jù)結(jié)構(gòu)。
結(jié)論:
位于AXIS Service的WSDD中的beanMapping規(guī)定了Service JavaBean轉(zhuǎn)成XML的時(shí)候,XML代碼所必須的的namespace和名字。當(dāng)客戶端接到SOAP XML代碼時(shí),必須使用那個(gè)namespace和名字才能將相應(yīng)的XML代碼轉(zhuǎn)成JavaBean。所以客戶端的代碼的確只是和SOAP XML相關(guān)。