Web 服务是一种允许两台或更多的计算机在网络中交互的系统设计。这种服务的主要优点是,它是在多台不同操作系统的计算机和应用服务器之间发送对象的标准解决方法。例如,我们的公司使用 Web 服务从一台运行 Microsoft .NET Framework 的计算机向基于 IBM Lotus Domino 的内联网发布文章。我们最近完成了另一个项目,公开了 Lotus Domino 7 服务器上的 Web 服务的专题报告。基于 Java 的应用服务器读取报告服务器,我们必须协商的惟一东西是 Web Services Description Language(WSDL)文件。
本文向您展示了如何创建 Domino Java 代理消费 Web 服务。它使用 Apache Axis 生成 Java 存根并读取 WSDL 文件。我们提供一个包含可以在本文以下部分使用的 Web 服务的数据库示例。更多信息请参见 “下载” 部分。
本文假设您是一个有经验的 Lotus Notes 和 Domino 应用程序开发人员,熟悉新的 Domino Web 服务设计元素。要学习有关新的 Domino Web 服务设计元素的更多知识,请参阅 developerWorks Lotus 文章 “Lotus Notes/Domino 7 Web Services”。
Web 服务的组件
Web 服务包含几个组件。这些组件包括:
- WSDL 文件
- 面向服务体系结构(Service-Oriented Architecture,SOA)
- 各种协议
WSDL 文件
WSDL 是 Web 服务安装的粘合剂(glue)。每个 Web 服务发布一个 WSDL 文件,该文件包含它可以处理哪些方法和自变量的信息,以及不同方法返回什么对象的信息。本文使用的是一个包含简单 Web 服务的数据库(在本实例中,是 Lotus Domino 7 数据库)。
尽管这个 Web 服务很简单,但是这个服务的 WSDL 文件是十分详细的。当然,这么详细的一个原因是 WSDL 文件使用详细的格式,XML。可是,考虑到 WSDL 文件包含 Web 服务发送和接收的所有对象的描述,这个文件大小不算过分。本文 Web 服务例子的 WSDL 文件有一个名为 ComplexClass 的 Java 类,代码片段如下所示:
<complexType name="MyComplexClass"><sequence><element name="alpha" nillable="true" type="xsd:string"/><element name="calcA" type="xsd:int"/><element name="calcB" type="xsd:int"/><element name="result" nillable="true" type="xsd:int"/></sequence></complexType> |
面向服务体系结构
面向服务体系结构(Service-Oriented Architecture,SOA)在过去的十年已经出现。简单地说,SOA 是一种软件体系结构,它更多地集中于业务而不是公用的、技术驱动的解决方案。它基本上是以消费者-提供者方式设计用于 Web 服务的体系结构。SOA 方法分离各个层,消费者通过服务层与业务对象进行交互,而不是直接进行交互。
关于 SOA 的更多信息,请参阅 developerWorks SOA 和 Web 服务上的 SOA and Web services 新手入门 页面。
Web 服务使用的协议
Web 服务消息不受使用 HTTP 的限制。它也可以使用 SMTP、Extensible Messaging and Presence Protocol(XMPP),甚至 FTP。但是,必须遵守 SOAP;否则,接收系统就很难解释消息。在老一点儿的系统上,可以找到 XML-Remote Procedure Call(XML-RPC),但是 SOAP 是目前正确的协议。
Web 服务的好处是您不必研究各种协议和标准:所有这些都由应用服务器和开发工具处理。在这个例子中,Apache Axis 帮助您解释 WSDL 并生成 Java 代码存根。
数据库示例
在开始使用 Apache Axis 工具前,必须有一个发布 WSDL 文件的 Web 服务。在本文的 “下载” 部分,有两个数据库示例:WebServiceConsumer.nsf 和 MyWebService.nsf。它们的名称表明了它们的作用。在把 MyWebService.nsf 下载到 Lotus Domino 7 服务器之后,用可以运行受限代理的 ID 标记 Web 服务设计元素 —— MyWebservice。WebServiceConsumer.nsf 仅供参考。
|
Apache Axis
Apache Axis 是一个包括 SOAP 服务器和许多生成并部署 Web 服务的不同工具的完整框架。在本文中使用通信部分和 WSDL2Java 方法。但是,首先必须安装 Apache Axis。
先决条件
在可以构建、测试和部署本文中描述的解决方法前,必须具备如下条件:
- Lotus Domino 7 服务器和 IBM Lotus Domino Designer
- Java 软件开发工具包(JDK)
- Apache Axis 框架
我们假设您已经安装了 Lotus Domino 7,并且您知道如何获得 Java 环境并运行。(本文的 “参考资料” 部分提供了所有必须下载的链接。)
表 1 显示了在我们的系统中使用的文件结构。如果您选择复制这个结构,可以重用稍后提到的批处理文件和类路径,也可以选择使用您自己的策略。我们为每一个目录使用工作名称,这样不会混乱。批处理文件是由变量驱动的,所以可以很容易地修改一两行代码使它在您的系统中运行。
表 1. 建议的文件结构
工作名称 | 路径 |
服务器路径 | C:\lotus\DominoR7StandAlone |
JDK 版本 2 | C:\java\j2re1.4.2_09 |
Apache Axis | C:\java\Axis |
工作目录 | C:\java\consumer |
下载并安装 Apache Axis
在下载 Apache Axis 之后,将软件包解压到 Axis 目录。(参见表 1 的建议路径。)本文使用 Apache Axis 提供的两个特性。一个是通信类,实际上,除了要把它们导入 Domino 环境,您不需要知道其他的任何东西。另一个特性是 wsdl2java 工具,Apache Axis 可以使用该工具读取 WSDL 文件并为所有需要的方法和对象生成完整的 Java 存根。
可以启动 shell 并开始运行 Apache Axis 类,但是我们发现启动每个命令要使用 100 个字符以上的类路径是很不方便的。一个解决方法是在一般 Java 类路径中为 Apache Axis 设置所需要的完整的类路径,但是我们更喜欢另一个解决方法:维护设置类路径的批处理文件。以下代码片段显示了名为 wsdl2java.bat 的批处理文件,它存在于工作目录中。
@echo OFFrem *******************************************************rem *** wsdl2java.bat ****rem *******************************************************set AXISPATH=c:\java\AXIS\libset JAVAPATH=C:\java\j2re1.4.2_09set DOMINOJAVAPATH=C:\lotus\DominoR7StandAlone\jvm\lib\extset CP=%AXISPATH%\axis.jarset CP=%CP%;%AXISPATH%\commons-logging-1.0.4.jarset CP=%CP%;%AXISPATH%\commons-discovery-0.2.jarset CP=%CP%;%AXISPATH%\jaxrpc.jarset CP=%CP%;%AXISPATH%\saaj.jarset CP=%CP%;%DOMINOJAVAPATH%\mail.jarset CP=%CP%;%DOMINOJAVAPATH%\activation.jarset CP=%CP%;%AXISPATH%\wsdl4j-1.5.1.jar%JAVAPATH%\bin\java -cp %CP% org.apache.axis.wsdl.WSDL2Java %1 |
|
创建 Web 服务消费代理
通过从 Web 服务获取 WSDL 文件开始创建代理。我们假设您正在使用已提供的 Web 服务 —— MyWebservice —— 并已经将它复制到 Lotus Domino 7 服务器。要想看到 WSDL 文件,将浏览器指向数据库并通过命令 ?WSDL 打开 Web 服务,如图 1 所示。
图 1. 在浏览器中显示 WSDL 文件的例子
在确定 WSDL 文件出现后,可以把 WSDL 文件保存到工作目录中,或者使用 URL 将 Apache Axis 工具包直接指向网络中的 WSDL 资源。现在,可以开始从 WSDL 文件生成 Java 存根。
|
从 WSDL 文件生成 Java 文件
WSDL2Java 函数可以把文件名作为参数,如下所示:
C:\java\consumer>wsd12java.bat MyWebservice.xml
或者以 WSDL 文件的完整的 Uniform Resource Indicator(URI)作为参数:
C:\java\consumer>wsd12java.bat http://localhost/mywebservice.nsf/MyWebService?WSDL
为了在本地工作,下载并使用名称 MyWebservice.xml 把 WSDL 文件保存到工作目录中,如第一个命令所示。
注意:我们工作使用的 Web 服务只是为了示范的目的(例如,没有使用名称空间)。所以,您现在在工作目录中看到一个名为 DefaultNamespace 的新目录。
wsdl2java.bat 的运行结果是生成五个 Java 文件:
- DominoSoapBindingStub.java
- HelloWorld.java
- HelloWorldService.java
- HelloWorldServiceLocator.java
- MyComplexClass.java
在这五个文件中,只有两个是真正重要的:HelloWorld.java 和 MyComplexClass.java。其他三个用于执行调用和解析响应。如果您想学习更多关于 Apache Axis 框架的内容,建议您访问 Apache Axis wiki。
HelloWorld.java 是一个描述 Web 服务可以处理的方法和自变量的接口。MyComplexClass.java 是 MyComplexClass 对象的 JavaBeans 版本,当调用 getMyComplexClass() 方法时 Web 服务用它进行响应。
现在,在 Domino 7 数据库中创建一个新的脚本库,可以使用它消费 Web 服务。
|
把 Java 文件导入 Lotus Notes
Web 服务消费代理使用 Apache Axis 生成的文件。导入 Java 文件最容易的方法是创建 Java 脚本库(不要与 JavaScriptlibrary 混淆)。导入文件并记住将工作目录设置为基础路径(参见图 2)。
图 2. 保存 Apache Axis 生成的 Java 存根的脚本库
注意:基础目录是工作目录,而不是 DefaultNamespace 目录,这一点非常重要。
当脚本库放在适当的位置并编译过之后,就可以关闭它并创建新的 Java 代理。这个代理使用 Apache Axis 客户机类。这些类是 Axis 框架的一部分,所以必须导入。
Apache Axis 客户机位于 Axis 目录下的 Java 存档文件(JAR 文件)中。有一些向代理公开这些类的选项,其中一个选项是直接在代理中导入这些类。但是由于这些类的天然性质 —— 当您发现 Web 消费是多么容易的时候就可以多次使用它们 —— 把它们存储到 IBM Lotus Notes 的其他 JAR 文件使用的 .\jvm\lib\ext 目录中是更自然的方法。
在 Lotus Notes 客户机目录中,将 JAR 文件 axis.jar、commons-discovery-0.2.jar 和 commons-logging-1.0.4.jar 从 .\Axis\lib 复制到 .\jvm\lib\ext。(在使用这些附加文件之前必须重新启动 Lotus Notes 客户机。)当 Lotus Domino Designer 运行时,在开始调用 Web 服务之前只剩下几个步骤。
|
调用 Web 服务的 Lotus Notes 代理
当 JAR 文件放在 .\jvm\lib\ext 目录下并已经重新启动 Lotus Domino Designer 之后,就可以编写 Web 消费代理的代码了。从创建普通的 Java 代理开始。下一步,打开 Edit Project 窗口导入先前创建的脚本库。关闭项目属性窗口,并添加必须的如下所示的导入行:
00 import lotus.domino.*;01 import java.net.URL;02 import org.apache.axis.client.Call;03 import org.apache.axis.client.Service;04 import DefaultNamespace.*;05 import java.io.*;06 public class JavaAgent extends AgentBase {07 public void NotesMain() {08 try {09 Session session = getSession();10 AgentContext agentContext = session.getAgentContext();1112 URL endpoint = new URL("http://localhost:80/MyWebService.nsf/MyWebService");1314 Service service1 = new Service();15 DominoSoapBindingStub service = new DominoSoapBindingStub(endpoint,service1);16 String greeting=service.getGreeting();17 System.out.println(greeting);1819 String greeting2=service.getGreeting("Lotus");20 System.out.println(greeting2);2122 } catch(Exception e) {23 e.printStackTrace();24 }25 }26} |
在第 12 行,创建一个标准的 Java URL 指向您想要使用的 Web 服务。在第 14 行,实例化 Apache Axis 提供的 Service() 类。然后,在第 15 行实例化 DominoSoapBindingStub 服务,并使用新创建的 service1 对象和第 12 行的 URI 提供它。在第 16 行,用 Web 服务方法 getGreeting() 提供的值设置新的字符串。
保存代理并启动 Java 控制台。(这个控制台是惟一一个现在能看到任何活动的地方。)当打开调试窗口时,选择新的数据库,然后运行代理,如图 3 所示。
图 3. 当代理完成后的 Java 控制台
正如您所见,使用 Apache Axis 和 wsdl2java 工具非常节省时间。以前,在 Lotus Domino 5 代理中消费 Web 服务时,您必须坐下来手工解码 SOAP 消息!
|
在服务器上运行 Web 服务消费代理
现在有了一个可以使用 Web 服务进行交互的强大代理。例如,您组织的内联网可以以比过去使用的 Comma Separated Value(CSV)文件更奇特更精确的方式预订最新的天气预报。还可以将 Web 服务与昂贵的 Enterprise Resource Planning(ERP)系统一起使用。
在服务器上运行这个代理不需要其他的步骤。只要保证在 Agent Properties 对话框中将 “Set runtime security level” 属性设置为 “2. Allows restricted operations”,签名者就可以有适当的访问权。
把先前描述的必要的 JAR 文件复制到 Lotus Domino 服务器的 .\jvm\lib\ext 路径。但是注意,如果在正在运行代理的同一台服务器上调用 Domino Web 服务,可能会经历死锁。
结束语
本文描述了构建 Domino 代理来消费 Web 服务的步骤。利用 Apache Axis 框架,可以节省许多时间并集中于业务价值。Apache Axis 已经使用了一段时间,它是稳定且可靠的。使用这样一个第三方的工具使系统更易受攻击,但是这个风险远小于 SOA 能够为您的组织所带来的好处。