当前最新的webservice 开发模型是 JAX-WS, 它support 两种webservice的client 类型。
A. Proxy Clients
B.Dispatch Clients
下面就对这两种client 类型做一个讲解。
1.概念
基于代理的客户端工作在webService 暴露的实现了SEI(Service Endpoint Interface)的本地代理对象上。
基于dispatch-client的model,是一个低level的model,它要求你自己提供必要的xml Request,这种model主要使用在一下两种情形:1.当你想自己动态组建你的SOAP request 时。2.当你使用一个不是基于SOAP的 webservice endpoint时。
Example:
当使用proxy-clients,你必须用相应的工具来根据WSDL生成client端的stub.
下面是一个WSDL
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://hello.itso/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://hello.itso/"
name="HelloMessengerService">
<types>
<xsd:schema>
<xsd:import namespace="http://hello.itso/"
schemaLocation="http://localhost:9999/Hello?xsd=1"></xsd:import>
</xsd:schema>
</types>
<message name="sayHello">
<part name="parameters" element="tns:sayHello"></part>
</message>
<message name="sayHelloResponse">
<part name="parameters" element="tns:sayHelloResponse"></part>
</message>
<portType name="HelloMessenger">
<operation name="sayHello">
<input message="tns:sayHello"></input>
<output message="tns:sayHelloResponse"></output>
</operation>
</portType>
<binding name="HelloMessengerPortBinding" type="tns:HelloMessenger">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document"></soap:binding>
<operation name="sayHello">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal"></soap:body>
</input>
<output>
<soap:body use="literal"></soap:body>
</output>
</operation>
</binding>
<service name="HelloMessengerService">
<port name="HelloMessengerPort"
binding="tns:HelloMessengerPortBinding">
<soap:address
location="http://localhost:9999/Hello"></soap:address>
</port>
</service>
</definitions>
生成的 客户端service class
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceFeature;
@WebServiceClient(
name = "HelloMessengerService",
targetNamespace = "http://hello.itso/",
wsdlLocation = "http://localhost:9999/Hello?wsdl")
public class HelloMessengerService extends Service {
private final static URL HELLOMESSENGERSERVICE_WSDL_LOCATION;
static {
URL url = null;
try {
Chapter 2. Web services programming model 91
url = new URL("http://localhost:9999/Hello?wsdl");
} catch (MalformedURLException e) {
e.printStackTrace();
}
HELLOMESSENGERSERVICE_WSDL_LOCATION = url;
}
public HelloMessengerService(URL wsdlLocation, QName serviceName) {
super(wsdlLocation, serviceName);
}
public HelloMessengerService() {
super(HELLOMESSENGERSERVICE_WSDL_LOCATION, new QName(
"http://hello.itso/", "HelloMessengerService"));
}
@WebEndpoint(name = "HelloMessengerPort")
public HelloMessenger getHelloMessengerPort() {
return (HelloMessenger) super.getPort(new
QName("http://hello.itso/",
"HelloMessengerPort"), HelloMessenger.class);
}
@WebEndpoint(name = "HelloMessengerPort")
public HelloMessenger getHelloMessengerPort(WebServiceFeature...
features) {
return (HelloMessenger) super.getPort(new
QName("http://hello.itso/",
"HelloMessengerPort"), HelloMessenger.class, features);
}
}
生成的client端Interface
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
@WebService(name = "HelloMessenger", targetNamespace =
"http://hello.itso/")
@XmlSeeAlso({
ObjectFactory.class
})
public interface HelloMessenger {
@WebMethod
@WebResult(targetNamespace = "")
@RequestWrapper(localName = "sayHello", targetNamespace =
"http://hello.itso/", className = "itso.hello.SayHello")
@ResponseWrapper(localName = "sayHelloResponse", targetNamespace =
"http://hello.itso/", className = "itso.hello.SayHelloResponse")
public String sayHello(
@WebParam(name = "arg0", targetNamespace = "")
String arg0);
}
客户端调用代码
import itso.hello.HelloMessenger;
import itso.hello.HelloMessengerService;
import javax.xml.ws.BindingProvider;
public class HelloClientCustomEndpoint {
public static void main(String... args) throws Exception {
HelloMessengerService service = new HelloMessengerService();
HelloMessenger port = service.getHelloMessengerPort();
//You can also change the endpoint dynamically
((BindingProvider)port).getRequestContext().put(BindingProvider.ENDPOIN
T_ADDRESS_PROPERTY, "http://itso.ibm.com:69693/Hello");
String message = port.sayHello("Thilde");
System.out.println(message);
当使用Dispatch-clients
示例代码如下:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.http.HTTPBinding;
public class HelloDispatchClient {
private static final String TNS = "http://hello.itso/";
public static void main(String... args) throws Exception {
// Define the service name, port name, and endpoint address
QName serviceName = new QName(TNS, "HelloMessengerService");
QName portName = new QName(TNS, "HelloMessenger");
String endpointAddress = "http://localhost:9999/Hello";
// Create a service that can bind to the HelloMessenger port
Service service = Service.create(serviceName);
service.addPort(portName, HTTPBinding.HTTP_BINDING,
endpointAddress);
// Create a Dynamic Dispatch client
//这里Service.Mode.MESSAGE意思是我们自己提供全部的 SOAPMessage,还有一个参数是Service.Mode.PAYLOAD意思是我们只提供SoapBody的部分。
Dispatch<Source> dispatch = service.createDispatch(portName,
Source.class, Service.Mode.MESSAGE);
// Create a SOAP request String
String request =
"<?xml version='1.0' encoding='UTF-8'?>"
+ "<soap:Envelope "
+
"xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'"
+ "xmlns:q0='http://hello.itso/'>"
+ "<soap:Body>"
+ "<q0:sayHello>"
+ "<arg0>Milo</arg0>"
+ "</q0:sayHello>"
+ "</soap:Body>"
+ "</soap:Envelope>";
// Invoke the HelloMessenger web service
Source soapRequest = new StreamSource(new
ByteArrayInputStream(request.getBytes()));
Source soapResponse = dispatch.invoke( soapRequest );
// Convert the response to a String
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Transformer transformer =
TransformerFactory.newInstance().newTransformer();
transformer.transform(soapResponse, new StreamResult(baos));
String response = baos.toString();
// Print the SOAP response String
System.out.println(response);
}
}
当然了,proxy-client有两种类型 同步跟异步,我刚用的是一个同步的proxy-client的例子。关于异步的将在下一张中讲解。