深蓝海域KMPRO

使用.Net, Java或者MS SOAP Toolkit 创建Web服务

2002-09-13 14:20

使用.Net, Java或者MS SOAP Toolkit 创建Web服务

本文将介绍如何使用下列三种语言中的任一种建立web服务以及客户端程序:.NET,MS SOAP Tookkit和Java.但是本文的主旨还是要告诉你如何使用上面提到的语言来建立web服务的客户端程序.

在不久以前.NET被发布了而且我们中的许多人开始急着编写ASP.NET web站点,C#程序或是Web Services.我当时真的惊讶于人们能够使用.NET相对容易的编写web服务.我以前曾用MS SOAP Toolkit和Apache SOAP for Java编写过一些web服务.然后有人要求我用不同的语言为这些web服务编写客户端程序.这被事实证明了是不容易的.虽然SOAP现在已经成为标准,但是web服务的不同实现情况有时使得与其它SOAP的互联性很差,如果不是不可能的话.

我的例子程序是只有一个方法--addNumbers的非常简单的web服务.你可能已经猜出来了,它能够将两个数字相加然后返回结果.这个程序的名字叫Hello2其源代码附在本文上.

STK 服务和客户端

首先让我们使用MS SOAP Toolkit,ASP 监听程序和一个ISAPI监听程序来编写一个Web 服务.

Visual Basic类中的addNumbers方法是:

Public Function addNumbers(ByVal NumberOne As Double, ByVal NumberTwo As Double) As Double

addNumbers = NumberOne + NumberTwo

End Function

用WSDLGen.exe向导力可以生成ISAPI监听器,ASP监听器或是同时产生两者(当然也可以分开产生).我的选择是同时产生ASP和ISAPI监听器,所以我将我的WSDL文件分别命名Hello2ASP.WSDL 和Hello2Isapi.WSDL.
现在燃我们为这个Hello2 web服务写一些客户端.

STK 客户端

第一个客户端是一个Visual Basic客户端程序,使用SOAP Toolkit中高层的API.创建一个VB工程并添加一个窗体和按钮.下面的代码在按钮被点击的时候执行.

Private Sub cmdDoTest_Click()

Const WS_URL = "
http://localhost/Hello2/Hello2Isapi.WSDL"

Dim objHello2ISapi As SoapClient

Dim nResult As Double, NumberOne As Double, NumberTwo As Double

On Error GoTo catch_err

Set objHello2ISapi = New SoapClient

Call objHello2ISapi.mssoapinit(WS_URL)

NumberOne = 10

NumberTwo = 25

nResult = objHello2ISapi.addNumbers(NumberOne, NumberTwo)

MsgBox nResult

cleanup:

Set objHello2ISapi = Nothing

Exit Sub

catch_err:

MsgBox Err.Description

Resume cleanup

End Sub

你可以发现客户端非常简单而且没有什么疑难.所有建立SOAP请求消息和解析返回的SOAP消息的过程被隐藏了,程序员无法看见.WS_URL是服务的URL.SOAP Toolkit中高层的API需要一个WSDL文件所以这个URL指向一个这样的WSDL文件.你提供哪一个并不重要,虽然使用ISAPI监听器的性能要好一些.

Java客户端

我们为Hello2服务程序编写的第二个客户端程序是一个Java程序.我对这个程序使用了Apache SOAP 2.1.你可以免费从
http://xml.apache.org/soap/index.html下载.

ASP监听器所使用的Java类程序如下:

import java.io.*;

import java.util.*;

import java.net.*;

import org.w3c.dom.*;

import org.apache.soap.util.xml.*;

import org.apache.soap.*;

import org.apache.soap.encoding.*;

import org.apache.soap.encoding.soapenc.*;

import org.apache.soap.rpc.*;

import org.apache.soap.transport.http.SOAPHTTPConnection;

