基於JAX-WS調用Web Service的Java用戶端

來源:互聯網
上載者:User

基於JAX-WS調用Web Service的Java用戶端一般採用兩種方式:proxy方式以及dispatch方式。
proxy方式,proxy的步驟主要如所示:

一,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】
2,初始化Service,指定wsdL URL和service的QName,service的QName的前一部分是命名空間,後一部分是名稱,與WSDL檔案中的<wsdl:service name="WSCXFProviderService">部分對應。然後通過getPort得到一個實現了SEI的執行個體,這個執行個體被叫做Proxy。它的QName與 wsdl檔案中的<wsdl:port name="WSCXFProviderPort"部分對應。
3,通過SEI調用web service,傳給SEI的參數是加上JAXB annotation的java類(簡單類型和String不用標記)。
4,傳入的參數被序列化為SOAP訊息的payload(body部分的xml),這是因為service.getPort是通過proxy機制建立的,調用這個proxy的方法時,和它關聯的InvocationHandler的invoke方法也會執行,invoke方法會通過JAXB把java參數序列化為XML。然後會把soap request發到伺服器端。
5,返回response是後與4類似,InvocationHandler負責把XML利用JAXB還原序列化為java對象。

二,Dispatch方式:dispatch有payload方式和message方式。
在payload方式中,用戶端需要關心的是 SOAP訊息中的body部分,可以通過把帶有JAXB註解的Java對象或者XML source兩種方法傳遞給dispatch來調用Web service。
1,payload方式通過JAXB Java對象:
範例程式碼:

// create ServiceURL 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 objectMyRequest 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 ServiceURL 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 ServiceURL 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));    }}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.