operationname="MAILSEND"
parameterOrder"SENDTOCOPYTOBLINDCOPYTOSUBJECTBODY">(5)
inputmessage="impl:
MAILSENDRequest"
name="MAILSENDRequest"/>
outputmessage="impl:
MAILSENDResponse"
name="MAILSENDResponse"/>
operation>
portType>
bindingname="DominoSoapBinding"
type="impl:
SimpleMailer">(6)
bindingstyle="rpc"
transport="http:
//schemas.xmlsoap.org/soap/http"/>(7)
operationname="MAILSEND">
operationsoapAction=""/>(8)
inputname="MAILSENDRequest">
bodyencodingStyle="http:
//schemas.xmlsoap.org/soap/encoding/"
namespace="urn:
DefaultNamespace"use="encoded"/>
input>
outputname="MAILSENDResponse">
bodyencodingStyle="http:
//schemas.xmlsoap.org/soap/encoding/"
namespace="urn:
DefaultNamespace"use="encoded"/>
output>
operation>
binding>
servicename="SimpleMailerService">(9)
portbinding="impl:
DominoSoapBinding"name="Domino">(10)
addresslocation=
"http:
//localhost/ws/WebservicesR7.nsf/Simplemailer?
OpenWebService"/>
port>
service>
看一下这个文档的各个部分。
下面的每个数字对应于WSDL文档中相应的数字。
1.消息中包含几个表示参数或返回值的标记。
设置request方法接收五个参数。
2.为消息的所有组成部分分配一个名称和数据类型。
3.设置响应返回一个String数据类型的值。
4.portType元素指定一组Web服务所支持的操作。
5.这一行指定了MailSend操作(函数)和这个操作的参数的顺序。
6.一个绑定,使用特定的portType定义了消息的格式和用于操作的协议的详细信息以及消息定义。
7.这个绑定指定了交互的样式(远程过程调用或RPC)和使用的传输协议(HTTP)。
8.使用可选的soapActionHTTP请求头信息域来表示SOAPHTTP请求的目的。
9.DominoDesigner7为WSDL文件生成一个服务和一个端口,或者如果导入一个WSDL文件,那么仅使用遇到的第一个服务元素的第一个端口。
10.一个端口通过为绑定指定单一地址定义了单一端点。
SOAP的结构
清单2展示了提供电子邮件的Web服务所生成的响应的SOAP结构。
清单2.提供电子邮件的Web服务所生成的SOAP响应
xmlversion="1.0"encoding="UTF-8"?
>
Envelopexmlns:
soapenv="http:
//schemas.xmlsoap.org/soap/envelope/"
xmlns:
xsd="http:
//www.w3.org/2001/XMLSchema"
xmlns:
xsi="http:
//www.w3.org/2001/XMLSchema-instance">
(1)
Body>
(2)
MAILSENDResponsesoapenv:
encodingStyle=
"http:
//schemas.xmlsoap.org/soap/encoding/"
xmlns:
ns1="urn:
DefaultNamespace">(3)
type="xsd:
string">OK(4)
MAILSENDResponse>
Body>
Envelope>
1.全部的消息包含在一个Envelope元素中。
Envelope包含一个Body元素和一个可选的Header元素。
2.SOAPBody包含消息的负载,携带了表示消息目的的数据。
3.这一行定义输出操作MAILSENDResponse并设置它的编码类型和名称空间。
如果没有其他说明,LotusDomino7使用urn:
DefaultNamespace作为名称空间。
4.消息输出部分的值,是一个字符串OK。
LotusDomino7中的Web服务
Web服务:
LotusDomino7中一个新的设计元素
Web服务是LotusDomino7中一个新的设计元素,可以使用LotusScript或Java编程语言进行编程。
在数据库设计窗格的SharedCode部分可以找到Web服务。
Web服务设计元素的实现看起来与通常的Domino代理设计十分相似,并具有相同的编程逻辑。
相同的基本安全性规则应用到Web服务,与应用到代理中一样:
∙数据库访问控制列表(accesscontrollist,ACL)用于验证访问
∙作为WebUser/作为Signer/以代理身份运行
∙对资源进行Restricted/Unrestricted访问
∙PublicAccess选项
创建新的Web服务简单到只需单击Web服务设计器面板上操作条中的NewWebService(参见图2)。
图2.创建新的Web服务的Action按钮
WebServicesProperties窗口
当创建一个新的Web服务时,可以在服务的Properties窗口中设置Web服务的基本行为和安全性属性。
这一过程与设置Domino代理的属性相似。
图3显示了稍后将在本教程中创建的简单LotusScriptWeb服务的Properties窗口的Basics附签。
图3.Basics附签
在Basics附签上,可以设置Web服务的名称、别名和PortType类。
注意WarniftheWSDLinterfaceismodified选项:
选中这个选项,如果隐式的WSDL结构更改时,例如,改变类名称、改变方法或函数的名称以及添加或删除类变量,那么将导致服务显示一条消息。
在生产环境中,这样的改变可能会引起现有消费您的Web服务的软件客户机,由于解析更改了的Web服务响应结构产生的错误而停止工作。
设置这一选项还能够阻止您保存这样的更改并给您一个将代码修改回原来状态的机会。
在创建和测试阶段不需要设置这一选项。
在PortTypeclass域中,指定了这个特定服务的类中包含的可用操作(方法和函数)。
如果在没有设置这个域之前试图保存Web服务,那么DominoDesigner7客户机将产生一个警告。
Security附签,如图4所示,看起来与代理属性中的Security附签一样。
在这里,可以为Web服务设置安全性选项。
图4.Security附签
Allowremotedebugging选项用于LotusScriptWeb服务,并且它生成适于远程调试的代码。
对于JavaWeb服务,提供了另一个称作CompileJavacodewithdebugginginformation的选项,使在控制台上查看哪一行代码产生了运行时错误成为可能。
Profilethiswebservice选项允许为概要分析收集运行时的统计信息。
Advanced附签,如图5所示,指定了编程模型和SOAP消息格式。
图5.Advanced附签
可以在两个编程模型选项中进行选择:
RPC和Message。
RPC支持常规方法参数和返回类型;Message限制方法接口为一个“消息”参数和返回类型(有关更多信息,请参阅联机文档)。
对于RPC编程模型,RPC/编码SOAP消息格式是默认的,但是如果有使用其他格式的特殊要求,那么可以修改它。
对于Message编程模型,SOAP消息格式是在Doc/literal中固定的。
有关选择SOAP消息格式的更多信息,请参阅参考资料中列出的RussellButek的文章WhichstyleofWSDLshouldIuse?
。
Porttypename、Serviceelementname和Serviceportname域是在您保存Web服务时自动填充。
在Porttypename域中,指定访问服务的端口类型名称。
这个指定对应于WSDL文档中portType>的name属性。
对于每个服务,LotusDomino7识别一个端口类型。
在Serviceelementname域中,指定服务的名称。
这个指定对应于WSDL文档中service>的name属性。
在Serviceportname域中,指定访问服务的端口。
这个指定对应于WSDL文档中service>下面port>的name属性。
对于每个服务,LotusDomino7识别一个端口。
下一节将向您展示如何使用Web服务集成Domino目录数据库和其他系统。
还将学习如何返回存储在Domino目录数据库中的信息以及如何发送Domino邮件。
创建一个LotusDomino7Web服务
场景概述
XimartCo是一个大规模的软件开发公司,拥有400名员工。
公司在三个城市有主要的办公室,以及遍布世界的几个小办公室。
公司总部有一台LotusDomino服务器用来提供邮件服务,并作为LotusNotes客户机和Web应用程序的主机。
所有的本地办公室都能够通过宽带连接到Internet。
一些办公室在几个月前通过宽带连接到了Internet,但是还没有完全实现LotusDomino,或没有建立虚拟专用网络(VirtualPrivateNetwork,VPN)连接到总办公室。
这些办公室仍然使用它们原有的基于Microsoft®的局域网系统,在公司的内部使用Internet信息服务(InternetInformationServices,IIS)和Apache进行信息交换。
许多办公室希望寻找一个方法来集成它们的AddressBooks和公司总部主机上公司的Domino目录数据库,以便于搜索其他办公室同事的信息。
Research&Development部门在集成动态AddressBook查询到他们的Java应用程序的过程中,也产生了许多的需求。
此外,许多开发人员希望使用Domino邮件服务器,作为他们的MicrosoftVisualBasic®和Java应用程序中发送邮件和自动通知的引擎。
为了满足对实时集成LotusDomino和其他系统不断增长的需求,XimartCo决定通过Web服务实现对Domino目录数据库的访问。
首先,他们决定允许外部系统对Domino目录数据库进行只读查询以获得特定的人员信息,并允许系统以编程的方式使用Domino邮件功能发送邮件。
为更好地支持不同的系统,并考虑以后有可能将相同的解决方案应用于具有相似基础设施的感兴趣的客户,需要创建几个Web服务供VisualBasic兼容客户机和Java客户机调用。
在本教程中,将创建简单和复杂的LotusScript以及JavaDominoWeb服务来满足XimartCo的需要。
根据我的理解,复杂的Web服务是指接受或输出数组数据类型而不是单一文本值的Web服务。
在下面的例子中,以一个LotusScript实现开始,然后提供相同Web服务的Java实现。
在DominoDesigner7客户机上测试Web服务,在Web浏览器中预览任何的表单或视图(参见图6)。
这一过程启动一台内部Web服务器,这台服务器足够满足我们的测试需要。
(注意,如果数据库驻留在LotusDomino服务器上,则不需要执行这一操作。
)
图6.从DominoDesigner客户机启动一台内部Web服务器
简单的LotusScriptWeb服务
按照下列步骤创建一个返回单个文本值的LotusScriptWeb服务。
该值可以是来自任意数据库中的任意字段;我使用的是我的Domino目录数据库中的MailAddress字段。
1.创建一个新的LotusDomino7数据库或者打开一个现有数据库。
2.在DominoDesigner7中创建一个新的Web服务。
3.为Web服务选择LotusScript作为编程语言。
(注意LotusScript是默认的编程语言。
)
4.在服务的Properties窗口的Name域中输入SimpleLSServiceNAB。
5.在PortTypeclass域中,输入GetPersonInfo。
6.粘贴清单3中的LotusScript代码到Web服务的Declarations部分(参见图7)。
7.粘贴GetPersonDocument和GetPersonField函数到Web服务的Declarations部分。
8.保存Web服务.
有关代码功能的描述,请参阅代码内部的注释。
清单3.简单的LotusScriptWeb服务的代码
'DeclareglobalvariablesaccessiblefromallpartsoftheWebservice.
'DeclareglobalvariablesaccessiblefromallpartsoftheWebservice.
DimsessionAsNotesSession
DimnabdbAsNotesDatabase
DimnabdocAsNotesDocument
DimnabviewAsNotesView
DimitemAsNotesItem
'CreateaLotusScriptclass.SubNewcanbeusedtoassignvaluestoglobal
'variables.Herewecansetoursessionobject.
ClassGetPersonInfo
SubNew
Setsession=NewNotesSession
EndSub
'NowwecancreatethemainpartofourWebservice:
GetEmailAddressfunctionand
'GetPhoneNumberfunction.Bothfunctionsworkinasimilarway,sowewilllook
'onlyatGetEmailAddressfunction.
PublicFunctionGetEmailAddress(personnameAsString)AsString
'Wedeclaredfunctionandsetittoaccept1parameter.
'WesetoutputtypetodatatypeStr