public class testClient {

public static void main(String[] args) throws Exception {

URL url = new URL ("http://localhost/Hello2/Hello2.asp");

SOAPMappingRegistry smr = new SOAPMappingRegistry ();

StringDeserializer sd = new StringDeserializer ();

smr.mapTypes (Constants.NS_URI_SOAP_ENC, new QName ("", "Result"), null, null, sd);

// 创建传输路径和参数

SOAPHTTPConnection st = new SOAPHTTPConnection();

// 创建调用

Call call = new Call ();

call.setSOAPTransport(st);

call.setSOAPMappingRegistry (smr);

call.setTargetObjectURI ("http://tempuri.org/message/");

call.setMethodName("addNumbers");

call.setEncodingStyleURI ("
http://schemas.xmlsoap.org/soap/encoding/");

Vector params = new Vector();

params.addElement(new Parameter("NumberOne", Double.class, "10", null));

params.addElement(new Parameter("NumberTwo", Double.class, "25", null));

call.setParams(params);

Response resp = null;

try {

resp = call.invoke (url, "
http://tempuri.org/action/Hello2.addNumbers");

}

catch (SOAPException e) {

System.err.println("Caught SOAPException (" + e.getFaultCode () + "): " + e.getMessage ());

return;

}

// 检查返回值

if (resp != null && !resp.generatedFault()) {

Parameter ret = resp.getReturnValue();

Object value = ret.getValue();

System.out.println ("Answer--> " + value);
}

else {

Fault fault = resp.getFault ();

System.err.println ("Generated fault: ");

System.out.println (" Fault Code = " + fault.getFaultCode());

System.out.println (" Fault String = " + fault.getFaultString());

}

}

}

正如你所看见的url变量指向ASP监听器.要将Java客户端指向ISAPI监听器只需要做如下修改:

URL url = new URL ("
http://localhost/Hello2/Hello2Isapi.wsdl");

.NET客户端

现在是时候为我们的Hello2 web服务写一个.NET客户端了.必须为我们的服务用 .NET Framework Beta 2 的WSD.exe工具来生成一个代理类.运行下面的命令.

wsdl http://localhost/Hello2/Hello2Isapi.wsdl

它将生成文件Hello2Isapi.cs.这是一个用C#(它是缺省的语言)写成的.NET代理类.你可以查到wsdl.exe的参数来生成用VB.NET或者其它语言写成的代理.现在用下面的命令编译代理

csc.exe /t:library Hello2Isapi.cs

可以编写.NET客户端了,它使用代理类来访问Hello2 web服务.下面是C#客户端的代码.

using System;

public class Hello2ISapiClient {

public static void Main() {

Hello2Isapi srv = new Hello2Isapi();

double res = 0, num1 = 10, num2 = 25;

res = srv.addNumbers(num1, num2);

Console.WriteLine("{0}+{1}={2}", num1, num2, res);

}

}

用Hello2IsapiClient.cs /reference:Hello2Isapi.dll编译客户端然后和Hello2IsapiClient一起运行它.

现在我们有了一个MS SOAP Toolkit web服务程序和三个客户端,分别用:SOAP Toolkit, Java 和.NET 写成.

用Apache SOAP编写Java服务器端和客户端

让我们继续用Apache SOAP来编写Java语言的同样的web 服务.下面是服务器端:

package samples.MyService;

import java.util.*;

import org.w3c.dom.*;

import org.apache.soap.util.xml.*;

public class MyService {

public double addNumbers(double num1, double num2) {

return num1+num2;

}

}

我将我的服务取名为MyService并将它添加到samples包里.这样你就不必在Tomcat服务器里添加上下文.只需要用下面的启用描述文件将这个服务添加到SOAP里:

<isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment" id="urn:myservice-service" checkMustUnderstands="false">

<isd:provider type="java" scope="Application" methods="addNumbers">

<isd:java class="samples.MyService.MyService" static="false"/>

</isd:provider>

</isd:service>

我不会在这里解释如何将Apache SOAP设置成Tomcat因为在Apache SOAP文件里有足够的指导.

Apache SOAP客户端

我们可以为这个服务编写客户端了.第一个是用Java写的.下面是源代码:

package samples.MyService;

import java.io.*;

import java.util.*;

import java.net.*;

import org.w3c.dom.*;

import org.apache.soap.util.xml.*;

import org.apache.soap.*;

import org.apache.soap.encoding.*;

import org.apache.soap.encoding.soapenc.*;

import org.apache.soap.rpc.*;

public class client {

public static void main(String[] args) throws Exception {

if (args.length != 3

&& (args.length != 4 || !args[0].startsWith("-")))

{

System.err.println("Usage:");

System.err.println(" java " + client.class.getName() +

" [-encodingStyleURI] SOAP-router-URL nameToLookup");

System.exit (1);

}

// 处理参数

int offset = 4 - args.length;

String encodingStyleURI = args.length == 4

? args[0].substring(1)

: Constants.NS_URI_SOAP_ENC;

URL url = new URL(args[1 - offset]);

Double num1 = new Double(args[2 - offset]),

num2 = new Double(args[3 - offset]);

SOAPMappingRegistry smr = new SOAPMappingRegistry();

BeanSerializer beanSer = new BeanSerializer();

System.out.println(encodingStyleURI);

System.out.println(url);

System.out.println(num1);

System.out.println(num2);

// 建立调用

Call call = new Call();

call.setSOAPMappingRegistry(smr);

call.setTargetObjectURI("urn:MyService");

call.setMethodName("addNumbers");

call.setEncodingStyleURI(encodingStyleURI);

Vector params = new Vector();

params.addElement(new Parameter("num1", Double.class, num1, null));

params.addElement(new Parameter("num2", Double.class, num2, null));

call.setParams(params);

// 启动调用过程

Response resp;

long nErrors = 0;

Calendar cal = Calendar.getInstance();

Date startTime = cal.getTime(), endTime;

try {

resp = call.invoke(url, "");

}

catch (SOAPException e) {

System.out.println("i=" + i);

System.err.println("Caught SOAPException (" +

e.getFaultCode() + "): " +

e.getMessage());

return;

}

// 检查返回值

if (!resp.generatedFault()) {

Parameter ret = resp.getReturnValue();

Object value = ret.getValue();

//System.out.println(value != null ? "\n" + value : "I don't know.");
}

else {

Fault fault = resp.getFault();

System.err.println("Generated fault: ");

System.out.println (" Fault Code = " + fault.getFaultCode());

System.out.println (" Fault String = " + fault.getFaultString());

}

cal = Calendar.getInstance();

endTime = cal.getTime();

System.out.println("Start time="+startTime);

System.out.println("End time="+endTime);

System.out.println ("Errors=" + nErrors);

}

}

如你所见,代码是非常直观的.应该没有什么问题因为我们使用了相同的SOAP库.一个STK客户端的代码如下:

STK Client

在高层次的和低层次的客户端程序里都存在错误因为在Apache SOAP for Java里需要xsi:类型.

.NET客户端

因为同样的问题.NET客户端也不会正常工作.

.NET服务和客户端

.NET Framework Beta 2 是最新的技术而且在Bata 2版本到最终版本发布可能还会有改动.在Beta2发布的时候主要的改变已经完成了.微软已经警告开发者有可能发生改动,所以这也就不奇怪了.

使用.NET编写一个web服务是很简单的而且可以用几种方法完成.我选择在ASMX文件里用C#编写我的web服务程序.下面是文件的内容.

using System;

using System.Web.Services;

[WebService(Namespace="http://www.catalin.com/webservices/")]

public class MyService: WebService {

[ WebMethod(Description="return the sum of two numbers")]

[System.Web.Services.Protocols.SoapRpcMethodAttribute(

"
http://www.catalin.com/webservices/addNumbers",

RequestNamespace="
http://www.catalin.com/webservices/",

ResponseNamespace="
http://www.catalin.com/webservices/")]

public double addNumbers(double numberOne, double numberTwo) {

return numberOne + numberTwo;

}

}

使用ASMX文件的好处是不需要进行编译,所以可以很快的使用这个程序.将文件放到IIS下的一个虚拟路径里.你可以用IE和http://localhost/testdotnetws/myservice.asmx .NET 客户端来测试这个服务程序.为这个服务编写一个客户端与我们前面写的.NET程序类似.在生成代理文件的时候将WSDL文件设置成http://localhost/testdotnetws/myservice.asmx?WSDL.这也是.NET framework用命令行产生WSDL文件的方式.

STK客户端

使用高层次的API会更快一些但是有一些问题我无法解决所以我使用了低层次的API.客户端程序并不复杂.唯一的技巧是使.NET服务对RPC形式的调用可用.感谢Christian Weyer帮我解决了这个问题.看一看web服务程序的代码并注意我们方法的System.Web.Services.Protocols.SoapRpcMethodAttribute属性.没有这个属性的话,.NET中程序对话的缺省类型就是消息了.

Java客户端

在java客户端中你需要将url改成如下所示:

URL url = new URL ("http://localhost/aspnet_test/myservice/myservice.asmx");

编译运行

我希望这次对web服务世界的简短历程能够帮助你们那些致力于web服务开发的人.

祝你的SOAP过程快乐!

相关推荐