QName HelloWorld -记CXF中QName的使用
一. 什么是QName
1.来历:qname是qualifiedname的简写
2.构成:由名字空间(namespace)前缀(prefix)以及冒号(:),还有一个元素名称构成
3.举例:<wsdl:definitions name="Helloworld" targetNamespace="http://server.com/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://server.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">.....<wsdl:portTypename="IHelloWorldService"><wsdl:operation name="sayHello"><wsdl:inputmessage="tns:sayHello" name="sayHello" /><wsdl:outputmessage="tns:sayHelloResponse" name="sayHelloResponse" /></wsdl:operation></wsdl:portType></wsdl:definitions>以wsdl:portType为例:wsdl是名字空间前缀,portTpye是元素名称,wsdl:portType就是一个qname,其namespace是:http://server.com/
二. QName在CXF中的使用
直接上代码,我使用的是apache-cxf-2.4.6.
服务器端(注意我测试的时候service接口,service实现类 和发布service的类放在同一包里,实际使用过程中可以放在不同的包里)
1. 服务器端代码:
1.1 service接口
- package com.server;
- import javax.jws.WebParam;
- import javax.jws.WebService;
- @WebService
- public interface IHelloWorldService {
- public String sayHello(@WebParam(name="text") String name);
- }
- 1.2 service 实现类
- package com.server;
- import javax.jws.WebService;
- @WebService(serviceName="Helloworld")
- public class HelloWorldService implements IHelloWorldService{
- public String sayHello( String name){
- return name + "say : Hello Service.";
- }
- }
- 1.3 发布service的类
- <pre class="java" name="code">package com.server;
- import javax.xml.ws.Endpoint;
- public class DeployHelloWorldService {
- public static void main(String[] args) throws Exception{
- IHelloWorldService service = new HelloWorldService();
- String address = "http://localhost:9000/helloWorld";
- Endpoint.publish(address, service);
- System.out.println("service ready ...");
- }
- }</pre>
- 1.4 运行发布的类后,在IE中输入:<a href="http://localhost:9000/helloWorld?wsdl" mce_href="http://localhost:9000/helloWorld?wsdl">http://localhost:9000/helloWorld?wsdl</a>就可以看到如下wsdl:
- <?xml version="1.0" encoding="UTF-8" ?>
- - <wsdl:definitions name="Helloworld" targetNamespace="http://server.com/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://server.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- - <wsdl:types>
- - <xs:schema elementFormDefault="unqualified" targetNamespace="http://server.com/" version="1.0" xmlns:tns="http://server.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
- <xs:element name="sayHello" type="tns:sayHello" />
- <xs:element name="sayHelloResponse" type="tns:sayHelloResponse" />
- - <xs:complexType name="sayHello">
- - <xs:sequence>
- <xs:element minOccurs="0" name="text" type="xs:string" />
- </xs:sequence>
- </xs:complexType>
- - <xs:complexType name="sayHelloResponse">
- - <xs:sequence>
- <xs:element minOccurs="0" name="return" type="xs:string" />
- </xs:sequence>
- </xs:complexType>
- </xs:schema>
- </wsdl:types>
- - <wsdl:message name="sayHelloResponse">
- <wsdl:part element="tns:sayHelloResponse" name="parameters" />
- </wsdl:message>
- - <wsdl:message name="sayHello">
- <wsdl:part element="tns:sayHello" name="parameters" />
- </wsdl:message>
- - <wsdl:portType name="IHelloWorldService">
- - <wsdl:operation name="sayHello">
- <wsdl:input message="tns:sayHello" name="sayHello" />
- <wsdl:output message="tns:sayHelloResponse" name="sayHelloResponse" />
- </wsdl:operation>
- </wsdl:portType>
- - <wsdl:binding name="HelloworldSoapBinding" type="tns:IHelloWorldService">
- <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
- - <wsdl:operation name="sayHello">
- <soap:operation soapAction="" style="document" />
- - <wsdl:input name="sayHello">
- <soap:body use="literal" />
- </wsdl:input>
- - <wsdl:output name="sayHelloResponse">
- <soap:body use="literal" />
- </wsdl:output>
- </wsdl:operation>
- </wsdl:binding>
- - <wsdl:service name="Helloworld">
- - <wsdl:port binding="tns:HelloworldSoapBinding" name="HelloWorldServicePort">
- <soap:address location="http://localhost:9000/helloWorld" />
- </wsdl:port>
- </wsdl:service>
- </wsdl:definitions>
2. 客户端使用QName调用WebService的代码
- package client;
- import javax.xml.namespace.QName;
- import javax.xml.ws.Service;
- import javax.xml.ws.soap.SOAPBinding;
- import com.server.IHelloWorldService;
- public class HelloWorldServiceClient {
- /**
- * namespaceURI即为:wsdl:definitions name="Helloworld" targetNamespace="http://server.com/"...
- * 中的targetNamespace.
- * 如果服务器端的service接口和类不在同一个包中时:
- * namespaceURI即为wsdl:import中的namespace
- * <wsdl:import location="http://localhost:9000/helloWorld?wsdl=IHelloWorldService.wsdl" namespace="http://inter.server.com/" />
- */
- private static String namespaceURI = "http://server.com/";
- private static final QName SERVICE_NAME = new QName(namespaceURI,"IHelloWorldService");
- private static final QName PORT_NAME = new QName(namespaceURI,"IHelloWorldServicePort");
- public static void main(String[] args) {
- Service service = Service.create(SERVICE_NAME);
- String endpointAddress = "http://localhost:9000/helloWorld";
- service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);
- IHelloWorldService clientService = service.getPort(IHelloWorldService.class);
- String result = clientService.sayHello("hello QName");
- System.out.println(result);
- }
运行该类就可以通过QName调用到Server端的service
注意以下几点:
2.1 namespaceURI 为:wsdl:definitions中的targetNamespace的值,在本例中就是http://server.com/
2.2.serviceName 为: wdsl中的IHelloWorldService对对应的portType 的name ,使用<wsdl:service name="Helloworld">中的Helloworld也可以,具体原因也说不上来。serviceName使用其他错误的值,该程序
也可以正常运行,搞不懂了。
2.3.protName 为wdsl中的IHelloWorldService对对应的portType 的name + “Port”即IHelloWorldServicePort,我估计之所以这么使用是因为客户端是通过IHelloWorldService调用的原因。
使用HelloworldPort会抛异常:
“Caused by: java.net.MalformedURLException: Invalid address. Endpoint address cannot be null.”
这个PortName也不是<wsdl:port binding="tns:HelloworldSoapBinding" name="HelloWorldServicePort"> 中的HelloWorldServicePort,如果使用HelloWorldServicePort也回抛出上面的异常。
总结一点,在使用QName的过程中nameSpaceUrl 和PortName 不能写错,否则会导致调用时抛异常。