增强你的SOAP::Lite
Web服务
作为一个有丰富Perl和Web服务经验的技术人员,我吃惊于SOAP::Lite会如此容易上手,容易运行。我还没有想到有哪个主要的SOAP工具包能有它容易使用,能像它一样可以快速部署,或者说能像它一样富于灵活性。使用SOAP::Lite安装Web服务的基础构件不用花很长时间,安装完毕后,你就可以使用这个工具包的其它特性。在下面的例子中,我会给你演示如何:
通过名字访问参数元素。
访问请求中的SOAP
Header(报头)元素。
将SOAP Header加到回应中。
生成SOAP Fault。
使用Document
Style Encoding生成回应。
通过名字访问SOAP Body(主体)元素
缺省地,SOAP::Lite对SOAP请求方法的数据元素进行串并转换,并将它们放到一个通用数组里。这个数组被按照原样传递给请求句柄的子程序。这个子程序就能够访问这些参数,就像它能够访问其他任何带参数的输入一样。这样做就能很容易地为各种服务建立原型,但是其代价是灵活性的降低。如果你的方法有任何可选参数,如果你的方法有任何你需要访问的属性,或者如果传递给方法的参数并不依赖于顺序,那么这种额外的简单性所带来的麻烦要比其带来的好处更多。
SOAP::Lite为你通过名字访问请求中的元素提供了一个更加方便的方法。这增加了可以定义的服务接口类型的灵活性。下面这个例子会告诉你如何实现:
1 #!/usr/bin/perl
2 # Filename: Echo.pm
3 package
Echo;
4 use strict;
5 use vars qw(@ISA);
6 @ISA =
qw(SOAP::Server::Parameters);
7 sub echo {
8 my $self = shift;
9 my
$envelope = pop;
10 my $str =
$envelope->dataof("//echo/whatToEcho")->value;
11 return $str;
12
}
13 1;
通过第5和第6行里对SOAP::Server::Parameters包的扩展,你可以通过名字找出SOAP数据元素的分封线。要访问SOAP
Body,首先将隐秘地传递给方法的SOAP分封线的对象弹出,然后调用一个dataof()子程序,用以返回对应于指定元素name/XPath的SOAP::Data对象,见第10行。由于dataof()返回的是一个SOAP::Data对象,你就能够访问SOAP::Data的所有子程序,包括value(),name(),type(),uri()和attr()等用于直接访问元素的值、元素的名字、元素的数据类型、元素的uri,以及所有元素各自的属性。
访问请求中的Header数据
要访问请求中的SOAP
Header元素,就要改变代码,这些代码事实上和通过名字访问SOAP
Body元素所要改变的代码是很类似的。要访问报头元素,只用像以下这样简单地调用headerof()子程序:
7 sub echo {
8 my
$self = shift;
9 my $envelope = pop;
10 my $header =
$envelope->headerof("//MyHeaderElementName")->value;
12 # do something
with the header here, if necessary
13 my $str =
$envelope->dataof("//echo/whatToEcho")->value;
14 return $str;
15
}
对于dataof()子程序,headerof()子程序返回一个SOAP::Data元素,让你能够访问名字、值、属性、命名空间和被参照的报头元素的数据类型。
文档风格回应
在上面的例子中,SOAP的回应一直在使用SOAP::Lite缺省的SOAP编码。如果你已经打开调试模式运行了上面的例子,你将毫无疑问地注意到:在回应的SOAP
Body里找到的元素名字似乎毫无意义。例如,看看下面SOAP回应的例子,注意一下叫作s-gensym3的元素。
<?xml version="1.0"
encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENC=http://schemas.xmlsoap.org/soap/encoding/
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<namesp1:echoResponse
xmlns:namesp1="urn:Echo">
<s-gensym3 xsi:type="xsd:string">Echo this
statement</s-gensym3>
</namesp1:echoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
如果你正在开发的服务要求这个元素要有明确的名字,或者要求回应里的SOAP
Body包含更多的复杂数据结构,那么只用简单地修改句柄,用以返回一个SOAP::Data对象,而不是一个初始的标量值。SOAP::Lite会自动地把返回的SOAP::Data元素串起来,放入相应的XML表示中去。以下的代码能让你完全控制方法的输出。
1 #!/usr/bin/perl
2 # Filename: Echo.pm
3 package
Echo;
4 use strict;
5 use vars qw(@ISA);
6 @ISA =
qw(SOAP::Server::Parameters);
7 sub echo {
8 my $self = shift;
9 my
$envelope = pop;
10 my $str =
$envelope->dataof("//echo/whatToEcho")->value;
11 return
SOAP::Data->name("whatWasEchoed" => "$str");
12 }
13 1;
使用SOAP::Lite编写复杂的XML数据结构并不总是直观的。要了解使用SOAP::Lite编写复杂的XML数据结构的更多信息,可以在这篇文章里进行一次实践之旅。
给回应加上SOAP Header
Web服务经常需要把SOAP
Header加到回应里返回给访问者。这在Web服务作为中间件时更加典型,但是从技术上讲,任何活动的服务都可以被允许给回应加上报头。幸运的是,给回应加上报头和在SOAP体里通过名字返回元素一样简单,只用简单地返回一个SOAP::Header元素,这和返回一个SOAP::Data是一样的。SOAP::Lite会自动地把每个SOAP::Header对象串起来,再把它们按照返回的顺序加到回应里。例如以下的代码:
1 #!/usr/bin/perl
2 # Filename: Echo.pm
3 package
Echo;
4 use strict;
5 use vars qw(@ISA);
6 @ISA =
qw(SOAP::Server::Parameters);
7 sub echo {
8 my $self = shift;
9 my
$envelope = pop;
10 my $str =
$envelope->dataof("//echo/whatToEcho")->value;
11 return
SOAP::Data->name("whatWasEchoed" => "$str"),
12
SOAP::Header->name("echoHeader1" => "something"),
13
SOAP::Header->name("echoDate" => time());
14 }
15 1;
会带来相应的SOAP回应:
<?xml version="1.0"
encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Header>
<echoHeader1
xsi:type="xsd:string">something</echoHeader1>
<echoDate
xsi:type="xsd:int">1019579390</echoDate>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<namesp1:echoResponse
xmlns:namesp1="urn:Echo">
<whatWasEchoed xsi:type="xsd:string">Echo
this
statement</whatWasEchoed>
</namesp1:echoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
生成SOAP Fault
SOAP::Lite能为你生成许多SOAP
Fault。例如,如果有人想要调用一个没有在分派句柄里定义的方法,SOAP::Lite将会返回一个带有错误串的SOAP Fault,这个错误串会是Failed
To Locate Method (Foo) In Class (Echo)这样的内容。SOAP::Lite还会为你自动生成其它的SOAP
Fault,其中的很多会在你试用SOAP::Lite时找到。不幸的是,这些SOAP Fault太多了,无法在此一一列举。
如果SOAP::Lite并不知道如何捕捉和使用SOAP
Fault来反映应用程序产生的错误,这又会怎样呢?经验丰富且熟悉Perl的die()函数的程序员,会发现从Web服务生成SOAP
Fault很容易,因为这个函数会终止Perl程序,并将指定的错误串输出到stderr。只用在服务的上下文中使用die()函数,SOAP::Lite就会将指定的错误串自动生成和返回成SOAP
Fault。
将一个简单的错误串传递给die()不会产生信息量最多的输出。但是,通过将SOAP::Fault对象传递给die()函数,你就可以设置以下这些任何一个或者所有值:错误码、错误串、错误产生者和错误细节。SOAP::Lite会自动地把SOAP::Fault对象串成一个合法的SOAP
Fault。以下这段代码可以被用在请求句柄的任何位置,以返回相应的SOAP Fault:
die
SOAP::Fault->faultcode('Server.MyFaultCode')
->faultstring('The echo
service died')
->faultdetail(bless {code => 1} =>
'BadError')
->faultactor('http://$YOUR_NAMESPACE_$HERE');
产生的SOAP Fault
<xml version="1.0"
encoding="UTF-8"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
xmlns:namesp1="http://namespaces.soaplite.com/perl">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode
xsi:type="xsd:string">SOAP-ENV:Server.MyFaultCode</faultcode>
<faultstring
xsi:type="xsd:string">The echo service
died</faultstring>
<detail>
<BadError
xsi:type="namesp1:BadError">
<code
xsi:type="xsd:int">1</code>
</BadError>
</detail>
<faultactor
xsi:type="xsd:string">http://$YOUR_NAMESPACE_$HERE</faultactor>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
即使好工具包也需要花功夫完善
尽管我对SOAP::Lite充满敬意,但是这个工具包要走的路还很长。它还要在本地完全地支持带有Attachment的SOAP下功夫,而且现在它太耗内存,其文档尤其需要大量的工作。
SOAP::Lite的在线用户指导、使用说明书和主页都有,但是你常常为了找到所需要的信息而不得不在这三者中疲于奔命。然而,SOAP::Lite活跃的、帮助很大的用户社区弥补了它在文档上的不足。如果你有问题要处理或者不知道该怎么做,我鼓励你访问SOAP::Lite的新闻组,在这里你可能会找到你任何问题的答案。如果机会好的话,SOAP::Lite的作者Paul会直接回答你的问题,这是他对着工具包所倾注心血的有力证明。
如果您希望与本文章的作者或其所在机构,进一步交流,请联系:畅享网 姜小姐
jill.jiang@amt.com.cn | 021-51096826-112 |
在线联系