一,proxy方式的调用代码片段一般如下:
URL wsdlURL = new URL("file:///D:/JAVAWorkspace/Test/WSClient/src/wsdl/prjCXFWeb.wsdl"); QName serviceQName = new QName("http://test.cxf.bt.com/", "WSCXFProviderService"); QName portQName = new QName("http://test.cxf.bt.com/", "WSCXFProviderPort"); Service service = Service.create(wsdlURL, serviceQName); WSCXFProvider port = (WSCXFProvider) service.getPort(portQName, WSCXFProvider.class); try{ System.out.println(port.testWS("message")); }catch(SOAPFaultException e){ System.out.println(e.getFault().getFaultCode()); System.out.println(e.getFault().getFaultString()); }1,用工具通过WSDL文件产生一个SEI(service endpoint interface),一个java的interface,能够对应该web service提供的功能。这个interface的类名会对应到WSDL的portType名称,方法会和operation对应,方法的参数会和message以及types对应。CXF和Axis都提供这样的工具:wsdl2java。【上面的WSCXFProvider就是SEI】
二,Dispatch方式:dispatch有payload方式和message方式。
// create Service URL wsdlURL = new URL("file:///D:/JAVAWorkspace/Test/WSClient/src/wsdl/prjCXFWeb.wsdl"); QName serviceQName = new QName("http://test.cxf.bt.com/", "WSCXFProviderService"); Service service = Service.create(wsdlURL, serviceQName); JAXBContext ctxt = JAXBContext.newInstance(MyRequest.class, MyResponse.class); QName portQName = new QName("http://test.cxf.bt.com/", "WSCXFProviderPort"); Dispatch<Object> dispatchJAXB = service.createDispatch(portQName, ctxt, Service.Mode.PAYLOAD); // create the custom request order object MyRequest myReq = new MyRequest(); myReq.arg0="message"; MyResponse resp = (MyResponse) dispatchJAXB.invoke(myReq); System.out.println(resp.get_return());MyRequest是加上JAXB 标注的类:
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "testWS", propOrder = { "arg0" }) @XmlRootElement(name = "testWS") public class MyRequest { protected String arg0; public String getArg0() { return arg0; } public void setArg0(String arg0) { this.arg0 = arg0; } }MyResponse也是加上JAXB 标注的类:
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "testWSResponse", propOrder = { "_return" }) @XmlRootElement(name = "testWSResponse", namespace="http://test.cxf.bt.com/") public class MyResponse { @XmlElement(name = "return") protected String _return; public String get_return() { return _return; } public void set_return(String _return) { this._return = _return; } }某些工具生成的JAXB客户端(MyRequest和MyResponse)会没有加上@XmlRootElement,这时候会报* unable to marshal type "....." as an element because it is missing an @XmlRootElement annotation],候需要手动的加上XmlRootElement注解.
2.1,payload方式通过XML source:只传入xml的payload部分的内容,不需要SOAP消息的envelope部分。
StreamSource xmlSource = new StreamSource(new StringReader( "<dlwmin:testWS xmlns:dlwmin=/"http://test.cxf.bt.com//"><arg0>xxx</arg0></dlwmin:testWS>")); // create Service URL wsdlURL = new URL("file:///D:/JAVAWorkspace/Test/WSClient/src/wsdl/prjCXFWeb.wsdl"); QName serviceQName = new QName("http://test.cxf.bt.com/", "WSCXFProviderService"); Service service = Service.create(wsdlURL, serviceQName); // create Dispatch<Source> QName portQName = new QName("http://test.cxf.bt.com/", "WSCXFProviderPort"); Dispatch<Source> dispatch = service.createDispatch(portQName, Source.class, Service.Mode.PAYLOAD); Source orderSource = dispatch.invoke(xmlSource); // Process the response. StreamResult result = new StreamResult(new ByteArrayOutputStream()); Transformer trans = TransformerFactory.newInstance().newTransformer(); trans.transform(orderSource, result); ByteArrayOutputStream baos = (ByteArrayOutputStream) result.getOutputStream(); // Write out the response content. String responseContent = new String(baos.toByteArray()); System.out.println(responseContent);
2.2,message方式通过XML source:传入整个的soap消息的xml内容。
StreamSource xmlSource1 = new StreamSource( new StringReader( "<?xml version=/"1.0/" encoding=/"utf-8/" ?> <SOAP-ENV:Envelope xmlns:SOAP-ENV=/"http://schemas.xmlsoap.org/soap/envelope//" xmlns:xsd=/"http://www.w3.org/2001/XMLSchema/" xmlns:xsi=/"http://www.w3.org/2001/XMLSchema-instance/"> <SOAP-ENV:Header/><SOAP-ENV:Body><dlwmin:testWS xmlns:dlwmin=/"http://test.cxf.bt.com//"> <arg0>xxx</arg0></dlwmin:testWS></SOAP-ENV:Body></SOAP-ENV:Envelope>")); // create Service URL wsdlURL = new URL("file:///D:/JAVAWorkspace/Test/WSClient/src/wsdl/prjCXFWeb.wsdl"); QName serviceQName = new QName("http://test.cxf.bt.com/", "WSCXFProviderService"); Service service = Service.create(wsdlURL, serviceQName); // create Dispatch<Source> QName portQName = new QName("http://test.cxf.bt.com/", "WSCXFProviderPort"); Dispatch<SOAPMessage> dispatch = service.createDispatch(portQName, SOAPMessage.class, Service.Mode.MESSAGE); MessageFactory factory = MessageFactory.newInstance(); SOAPMessage message = factory.createMessage(); message.getSOAPPart().setContent(xmlSource1); message.saveChanges(); SOAPMessage response = dispatch.invoke(message); SOAPPart sp = response.getSOAPPart(); Source resp = sp.getContent(); // Process the response. StreamResult result = new StreamResult(new ByteArrayOutputStream()); Transformer trans = TransformerFactory.newInstance().newTransformer(); trans.transform(resp, result); ByteArrayOutputStream baos = (ByteArrayOutputStream) result.getOutputStream(); // Write out the response content. String responseContent = new String(baos.toByteArray()); System.out.println(responseContent);2.3,JAX-WS仍然支持使用RPC方式调用,但已经完全不鼓励使用(服务器端的服务提供类必须extends Remote).下面是一个客服端的调用例子:引入的是javax.xml.rpc包下的类.
package com.test.jaxws.caller; import java.net.MalformedURLException; import java.net.URL; import java.rmi.RemoteException; import javax.xml.namespace.QName; import javax.xml.rpc.Service; import javax.xml.rpc.ServiceException; import javax.xml.rpc.ServiceFactory; import com.cxfws.test.SimpleService; public class JAXRPCWSCaller { static String wsdlLocation = "file:///D:/JAVAWorkspace/Repository/prjCXFWS/src/wsdl/prjCXFWS.wsdl"; // SimpleService must extends Remote if using this way to call web service public static void main(String[] args) throws MalformedURLException, ServiceException, RemoteException { ServiceFactory serviceFactory = ServiceFactory.newInstance(); Service service = serviceFactory.createService(new URL(wsdlLocation), new QName("http://test.cxfws.com/", "SimpleServiceService")); SimpleService myProxy = (SimpleService) service.getPort( new QName("http://test.cxfws.com/", "SimpleServicePort"), SimpleService.class); String result = myProxy.concatenate("s1", "s2"); System.out.println(result); } }2.4,而如果服务器端不是JAVA实现,那就只能用soap.jar的rpc.Call了[下面的例子是一个很古老的代码了...]
package com.test.soaprpc.caller; import java.net.URL; import java.util.Arrays; import java.util.Vector; import org.apache.soap.Constants; import org.apache.soap.Fault; import org.apache.soap.Header; import org.apache.soap.encoding.SOAPMappingRegistry; import org.apache.soap.encoding.soapenc.StringDeserializer; import org.apache.soap.rpc.Call; import org.apache.soap.rpc.Parameter; import org.apache.soap.rpc.Response; import org.apache.soap.util.xml.QName; public class WSCallerBySOAP { public Object callWS(Parameter[] params, String uri, String mtdName, String url, SOAPMappingRegistry smr) { try { Call call = new Call(); call.setTargetObjectURI(uri); call.setMethodName(mtdName); call.setParams(new Vector(Arrays.asList(params))); call.setSOAPMappingRegistry(smr); Header myHeader = new Header(); myHeader.declareNamespace("", " XXX "); myHeader.setAttribute(new QName("", "Minor"), "0"); call.setHeader(myHeader); Response resp = call.invoke(new URL(url), ""); if (resp.generatedFault()) { Fault fault = resp.getFault(); System.out.println(fault.getFaultCode()); System.out.println(fault.getFaultString()); } else { if (resp.getReturnValue() != null) { Object obj = resp.getReturnValue().getValue(); return obj; } } } catch (Exception e) { e.printStackTrace(); System.out.println(e); } return null; } public static void main(String[] args) { WSCallerBySOAP wsCaller = new WSCallerBySOAP(); Parameter param1 = new Parameter("arg0", String.class, "<test:testWS>" + "<arg0>aaaaaaaaaa</arg0>" + "</test:testWS>", Constants.NS_URI_SOAP_ENC); Parameter[] prams = new Parameter[] { param1 }; String uri = "WSCXFProviderPort"; String url = "http://localhost:7225/prjCXFWeb/services/WSCXFProviderPort"; String mtdName = "testWS"; SOAPMappingRegistry smr = new SOAPMappingRegistry(); smr.mapTypes(Constants.NS_URI_SOAP_ENC, new QName("", "return"), null, null, new StringDeserializer()); System.out.println(wsCaller.callWS(prams, uri, mtdName, url, smr)); } }