http://blog.csdn.net/lgp828368/archive/2008/04/03/2246546.aspx
(好像发不了图片,如果想看图片,请到我的资源上下载)
一、简介
在做java项目的时候,有时候我们需要提供一些方法给外部调用,调用者可以处在网络上的任何位置,只要通过特定的设置就可以调用java提供的方法。在java中,我们可以通过把这些方法做成web service。本文档主要对用Visual C++调用java做的webservice进行一系列的说明
二、使用说明
C++调用web service的实质是:发送soap 请求并得到返回的结果。用 C++调用java的webservice,发现与调用微软的webservice还是不同的,用其自带的例子无法实现与java做的webservice通讯,下面和大家分享一下实现的方法。
1.首先,需要安装微软的mssoap tookit 3.0工具包,可以从微软的官方网站上下载;
2.使用java建立一个web服务 ,本例子的web service 使用开源项目cxf建立起来的,想了解cxf请登陆:
http://incubator.apache.org/cxf/
2.1 安装使用Soap Toolk
首先C++要调用web service,首先要下载mssoap tookit 3.0工具包,并安装好。mssoap tookit必须是3.0,否则会出现错误。默认安装好mssoup tookit 3.0後,就可以使用C++来调用webservice了。这时候可以使用mssoap tookit 3.0来监控C++的soap请求。现在假设网络上有一个web service:http://192.168.0.10:8082/ServiceGateway/ServiceServer,下面就这个web service来详细描述使用mssoap tookit 3.0来监控C++调用web service 的情形和不监控的情形,
2.2 使用mssoap tookit 3.0监视C++调用web service
要想使用mssoap tookit 3.0来监控,首先请打开Trace Utility。
打开时候请新建一个 Formatted Trace,如下图
这时候会弹出一个如下图的窗口:
Local port,可以自己定义,使用本机上的一个空闲的端口即可,本例设置为:8080,该端口的意义:以后使用该端口来发送soap请求,Destination:localhos中的localhost请设置为web service的IP,本例应该设置为:192.168.0.10,Destination:80请设置为web service 的端口,本例设置为:8082,设置好之后就可以通过localport来监控soap请求了。
先查看wsdl文件:http://192.168.0.10:8082/ServiceGateway/ServiceServer?wsdl
<?xml version="1.0" encoding="utf-8" ?>
- <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://gateway/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="IndexServiceService" targetNamespace="http://gateway/">
- <wsdl:types>
- <xsd:schema attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://gateway/" xmlns:tns="http://gateway/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="numList" type="tns:numList" />
- <xsd:complexType name="numList">
- <xsd:sequence>
<xsd:element name="arg0" type="xsd:int" />
<xsd:element maxOccurs="unbounded" minOccurs="0" name="arg1" type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="numListResponse" type="tns:numListResponse" />
- <xsd:complexType name="numListResponse">
- <xsd:sequence>
<xsd:element maxOccurs="unbounded" minOccurs="0" name="return" type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="login" type="tns:login" />
- <xsd:complexType name="login">
- <xsd:sequence>
<xsd:element minOccurs="0" name="arg0" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="loginResponse" type="tns:loginResponse" />
- <xsd:complexType name="loginResponse">
- <xsd:sequence>
<xsd:element minOccurs="0" name="return" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
- <wsdl:message name="loginResponse">
<wsdl:part element="tns:loginResponse" name="parameters" />
</wsdl:message>
- <wsdl:message name="login">
<wsdl:part element="tns:login" name="parameters" />
</wsdl:message>
- <wsdl:message name="numListResponse">
<wsdl:part element="tns:numListResponse" name="parameters" />
</wsdl:message>
- <wsdl:message name="numList">
<wsdl:part element="tns:numList" name="parameters" />
</wsdl:message>
- <wsdl:portType name="IndexService">
- <wsdl:operation name="numList">
<wsdl:input message="tns:numList" name="numList" />
<wsdl:output message="tns:numListResponse" name="numListResponse" />
</wsdl:operation>
- <wsdl:operation name="login">
<wsdl:input message="tns:login" name="login" />
<wsdl:output message="tns:loginResponse" name="loginResponse" />
</wsdl:operation>
</wsdl:portType>
- <wsdl:binding name="IndexServiceServiceSoapBinding" type="tns:IndexService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
- <wsdl:operation name="numList">
<soap:operation soapAction="" style="document" />
- <wsdl:input name="numList">
<soap:body use="literal" />
</wsdl:input>
- <wsdl:output name="numListResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
- <wsdl:operation name="login">
<soap:operation soapAction="" style="document" />
- <wsdl:input name="login">
<soap:body use="literal" />
</wsdl:input>
- <wsdl:output name="loginResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
- <wsdl:service name="IndexServiceService">
- <wsdl:port binding="tns:IndexServiceServiceSoapBinding" name="IndexServicePort">
<soap:address location="http://192.168.0.10:8082/ServiceGateway/ServiceServer" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
可见有两个远程方法:
int[] numList(int,int[])
String login(String)
用vc建立一个console的程序,其全部代码如下:
// testwebservice.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#import "msxml4.dll"
using namespace MSXML2;
#import "C:/Program Files/Common Files/MSSoap/Binaries/mssoap30.dll" /
exclude("IStream", "IErrorInfo", "ISequentialStream", "_LARGE_INTEGER", /
"_ULARGE_INTEGER", "tagSTATSTG", "_FILETIME")
using namespace MSSOAPLib30;
void Add()
{
ISoapSerializerPtr Serializer;
ISoapReaderPtr Reader;
ISoapConnectorPtr Connector;
// Connect to the service.
Connector.CreateInstance(__uuidof(HttpConnector30));
//使用EndPointURL属性指定Web服务,因为使用soap tookit3.0来监控,所以使用本地的8080端口来发送soap请求
Connector->Property["EndPointURL"] = "http://localhost:8080/ServiceGateway/ServiceServer";
//这是不使用mssoap tookit 3.0来监控的情形,需要直接发送请求到远端的端口。
// Connector->Property["EndPointURL"] = "http://192.168.0.10:8082/ ServiceGateway/ServiceServer ";
Connector->Connect();
// 开始消息
// //在与服务器连接后,我们需要指定Web服务完成的操作。
//为了指定该操作,我们需要再次使用SoapConnector的Property属性
Connector->Property["SoapAction"] = "http://localhost:8080/ServiceGateway/ServiceServer";
//这是不使用mssoap tookit 3.0来监控的情形
//Connector->Property["SoapAction"] = " http://192.168.0.10:8082/ ServiceGateway/ServiceServer ";
Connector->BeginMessage();
// Create the SoapSerializer object.
Serializer.CreateInstance(__uuidof(SoapSerializer30));
// Connect the serializer object to the input stream of the connector object.
Serializer->Init(_variant_t((IUnknown*)Connector->InputStream));
// 创建SOAP消息
Serializer->StartEnvelope("","","");
Serializer->StartBody
// 开始SOAP消息中的一个元素,第一个参数描述了名字空间,是wsdl文件中的://targetNamespace="http://gateway/"
// 如果它是空值,就会缺省地使用SOAP-ENV。第二、第三个参数
//调用login方法,参数名由wsdl文件决定:
//<xsd:complexType name="login">
// <xsd:sequence>
// <xsd:element minOccurs="0" name="arg0" type="xsd:string" />
// </xsd:sequence>
// </xsd:complexType>
Serializer->StartElement("login","http://server.hw/","STANDARD","");
Serializer->StartElement("arg0","","STANDARD","");
Serializer->WriteString("cellcom");
Serializer->EndElement();
Serializer->EndElement();
Serializer->EndBody();
Serializer->EndEnvelope();
// 将该消息发送给web服务
Connector->EndMessage();
// // 读取响应
.
Reader.CreateInstance(__uuidof(SoapReader30));
// 将reader联接到connector的输出字符串
Reader->Load(_variant_t((IUnknown*)Connector->OutputStream), "");
// 显示结果
printf("Answer: %s/n", (const char*)Reader->RpcResult->text);
return;
}
int main(int argc, char* argv[])
{
CoInitialize(NULL);
Add();
CoUninitialize();
return 0;
}
上面的代码是一个完整的C++调用web service的情形,运行之后会发现Trace Utility里有些信息,如下图:
第一个框里是一个soap请求,第二个框是soap请求返回的结果。
2.3不使用mssoap tookit 3.0监视C++调用web service
不使用mssoap tookit 3.0监控的时候,C++的代码要做如下修改:
//使用EndPointURL属性指定Web服务,因为使用soap tookit3.0来监控,所以使用本地的8080端口来发送soap请求
//Connector->Property["EndPointURL"] = "http://localhost:8080/ServiceGateway/ServiceServer";
//这是不使用mssoap tookit 3.0来监控的情形,需要直接发送请求到远端的端口。
Connector->Property["EndPointURL"] = "http://192.168.0.10:8082/ ServiceGateway/ServiceServer ";
Connector->Connect();
// 开始消息
// //在与服务器连接后,我们需要指定Web服务完成的操作。
//为了指定该操作,我们需要再次使用SoapConnector的Property属性
// Connector->Property["SoapAction"] = "http://localhost:8080/ServiceGateway/ServiceServer";
//这是不使用mssoap tookit 3.0来监控的情形
Connector->Property["SoapAction"] = " http://192.168.0.10:8082/ ServiceGateway/ServiceServer ";
//要使用http://192.168.0.10:8082/ ServiceGateway/ServiceServer来指定服务。
//其他的基本上没改变。
2.4 被调用的方法参数是数组的情形
下面是调用numList的情形,通过查看wsdl知道,numList有两个参数:
<xsd:complexType name="numList">
- <xsd:sequence>
<xsd:element name="arg0" type="xsd:int" />
<xsd:element maxOccurs="unbounded" minOccurs="0" name="arg1" type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
通过询问web service 的开发人员知道,第一个参数是int,第二个参数是int[],该方法是把int[]里所有在第一参数之前的数加一,
Serializer->StartEnvelope("","","");
Serializer->StartBody("");
// 开始SOAP消息中的一个元素,第一个参数描述了名字空间,
// 如果它是空值,就会缺省地使用SOAP-ENV。第二、第三个参数
Serializer->StartElement("numList","http://gateway/","STANDARD","");
Serializer->StartElement("arg0","","STANDARD","");
Serializer->WriteString("2");
Serializer->EndElement();
Serializer->StartElement("arg1","","STANDARD","");
Serializer->WriteString("53");
Serializer->EndElement();
Serializer->StartElement("arg1","","STANDARD","");
Serializer->WriteString("58");
Serializer->EndElement();
查看soap监控里的信息:
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lgp828368/archive/2008/04/03/2246546.aspx