您的位置:首页 > 编程语言 > Java开发

JAX-WS和JAX-RPC方式调用Web Service的Java客户端

2012-06-19 17:14 471 查看
基于JAX-WS调用Web Service的Java客户端一般采用两种方式:proxy方式以及dispatch方式。
proxy方式,proxy的步骤主要如下图所示:



一,proxy方式的调用代码片段一般如下:

[java] view
plaincopy

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对象:
示例代码:

[java] view
plaincopy

// 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 标注的类:

[java] view
plaincopy

@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 标注的类:

[java] view
plaincopy

@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部分。

[java] view
plaincopy

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内容。

[java] view
plaincopy

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包下的类.

[java] view
plaincopy

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了[下面的例子是一个很古老的代码了...]

[java] view
plaincopy

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));  

    }  

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息