本篇讲述如何通过Java客户端访问C++服务端发布的SOAP模式的WebService接口。文档中的样例代码拷贝出去即可运行,所有的代码都是本地测试OK的;本文不但解决了接口调用的问题,同时解决了中文乱码的问题。
1、  CXF组件:Java端用于发布WebService服务的开源组件,内部自带jetty Web容器。 
2、  Gsoap组件:C++端用户访问WebService服务的组件。使用的是gsoap-2.8。这两个组件可以直接google,官网下载。 
3、  Eclipse:Java开发IDE。 
4、  VS 2010:C++开发IDE。
//gsoap ns service name: wscplus
//gsoap ns service style: rpc
//gsoap ns service namespace: http://localhost:10010/wscplus.wsdl
//gsoap ns service location: http://localhost:10010
//gsoap ns schema namespace: urn:wscplus
int ns__hellowebservice(char* param, char** result);定义接口需要注意: 
1、  接口返回值是int型. 
2、  接口名称定义格式为 ns__xxx。 
3、  输入参数是字符串指针,输出参数是指针的指针。同样,可以通过json串传递更多的内容。 
4、  函数头注释按给的样例定义。在注释中定义服务IP,端口,wsdl文件名。如果函数头未按指定格式定义,使用soapcpp2.exe转换时将产生不了wsdl文件。
生成了如下文件: 
  
编译不过,将soapServerLib.cpp中的#include “soapC.cpp”、#include “soapServer.cpp”注释掉。
// 实现WebService接口
int ns__hellowebservice(struct soap* soapObject, char* param, char** result)
{
    wchar_t* param1 = MulityByteToWideChar(CP_UTF8, param);
    printf("接收到Java客户端传过来的参数-param: %s\n", WideCharToMulityByte(CP_ACP, param1));
    *result = WideCharToMulityByte(CP_UTF8, L"abKJLcd123e12一大堆中文输出参数");
    return SOAP_OK;
}接口实现函数的第一个参数是struct soap* soapObject。后面的参数与helloWebService.h中定义的接口一致。为了保证中文传输不乱码,接收的参数和返回值都做了编码转换。
// 编写get响应请求,目的是为了在浏览器中输入url能看到wsdl文件。 
// 也方便在soapUI等Webservice接口调试工具中能直接调用定义的接口。
int http_get(struct soap* soapObject)
{    
    FILE*fd = NULL;
    // wscplus.wsdl 是执行soapcpp2.exe命令时生成的。把他拷贝到了当前目录下。
    fd = fopen("wscplus.wsdl", "rb"); //open WSDL file to copy        
    if (!fd)        
    {                
        return 404; //return HTTP not found error        
    }
    soapObject->http_content = "text/xml";  //HTTP header with text /xml content        
    soap_response(soapObject, SOAP_FILE);        
    for(;;)        
    {
        size_t r = fread(soapObject->tmpbuf,1, sizeof(soapObject->tmpbuf), fd);
        if (!r)                
        {
            break;                
        }                
        if (soap_send_raw(soapObject, soapObject->tmpbuf, r))
        {
            break; //cannot send, but little we can do about that                
        }
    }
    fclose(fd);
    soap_end_send(soapObject);       
    return SOAP_OK;
}int _tmain(int argc, _TCHAR* argv[])
{
    struct soap soapObject;
    soap_init(&soapObject);
    soap_set_mode(&soapObject, SOAP_C_UTFSTRING);
    soapObject.fget = http_get;
    soap_set_namespaces(&soapObject, namespaces);
    int ret = soap_bind(&soapObject, NULL, 10010, 100);
    if (ret < 0)
    {
        return -1;
    }
    while (true)
    {
        // 阻塞线程,等待外部请求
        ret = soap_accept(&soapObject);
        if (ret <  0)
        {
            return -1;
        }
        soap_serve(&soapObject);
        soap_end(&soapObject);
    }
    return 0;
}不能不说Java的开源组件太好用,傻瓜式开发。C++的gsoap太麻烦了。
import java.nio.charset.Charset;
import java.rmi.RemoteException;   
import javax.xml.namespace.QName;   
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.ServiceException;
import org.apache.axis.client.Call;   
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
public class StartupClient 
{
    public static void main(String[] args) 
    {
        try 
        {   
            String endpoint = "http://localhost:10010/wscplus?wsdl";    
            Service service = new Service();   
            Call call = (Call)service.createCall();    
            call.setTargetEndpointAddress(endpoint);  
            // 设置调用的接口,指定输入参数,输出参数
            call.setOperationName(new QName("urn:wscplus", "hellowebservice"));    
            call.addParameter("param", XMLType.XSD_STRING, ParameterMode.IN);
            call.addParameter("result", XMLType.XSD_STRING, ParameterMode.OUT);
            call.setReturnType(XMLType.XSD_STRING);
            String str = "237anastasiaABG293729一大堆中文输入参数";
            String strParam = new String(str.getBytes(Charset.forName("UTF-8")));
            String result = (String)call.invoke(new Object[]{strParam});
            System.out.println("获取C++服务端返回值-result: " + result);   
        }
        catch (ServiceException e) 
        {   
            e.printStackTrace();   
        } 
        catch (RemoteException e) 
        {   
            e.printStackTrace();   
        }
    }
}先启动服务端,在eclipse中启动客户端单步调试,可以看输出参数,返回值信息。
原文地址:http://blog.csdn.net/ylforever/article/details/44513519