﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-我的漫漫程序之旅-文章分类-WebService</title><link>http://www.blogjava.net/supercrsky/category/28819.html</link><description>专注于JavaWeb开发</description><language>zh-cn</language><lastBuildDate>Thu, 15 May 2008 10:30:12 GMT</lastBuildDate><pubDate>Thu, 15 May 2008 10:30:12 GMT</pubDate><ttl>60</ttl><item><title>基于SOAP报文的纯服务端测试</title><link>http://www.blogjava.net/supercrsky/articles/200663.html</link><dc:creator>々上善若水々</dc:creator><author>々上善若水々</author><pubDate>Thu, 15 May 2008 07:57:00 GMT</pubDate><guid>http://www.blogjava.net/supercrsky/articles/200663.html</guid><wfw:comment>http://www.blogjava.net/supercrsky/comments/200663.html</wfw:comment><comments>http://www.blogjava.net/supercrsky/articles/200663.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/supercrsky/comments/commentRss/200663.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/supercrsky/services/trackbacks/200663.html</trackback:ping><description><![CDATA[<p style="text-indent: 21pt">AbstractXFireTest扩展于JUnit标准的TestCase类，提供了向某个Web Service发送SOAP请求报文并对返回的SOAP响应报文进行检验的能力。该测试类提供了若干个方便的断言方法，分别介绍如下：</p>
<p style="margin-left: 33.05pt; text-indent: -12.05pt">—&nbsp; void assertNoFault(Document node)：确认SOAP响应报文无错误；</p>
<p style="margin-left: 33.05pt; text-indent: -12.05pt">—&nbsp; java.util.List assertValid(java.lang.String xpath, java.lang.Object node)：确认在DOM节点特定路径下有对应的元素，路径通过XPath表达式进行定义，该方法还将匹配的元素以List对象返回，用户可以对匹配的元素进行进一步检验；</p>
<p style="margin-left: 33.05pt; text-indent: -12.05pt">—&nbsp; void assertXPathEquals(java.lang.String xpath, java.lang.String value, Document node)：确认特定路径DOM节点为某一特定值；</p>
<p style="margin-left: 33.05pt; text-indent: -12.05pt">—&nbsp; assertInvalid(java.lang.String xpath, java.lang.Object node)：确认DOM节点特定路径下未包含元素。</p>
<p style="text-indent: 21pt">AbstractXFireSpringTest是AbstractXFireTest的子类，在Spring中用户只需要扩展该类并实现该类的抽象方法ApplicationContext createContext()，就可以对Spring容器中用XFire定义的Web Service进行测试了。</p>
<p style="text-indent: 21pt">为了测试Web Service，我们必须准备一个SOAP请求报文，用户可以简单地手工编写一个，或通过SOAP报文截取工具（如前面我们介绍的TcpTrace、SOAPScope、Apache Axis的TCPMon等）获得一些可用的SOAP请求报文。代码清单16-6是一个访问BbtForumService 服务的请求SOAP报文：</p>
<p style="margin: 7.2pt 0cm 3.6pt; text-indent: 21.6pt">代码清单16-6 &nbsp;request_soap.xml：SOAP报文层面测试</p>
<p style="text-indent: 0cm">&nbsp;</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">&lt;</span><span style="color: #800000">soap:Envelope&nbsp;</span><span style="color: #ff0000">xmlns:soap</span><span style="color: #0000ff">="http://schemas.xmlsoap.org/soap/envelope/"</span><span style="color: #ff0000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;xmlns:xsd</span><span style="color: #0000ff">="http://www.w3.org/2001/XMLSchema"</span><span style="color: #ff0000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;xmlns:xsi</span><span style="color: #0000ff">="http://www.w3.org/2001/XMLSchema-instance"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">soap:Body</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">getRefinedTopicCount<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #ff0000">xmlns</span><span style="color: #0000ff">="http://server.xfire.baobaotao.com"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">in0&nbsp;</span><span style="color: #ff0000">xmlns</span><span style="color: #0000ff">="http://server.xfire.baobaotao.com"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">20</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">in0</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">getRefinedTopicCount</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">soap:Body</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">soap:Envelope</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
<p style="text-indent: 0cm">&nbsp;</p>
<p style="text-indent: 21pt">我们将其保存在request_soap.xml文件中，放置在类路径com/baobaotao/xfire/server下。当该SOAP请求报文发送给BbtForumService的Web Service后，我们预计它应该返回如代码清单16-7所示的正确的SOAP响应报文：</p>
<p style="margin: 7.2pt 0cm 3.6pt; text-indent: 21.6pt">代码清单16-7&nbsp; SOAP响应报文</p>
<p style="text-indent: 0cm">&nbsp;</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">&lt;?</span><span style="color: #ff00ff">xml&nbsp;version="1.0"&nbsp;encoding="UTF-8"</span><span style="color: #0000ff">?&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">&lt;</span><span style="color: #800000">soap:Envelope&nbsp;</span><span style="color: #ff0000">xmlns:soap</span><span style="color: #0000ff">="http://schemas.xmlsoap.org/soap/envelope/"</span><span style="color: #ff0000">&nbsp;xmlns:xsd</span><span style="color: #0000ff">="http://www.w3.org/2001/XMLSchema"</span><span style="color: #ff0000">&nbsp;xmlns:xsi</span><span style="color: #0000ff">="http://www.w3.org/2001/XMLSchema-instance"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">soap:Body</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">getRefinedTopicCountResponse&nbsp;</span><span style="color: #ff0000">xmlns</span><span style="color: #0000ff">="http://www.baobaotao.com"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">out</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">32</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">out</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">getRefinedTopicCountResponse</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">soap:Body</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">soap:Envelope</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
<p style="text-indent: 0cm">&nbsp;</p>
<p style="text-indent: 21pt">下面，我们着手编写测试BbtForumService Web Service的测试类，以验证实际SOAP响应报文是否和代码清单16-7中的一样：</p>
<p style="margin: 7.2pt 0cm 3.6pt; text-indent: 21.6pt">代码清单16-8&nbsp; TestBbtForumService</p>
<div style="padding-right: 0cm; padding-left: 0cm; padding-bottom: 1pt; border-top-style: none; padding-top: 0cm; border-bottom: #999999 1pt solid; border-right-style: none; border-left-style: none">
<p style="padding-right: 0cm; padding-left: 0cm; margin-bottom: 6pt; padding-bottom: 0cm; border-top-style: none; text-indent: 0cm; padding-top: 0cm; border-right-style: none; border-left-style: none; border-bottom-style: none"><img height="512" src="http://book.csdn.net/BookFiles/466/img/image078.jpg" width="544"  alt="" /></p>
</div>
<p>使用AbstractXFireSpringTest测试Web Service首先要做的第一件事是通过实现createContext()方法构造Spring容器，如①所示。当Spring容器启动时，XFire将自动让容器中的Web Service生效（仅进行测试，不能对外提供服务）。</p>
<p style="text-indent: 21pt">第二步需要向Web Service发送一个SOAP请求报文以得到一个SOAP响应报文，如②所示。接下来，通过AbstractXFireTest提供的检测DOM内容的方法对报文进行正确性验证。由于代码清单16‑7的SOAP报文体中对应的&lt;getRefinedTopicCountResponse&gt;元素及内部元素都位于http://www.baobaotao.com命名空间中，报文体中没有为这个命名空间定义相应的别名，为了在后续断言方法中能够使用简单的方式定义XPath表达式，我们在④处为http://www.baobaotao.com命名空间定义了一个别名。</p>
<p style="text-indent: 21pt">理解以上测试代码中几个断言方法的关键在于理解XPath表达式语言，XPath语法内容很丰富，不可能在这里逐一讲解，我们只介绍一些典型的XPath语法以满足常见的测试需求：</p>
<p style="margin-left: 33.05pt; text-indent: -12.05pt">— 以&#8220;/&#8221;为前缀的路径表示从DOM根路径开始，如&#8220;/soap:Envelope/soap:Body&#8221;；</p>
<p style="margin-left: 33.05pt; text-indent: -12.05pt">— 以&#8220;//&#8221;为前缀的路径表示从DOM任意元素开始查询，如&#8220;//out&#8221;表示任意元素为out的元素；</p>
<p style="margin-left: 33.05pt; text-indent: -12.05pt">— 元素的属性通过@attrName表示，如&#8220;//xsd:complexType[@name=""Book""]&#8221;表示DOM中任意元素名为complexType并且拥有一个值为Book的name属性的元素；</p>
<p style="margin-left: 33.05pt; text-indent: -12.05pt">— 元素的值通过text()表示，如&#8220;//test:Response[text()='32']&#8221;表示DOM中任意值为32、元素名为Response，且位于test命名空间中的元素。</p>
<p style="text-indent: 21pt">现在回过头来看⑤、⑥两处的断言方法，相信大家就可以很容易地理解断言规则了，⑤处的断言检测SOAP响应报文是否包含某一特定元素，而⑥处的断言则对元素内的值进行检测。我们也可以通过printNode()方法将一个节点输出到控制台上，以便于查看。</p>
<h3>16.5.2&nbsp; 在JVM模式通过客户端进行测试</h3>
<p style="text-indent: 21pt">能够不启动Web服务器的情况下通过客户端程序测试Web Service的功能，这一崭新的测试方法对于开发人员来说一定颇具吸引力。因为，这意味着用户可以完全在IDE环境中运行测试，不需要外部环境的支持。不过享受这一测试好处的应用必须保证客户端和服务端的Web Service都位于同一JVM中，这时请求报文和响应报文直接在JVM内部通道中传输。当使用JVM内部通道传输请求和响应的SOAP报文时，我们只需要调整服务的地址就可以了：</p>
<p style="margin: 7.2pt 0cm 3.6pt; text-indent: 21.6pt">代码清单16-9&nbsp; TextBbtForumService&nbsp; JVM模式测试</p>
<p style="text-indent: 0cm"><img height="392" src="http://book.csdn.net/BookFiles/466/img/image079.jpg" width="544"  alt="" />&nbsp; </p>
<p style="text-indent: 21pt">以上代码中，①处的服务地址采用了JVM模式的地址，和其对应的HTTP地址则是http://localhost:8080/baobaotao/service/BbtForumService，所以只需要将服务名前的部分替换为&#8220;xfire.local://&#8221;就可以了。</p>
<img src ="http://www.blogjava.net/supercrsky/aggbug/200663.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/supercrsky/" target="_blank">々上善若水々</a> 2008-05-15 15:57 <a href="http://www.blogjava.net/supercrsky/articles/200663.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XFire客户端流程分析</title><link>http://www.blogjava.net/supercrsky/articles/198899.html</link><dc:creator>々上善若水々</dc:creator><author>々上善若水々</author><pubDate>Wed, 07 May 2008 03:09:00 GMT</pubDate><guid>http://www.blogjava.net/supercrsky/articles/198899.html</guid><wfw:comment>http://www.blogjava.net/supercrsky/comments/198899.html</wfw:comment><comments>http://www.blogjava.net/supercrsky/articles/198899.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/supercrsky/comments/commentRss/198899.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/supercrsky/services/trackbacks/198899.html</trackback:ping><description><![CDATA[<p style="text-indent: 21pt">XFire<span style="font-family: 宋体">是当前</span>J2EE<span style="font-family: 宋体">领域非常流行的</span>Web Service<span style="font-family: 宋体">框架，以其卓越的性能和简单易用的特性博得了广大开发者的青睐。目前</span>XFire<span style="font-family: 宋体">已经演变为</span>Apache<span style="font-family: 宋体">的</span>CXF<span style="font-family: 宋体">项目，但仍有大量用户在使用</span>XFire<span style="font-family: 宋体">。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">下面是</span>XFire<span style="font-family: 宋体">客户端调用的流程分析图，本文后续本分将围绕该图展开。</span></p>
<p style="text-indent: 21pt"><a href="http://www.blogjava.net/images/blogjava_net/hywavesoft/5589/o_xfireClient.jpg"><img height="320" alt="" src="http://www.blogjava.net/images/blogjava_net/hywavesoft/5589/r_xfireClient.jpg" width="640" border="0" /></a></p>
<p style="text-indent: 21pt">XFire<span style="font-family: 宋体">客户端的调用非常灵活，可以有很多种方式，如通过配置调用、通过</span>API<span style="font-family: 宋体">编程调用或者与</span>Spring<span style="font-family: 宋体">等</span>IoC<span style="font-family: 宋体">框架集成使用。虽然调用方式灵活多样，但万变不离其中，其内部流程是一致的。</span></p>
<h3><span style="font-family: 宋体">创建服务模型</span></h3>
<p style="text-indent: 21pt"><span style="font-family: 宋体">服务模型是</span>XFire<span style="font-family: 宋体">中非常重要的概念之一，包含了服务的接口信息、操作信息、</span>Binding<span style="font-family: 宋体">信息等诸多服务调用过程中需要的信息。因此在进行服务调用之前首先要创建服务模型。创建服务模型的工作是由服务工厂</span>ServiceFactory<span style="font-family: 宋体">完成的，用户需要为服务工程提供服务接口、名称、命名空间等一些信息，其中服务接口是必须的，其他为可选信息。</span></p>
<h3><span style="font-family: 宋体">创建</span>Client<span style="font-family: 宋体">实例</span></h3>
<p style="text-indent: 21pt">Client<span style="font-family: 宋体">是</span>XFire<span style="font-family: 宋体">客户端的核心组成部分，间接的代表了一个服务。当为具体某个服务配置拦截器（</span>Handler<span style="font-family: 宋体">，有很多种译法如拦截器、处理器、过滤器等，本文统一用拦截器）时，其实是将拦截器信息应用到</span>Client<span style="font-family: 宋体">实例上。</span>Client<span style="font-family: 宋体">可以手工创建也可以由</span>XFireProxyFactory<span style="font-family: 宋体">创建，无论通过哪种方式，</span>Client<span style="font-family: 宋体">在初始化过程中最重要的一步都是在</span>out<span style="font-family: 宋体">拦截器堆栈中增加一个</span>OutMessageSender<span style="font-family: 宋体">拦截器。该拦截器负责最终将服务调用通过</span>HTTP<span style="font-family: 宋体">发送到服务提供者并返回处理结果。本文后续部分还会对</span>OutMessageSender<span style="font-family: 宋体">做更加详细的讲解。</span></p>
<h3><span style="font-family: 宋体">创建服务代理对象</span></h3>
<p style="text-indent: 21pt">XFireProxy<span style="font-family: 宋体">，</span>XFire SOAP<span style="font-family: 宋体">客户端代理实现，用户调用服务时（如</span>Hello.echo(&#8220;tony&#8221;)<span style="font-family: 宋体">）就是通过该对象的</span>invoke<span style="font-family: 宋体">方法来执行。实际上，</span>XFireProxy<span style="font-family: 宋体">只是将调用代理到</span>Client<span style="font-family: 宋体">实例，最终执行服务的还是</span>Client<span style="font-family: 宋体">实例。</span></p>
<h3><span style="font-family: 宋体">构造调用链信息</span></h3>
<p style="text-indent: 21pt">Client<span style="font-family: 宋体">实例的</span>invoke<span style="font-family: 宋体">方法在执行时，生成了一个</span>Invocation<span style="font-family: 宋体">对象，该对象构造了一次完整的调用信息，包括</span>OutMessage<span style="font-family: 宋体">、</span>MessageContext<span style="font-family: 宋体">等。同时</span>Invocation<span style="font-family: 宋体">还负责构造一个拦截器管道（</span>HandlerPipeline<span style="font-family: 宋体">），该管道包含了本次调用需要执行的所有拦截器，当然也包括</span>OutMessageSender<span style="font-family: 宋体">。这些拦截器会分不同的阶段来执行，这也是</span>XFire<span style="font-family: 宋体">一个特性。</span>XFire<span style="font-family: 宋体">默认定义了很多阶段（</span>Phase<span style="font-family: 宋体">），每个阶段都会有若干拦截器被调用。</span></p>
<h3><span style="font-family: 宋体">循环调用拦截器</span></h3>
<p style="text-indent: 21pt"><span style="font-family: 宋体">拦截器（</span>Handler<span style="font-family: 宋体">）是</span>XFire<span style="font-family: 宋体">中最为重要的概念，一次服务调用就是由若干拦截器组合完成的。</span>XFire<span style="font-family: 宋体">默认提供了很多预定义的拦截器，用户也可以定义自己的拦截器。基本上，通过拦截器可以影响</span>XFire<span style="font-family: 宋体">执行过程中的任何步骤，你可以为所欲为：）</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">拦截器有两个重要的概念，一个是阶段（</span>Phase<span style="font-family: 宋体">），一个是顺序（</span>Order<span style="font-family: 宋体">）。这两个因素共同决定了拦截器的执行顺序。可以在三个不同的地方配置拦截器：</span></p>
<p style="margin-left: 42pt; text-indent: -21pt; tab-stops: list 42.0pt"><span style="font-family: Wingdings">n<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>XFire<span style="font-family: 宋体">实例：全局拦截器，对所有通道上的所有服务起作用</span></p>
<p style="margin-left: 42pt; text-indent: -21pt; tab-stops: list 42.0pt"><span style="font-family: Wingdings">n<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>Transport<span style="font-family: 宋体">：通道特定的拦截器，只对该通道（如</span>HTTP<span style="font-family: 宋体">、</span>JMS<span style="font-family: 宋体">）起作用</span></p>
<p style="margin-left: 42pt; text-indent: -21pt; tab-stops: list 42.0pt"><span style="font-family: Wingdings">n<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体">具体服务：服务特定的拦截器，只对该服务起作用</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">其实，具体服务上的拦截器最终是配置到</span>Client<span style="font-family: 宋体">上。对于同一个阶段上的拦截器，执行顺序为&#8220;具体服务—</span>&gt;Transport<span style="font-family: 宋体">—</span>&gt;XFire<span style="font-family: 宋体">实例&#8221;。千万不要忽视这些顺序，这对你正确的使用拦截器非常有帮助。</span></p>
<h3><span style="font-family: 宋体">发送远程服务请求</span></h3>
<p style="text-indent: 21pt"><span style="font-family: 宋体">这是整个调用链中最后的一环，也是最关键的一步。</span>OutMessageHandler<span style="font-family: 宋体">，前文已经有所提及，是一个特殊的拦截器，在</span>Client<span style="font-family: 宋体">初始化时创建并加入调用链中。该拦截器处于拦截器调用链的</span>Phase.SEND<span style="font-family: 宋体">阶段，基本上也是最后的阶段。</span>OutMessageHandler<span style="font-family: 宋体">从当前调用的消息上下文（</span>MessageContext<span style="font-family: 宋体">）中获取请求的服务地址</span>URI<span style="font-family: 宋体">以及</span>SOAP<span style="font-family: 宋体">消息，然后通过</span>HTTP<span style="font-family: 宋体">将</span>SOAP<span style="font-family: 宋体">请求发送到远程服务器（针对</span>HTTP<span style="font-family: 宋体">通道，如果是</span>JMS<span style="font-family: 宋体">通道则发送到指定的目的地）。最终将远程服务器的响应逐级返回给调用者。</span></p>
<h3><span style="font-family: 宋体">案例分析</span></h3>
<p style="text-indent: 21pt"><span style="font-family: 宋体">前文很多地方都提到</span>Handler<span style="font-family: 宋体">非常重要，那么具体有那些应用场景呢？本部分通过两个案例逐步演示</span>Handler<span style="font-family: 宋体">的应用。</span></p>
<p style="margin-left: 42pt; text-indent: -21pt; tab-stops: list 42.0pt"><strong>一、<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></strong><strong><span style="font-family: 宋体">简单安全验证</span></strong></p>
<p style="margin-left: 21pt; text-indent: 21pt"><span style="font-family: 宋体">这是一个非常典型的应用场景，假设</span>A<span style="font-family: 宋体">公司对外提供了一个旅程信息查询服务，该服务通过</span>XFire<span style="font-family: 宋体">对外发布。但是</span>A<span style="font-family: 宋体">公司只希望其合作伙伴才能使用该服务，那么</span>A<span style="font-family: 宋体">公司可以为该服务配置一个</span>Handler<span style="font-family: 宋体">，该</span>Handler<span style="font-family: 宋体">从</span>SOAP<span style="font-family: 宋体">的消息头中获取认证字符串，只有通过验证的请求才被执行。下面是简单的示例代码，真实情况要比这复杂得多。</span></p>
<table style="border-right: medium none; border-top: medium none; background: #e5e5e5; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tbody>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="568">
            <p style="text-indent: 14.75pt; line-height: normal; text-align: left" align="left"><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">public</span></strong><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">void</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New'"> invoke(MessageContext context) </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">throws</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New'"> Exception { </span></p>
            <p style="text-indent: 30pt; line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">Element header = context.getInMessage().getHeader();&nbsp;&nbsp; </span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String <span style="background: silver">authCode</span> = header.getChild(</span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New'">"authCode"</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">,</span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">null</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New'">).getValue();</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">if</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New'">(!</span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New'">"tony"</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">.equals(<span style="background: silver">authCode</span>)){</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">throw</span></strong><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">new</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New'"> XFireFault(</span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New'">"Authentication Fail!"</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">, XFireFault.</span><em><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">SENDER</span></em><span style="font-size: 10pt; color: black; font-family: 'Courier New'">);</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;}</span></p>
            <p><span style="font-size: 10pt; color: black; line-height: 150%; font-family: 'Courier New'">}</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p style="margin-left: 21pt; text-indent: 21pt"><span style="font-family: 宋体">对于</span>A<span style="font-family: 宋体">公司的合作伙伴，要想调用该服务，必须在其</span>SOAP<span style="font-family: 宋体">的消息头中包含上面代码中的验证字符串，否则服务将被拒绝。下面是简单的示例代码：</span></p>
<table style="border-right: medium none; border-top: medium none; background: #e5e5e5; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tbody>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="568">
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">public</span></strong><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">void</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New'"> invoke(MessageContext context) </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">throws</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New'"> Exception {</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Element header = context.getInMessage().getHeader();</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Element authCode = </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">new</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New'"> Element(</span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New'">"authCode"</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">);</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; authCode.addContent(</span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New'">"tony"</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">);</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; header.addContent(authCode);</span></p>
            <p><span style="font-size: 10pt; color: black; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; }</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p style="margin-left: 42pt; text-indent: -21pt; tab-stops: list 42.0pt"><strong>二、<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></strong><strong><span style="font-family: 宋体">查找真实服务</span></strong></p>
<p style="margin-left: 21pt; text-indent: 21pt"><span style="font-family: 宋体">这是一个比较特殊的应用场景：假设</span>A<span style="font-family: 宋体">公司已经初步实现</span>SOA<span style="font-family: 宋体">，拥有一个服务注册中心，所有的</span>XFire<span style="font-family: 宋体">服务都在该中心注册。客户端在调用服务时需要动态的从该服务注册中心获取当前的服务地址及版本。通过其他方式肯定也可以实现该需求，但是通过</span>Handler<span style="font-family: 宋体">来实现会非常的幽雅，而且对应用不需要做任何变动。我们先来看一下</span>Handler<span style="font-family: 宋体">的代码：</span></p>
<table style="border-right: medium none; border-top: medium none; background: #e5e5e5; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tbody>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="568">
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">public</span></strong><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">void</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New'"> invoke(MessageContext context) </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">throws</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New'"> Exception {</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: #3f7f5f; font-family: 'Courier New'">// 1.</span><span style="font-size: 10pt; color: #3f7f5f; font-family: 宋体">寻址</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lookupRealServiceUri(context);</span></p>
            <p style="text-indent: 21pt"><span style="font-size: 10pt; color: black; line-height: 150%; font-family: 'Courier New'">}</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">private</span></strong><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">void</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New'"> lookupRealServiceUri(MessageContext context) {</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String uri = context.getOutMessage().getUri();</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">try</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New'"> {</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uri = </span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New'">serviceLocator</span><span style="font-size: 10pt; color: black; font-family: 'Courier New'">.lookup(requestEnvironment, uri);</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New'">catch</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New'"> (</span><u><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">Exception</span></u><span style="font-size: 10pt; color: black; font-family: 'Courier New'"> e) {</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: #3f7f5f; font-family: 'Courier New'">// Ignoral this exception</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
            <p style="line-height: normal; text-align: left" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.getOutMessage().setUri(uri);</span></p>
            <p><span style="font-size: 10pt; color: black; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; }</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p style="margin-left: 21pt; text-indent: 21pt"><span style="font-family: 宋体">正如代码所示，只需要从</span>context<span style="font-family: 宋体">中获取当前请求的服务</span>URI<span style="font-family: 宋体">地址，然后用当前请求环境信息及服务</span>URI<span style="font-family: 宋体">地址到服务注册中心查找真实的服务，并重新设置服务的地址。</span></p>
<h3><span style="font-family: 宋体">结束语</span></h3>
<p style="margin-left: 21pt; text-indent: 21pt"><span style="font-family: 宋体">本文粗略的介绍了</span>XFire<span style="font-family: 宋体">客户端的调用流程，并着重讲解了</span>Handler<span style="font-family: 宋体">的扩展机制及其应用场景，力求读者能够通过本文对</span>XFire<span style="font-family: 宋体">能有更加深入的了解和掌握。文中难免存在不足之处，欢迎任何形式的交流。</span></p>
<img src ="http://www.blogjava.net/supercrsky/aggbug/198899.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/supercrsky/" target="_blank">々上善若水々</a> 2008-05-07 11:09 <a href="http://www.blogjava.net/supercrsky/articles/198899.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实施WebService Security[WS-Security1.0]的Encrypt和Sign模式(XFire+WSS4J) </title><link>http://www.blogjava.net/supercrsky/articles/198898.html</link><dc:creator>々上善若水々</dc:creator><author>々上善若水々</author><pubDate>Wed, 07 May 2008 03:08:00 GMT</pubDate><guid>http://www.blogjava.net/supercrsky/articles/198898.html</guid><wfw:comment>http://www.blogjava.net/supercrsky/comments/198898.html</wfw:comment><comments>http://www.blogjava.net/supercrsky/articles/198898.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/supercrsky/comments/commentRss/198898.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/supercrsky/services/trackbacks/198898.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 鉴于很多系统需要实施WS-Security的标准，我们在SpringSide中提供了XFire+WSS4J的Demo，本文介绍SpringSide中Spring+XFire+WSS4J的基本配置[WebService Server端配置]第一，创建一个基本的BookServicepublic&nbsp;interface&nbsp;BookService&nbsp;{&nbsp...&nbsp;&nbsp;<a href='http://www.blogjava.net/supercrsky/articles/198898.html'>阅读全文</a><img src ="http://www.blogjava.net/supercrsky/aggbug/198898.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/supercrsky/" target="_blank">々上善若水々</a> 2008-05-07 11:08 <a href="http://www.blogjava.net/supercrsky/articles/198898.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>图文并茂——使用xfire编写webservice,并通过C#调用</title><link>http://www.blogjava.net/supercrsky/articles/197283.html</link><dc:creator>々上善若水々</dc:creator><author>々上善若水々</author><pubDate>Tue, 29 Apr 2008 07:41:00 GMT</pubDate><guid>http://www.blogjava.net/supercrsky/articles/197283.html</guid><wfw:comment>http://www.blogjava.net/supercrsky/comments/197283.html</wfw:comment><comments>http://www.blogjava.net/supercrsky/articles/197283.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/supercrsky/comments/commentRss/197283.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/supercrsky/services/trackbacks/197283.html</trackback:ping><description><![CDATA[&nbsp;我没学习过axis系列，一开始学的就是xfire，myeclipse5.1支持xfire支持的非常棒。这里讲解一个简单的例子，<br />
1.首先建立一个web service工程：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img height="428" alt="new_wizard1.gif" src="http://www.blogjava.net/images/blogjava_net/killme2008/new_wizard1.gif" width="354" border="0" /><br />
<img height="411" alt="new_wizard2.gif" src="http://www.blogjava.net/images/blogjava_net/killme2008/new_wizard2.gif" width="460" border="0" /><br />
<hr width="100%" size="2" />
<img height="411" alt="new_wizard3.gif" src="http://www.blogjava.net/images/blogjava_net/killme2008/new_wizard3.gif" width="460" border="0" /><br />
<img height="496" alt="4.BMP" src="http://www.blogjava.net/images/blogjava_net/killme2008/4.BMP" width="615" border="0" /><br />
<br />
<br />
点击finish之后，myeclipse自动帮你生成services.xml以及web应用目录结构，其中的services.xml是你导出服务的配置文件，注意在WEB-INF/web.xml文件中配置了xfire自己的servlet.<br />
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">servlet</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">servlet-name</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">XFireServlet</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">servlet-name</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">servlet-class</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">org.codehaus.xfire.transport.http.XFireConfigurableServlet</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">servlet-class</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">load-on-startup</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">0</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">load-on-startup</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">servlet</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">servlet-mapping</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">servlet-name</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">XFireServlet</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">servlet-name</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">url-pattern</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">/services/*</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">url-pattern</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">servlet-mapping</span><span style="color: rgb(0,0,255)">&gt;</span></div>
<br />
<br />
2.接下来，现在编写要导出的pojo类，首先是接口：<br />
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,0,255)">package</span><span style="color: rgb(0,0,0)">&nbsp;net.rubyeye.webservicedemo;<br />
<br />
</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">Generated&nbsp;by&nbsp;MyEclipse</span><span style="color: rgb(0,128,0)"><br />
</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">interface</span><span style="color: rgb(0,0,0)">&nbsp;IHelloWorldService&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;String&nbsp;sayHello(String&nbsp;name);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
}</span></div>
<br />
这个接口我们只提供一个方法:sayHello()，我们没有采用JSR181标注式的声明方式，还是采用xml配置文件。然后是实现类：<br />
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,0,255)">package</span><span style="color: rgb(0,0,0)">&nbsp;net.rubyeye.webservicedemo;<br />
<br />
</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">Generated&nbsp;by&nbsp;MyEclipse</span><span style="color: rgb(0,128,0)"><br />
</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)">&nbsp;HelloWorldServiceImpl&nbsp;</span><span style="color: rgb(0,0,255)">implements</span><span style="color: rgb(0,0,0)">&nbsp;IHelloWorldService&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;String&nbsp;sayHello(String&nbsp;name){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">hello,</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">+</span><span style="color: rgb(0,0,0)">name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
}</span></div>
<br />
最后，配置下services.xml文件:<br />
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">service</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">name</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">HelloWorldService</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">name</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">serviceClass</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;net.rubyeye.webservicedemo.IHelloWorldService<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">serviceClass</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">implementationClass</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;net.rubyeye.webservicedemo.HelloWorldServiceImpl<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">implementationClass</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">style</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">wrapped</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">style</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">use</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">literal</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">use</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">scope</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">application</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">scope</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">service</span><span style="color: rgb(0,0,255)">&gt;</span></div>
<br />
我们的web服务名称叫做<span style="color: rgb(0,0,0)">HelloWorldService，接口是</span><span style="color: rgb(0,0,0)">IHelloWorldService，实现类是</span><span style="color: rgb(0,0,0)">HelloWorldServiceImpl。<strong>注意，其实我们这三个步骤可以一步完成，只要直接使用myeclipse的new web service向导即可</strong><br />
<br />
<img height="598" alt="new_webservice_wiz1.gif" src="http://www.blogjava.net/images/blogjava_net/killme2008/new_webservice_wiz1.gif" width="394" border="0" /><br />
</span><img height="458" alt="new_webservice_wiz1_codefirst2.gif" src="http://www.blogjava.net/images/blogjava_net/killme2008/new_webservice_wiz1_codefirst2.gif" width="492" border="0" /><br />
<br />
<br />
3.然后将此工程部署到tomcat上，通过http://localhost:8081/HelloWorld/services/HelloWorldService?wsdl可以看到生成的wsdl文件。注意，在部署之后，services会被拷贝到WEB-INF\classes\META-INF\xfire目录下，xfire会自动搜索此目录并加载配置文件。我们可以编写一个client来测试web服务，你也可以点击myeclipse上的Launch the Web Services来测试web服务<br />
<br />
<img height="120" alt="webexplorer_launch.gif" src="http://www.blogjava.net/images/blogjava_net/killme2008/webexplorer_launch.gif" width="261" border="0" /><br />
<br />
<br />
4.编写client代码：<br />
<br />
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,0,255)">package</span><span style="color: rgb(0,0,0)">&nbsp;net.rubyeye.webservicedemo;<br />
<br />
</span><span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;java.net.MalformedURLException;<br />
</span><span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;java.util.ArrayList;<br />
</span><span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;java.util.List;<br />
<br />
</span><span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;org.codehaus.xfire.XFireFactory;<br />
</span><span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;org.codehaus.xfire.client.XFireProxyFactory;<br />
</span><span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;org.codehaus.xfire.service.Service;<br />
</span><span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;org.codehaus.xfire.service.binding.ObjectServiceFactory;<br />
<br />
</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)">&nbsp;HelloWorldClient&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">static</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;main(String&nbsp;args[])&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Service&nbsp;srvcModel&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;ObjectServiceFactory()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.create(IHelloWorldService.</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XFireProxyFactory&nbsp;factory&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;XFireProxyFactory(XFireFactory<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.newInstance().getXFire());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;helloWorldURL&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">http://localhost:8081/HelloWorld/services/HelloWorldService</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">try</span><span style="color: rgb(0,0,0)">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IHelloWorldService&nbsp;srvc&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;(IHelloWorldService)&nbsp;factory.create(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;srvcModel,&nbsp;helloWorldURL);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print(srvc.sayHello(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">dennis</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: rgb(0,0,255)">catch</span><span style="color: rgb(0,0,0)">&nbsp;(MalformedURLException&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</span></div>
<br />
<span style="color: rgb(0,0,0)">执行，打印：hello,dennis<br />
<br />
<strong>注意，你也可以使用MyEclipse的new webservice client向导自动生成client，同时生成供客户端调用的stub类等。<br />
<br />
</strong>最后，我们再编写一个C#调用此web service的例子。<br />
1.在vs.net中新建一个windows 应用程序项目，并添加一个button，和一个label<br />
<img height="255" alt="c1.BMP" src="http://www.blogjava.net/images/blogjava_net/killme2008/c1.BMP" width="362" border="0" /><br />
<img height="364" alt="c2.BMP" src="http://www.blogjava.net/images/blogjava_net/killme2008/c2.BMP" width="320" border="0" /><br />
<br />
2.项目菜单——》添加web应用，输入我们要调用的web服务的wsdl文件的url，并点击前往。<br />
<img height="469" alt="c3.BMP" src="http://www.blogjava.net/images/blogjava_net/killme2008/c3.BMP" width="713" border="0" /><br />
<br />
<br />
3.添加引用之后，vs.net会自动帮你生成提供给客户端调用的stub等，这些文件在名为localhost的命名空间下。此空间下将有一个类，名为HelloWorldService。最后，在button1的onclick事件中添加代码：<br />
<br />
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,0,255)">using</span><span style="color: rgb(0,0,0)">&nbsp;System;<br />
</span><span style="color: rgb(0,0,255)">using</span><span style="color: rgb(0,0,0)">&nbsp;System.Collections.Generic;<br />
</span><span style="color: rgb(0,0,255)">using</span><span style="color: rgb(0,0,0)">&nbsp;System.ComponentModel;<br />
</span><span style="color: rgb(0,0,255)">using</span><span style="color: rgb(0,0,0)">&nbsp;System.Data;<br />
</span><span style="color: rgb(0,0,255)">using</span><span style="color: rgb(0,0,0)">&nbsp;System.Drawing;<br />
</span><span style="color: rgb(0,0,255)">using</span><span style="color: rgb(0,0,0)">&nbsp;System.Text;<br />
</span><span style="color: rgb(0,0,255)">using</span><span style="color: rgb(0,0,0)">&nbsp;System.Windows.Forms;<br />
<br />
</span><span style="color: rgb(0,0,255)">namespace</span><span style="color: rgb(0,0,0)">&nbsp;MyProject<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;partial&nbsp;</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)">&nbsp;Form1&nbsp;:&nbsp;Form<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;localhost.HelloWorldService&nbsp;helloService&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;localhost.HelloWorldService();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Form1()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitializeComponent();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">private</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;button1_Click(</span><span style="color: rgb(0,0,255)">object</span><span style="color: rgb(0,0,0)">&nbsp;sender,&nbsp;EventArgs&nbsp;e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;label1.Text&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;helloService.sayHello(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">dennis</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
我们new一个</span><span style="color: rgb(0,0,0)"><span style="color: rgb(0,0,0)">HelloWorldService ，并调用sayHello方法，将结果显示在label上</span></span><br />
<span style="color: rgb(0,0,0)">4.执行ctr+F5<br />
<br />
<img height="298" alt="c4.BMP" src="http://www.blogjava.net/images/blogjava_net/killme2008/c4.BMP" width="318" border="0" /><br />
<br />
<br />
<img height="294" alt="c5.BMP" src="http://www.blogjava.net/images/blogjava_net/killme2008/c5.BMP" width="311" border="0" /></span>
<img src ="http://www.blogjava.net/supercrsky/aggbug/197283.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/supercrsky/" target="_blank">々上善若水々</a> 2008-04-29 15:41 <a href="http://www.blogjava.net/supercrsky/articles/197283.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.Net/C# 与 J2EE/Java Web Service 互操作完整实例 </title><link>http://www.blogjava.net/supercrsky/articles/197050.html</link><dc:creator>々上善若水々</dc:creator><author>々上善若水々</author><pubDate>Tue, 29 Apr 2008 03:00:00 GMT</pubDate><guid>http://www.blogjava.net/supercrsky/articles/197050.html</guid><wfw:comment>http://www.blogjava.net/supercrsky/comments/197050.html</wfw:comment><comments>http://www.blogjava.net/supercrsky/articles/197050.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/supercrsky/comments/commentRss/197050.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/supercrsky/services/trackbacks/197050.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: .Net 与 J2EE/Java Web Service 互操作完整实例实现支持文件分块多点异步上传的 J2EE/Java Web Services 及其 .Net 非 Web 客户端应用程序异步上传本文参考:实现支持文件分块多点异步上传的 Web Services 及其客户端(非Web)应用程序调用相关异步执行的 Web Methodhttp://blog.csdn.net/pl...&nbsp;&nbsp;<a href='http://www.blogjava.net/supercrsky/articles/197050.html'>阅读全文</a><img src ="http://www.blogjava.net/supercrsky/aggbug/197050.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/supercrsky/" target="_blank">々上善若水々</a> 2008-04-29 11:00 <a href="http://www.blogjava.net/supercrsky/articles/197050.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XPath详解</title><link>http://www.blogjava.net/supercrsky/articles/196011.html</link><dc:creator>々上善若水々</dc:creator><author>々上善若水々</author><pubDate>Fri, 25 Apr 2008 09:02:00 GMT</pubDate><guid>http://www.blogjava.net/supercrsky/articles/196011.html</guid><wfw:comment>http://www.blogjava.net/supercrsky/comments/196011.html</wfw:comment><comments>http://www.blogjava.net/supercrsky/articles/196011.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/supercrsky/comments/commentRss/196011.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/supercrsky/services/trackbacks/196011.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 以下是本人找到的最完整最易懂的XPath教程，不敢私藏，拿出来与大家分享。实例 1基本的XPath语法类似于在一个文件系统中定位文件,如果路径以斜线 / 开始, 那么该路径就表示到一个元素的绝对路径                                    /AAA                                       ...&nbsp;&nbsp;<a href='http://www.blogjava.net/supercrsky/articles/196011.html'>阅读全文</a><img src ="http://www.blogjava.net/supercrsky/aggbug/196011.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/supercrsky/" target="_blank">々上善若水々</a> 2008-04-25 17:02 <a href="http://www.blogjava.net/supercrsky/articles/196011.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java开发WebService实例--计数器</title><link>http://www.blogjava.net/supercrsky/articles/196012.html</link><dc:creator>々上善若水々</dc:creator><author>々上善若水々</author><pubDate>Fri, 25 Apr 2008 09:02:00 GMT</pubDate><guid>http://www.blogjava.net/supercrsky/articles/196012.html</guid><wfw:comment>http://www.blogjava.net/supercrsky/comments/196012.html</wfw:comment><comments>http://www.blogjava.net/supercrsky/articles/196012.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/supercrsky/comments/commentRss/196012.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/supercrsky/services/trackbacks/196012.html</trackback:ping><description><![CDATA[&nbsp; 如果使用GOOGLE、BAIDU等搜索工具，搜索WebService的相关知识，可以查到N多的网页，我就是通过这些网页的学习，逐渐掌握了些WebService的相关知识。这里对那些无私奉献知识的人一并表示感谢。
<p>
网上关于WebService的例子，多是一些简单得不能再简单的hello
world的例子，简单得以至于你对WebService没有什么感觉。有了WebService的基本知识后，我一直再想，可以把什么样的即简单又实用
的东东做成WebService，开展示一下其功能特点。今天终于想到一个：计数器，计数器用得比较多，功能比较独立，做成WebService可以一劳
永逸为不同系统（不管是JSP还ASP，这是WebService的突出优点）、不同应用节省此类编码工作，可以说以后再也不用写计数器了。只要用就行
了。 <br />
<br />
&nbsp; 说了这么多废话，下面我们开始。本教程介绍一下WebService环境搭建、服务部署的相关知识，然后介绍一个计数器的开发。   <br />
<br />
运行图：</p>
<p><span><strong><img src="http://www.java3z.com/cwbwebhome/article/article5/img/9725623.gif" height="347" width="483"  alt="" /><br />
<br />
二、基础工作</strong></span><br />
<br />
1.开发环境<br />
我使用axis做为Web
Service引擎，它是Apache的一个开源web service引擎。它目前最为成熟的开源web
service引擎之一。下面我主要介绍一下如何使用Axis搭建web service 服务的环境。 <br />
①安装tomcat5.0应用服务器（也可以装5.5，不过我一直在用5.0）;   <br />
②解压下载（
http://ws.apache.org/Axis）后的axis包，将包中axis目录复制到tomcat目录下的webapps目录下；　　   <br />
③将axis/WEB-INF/lib目录下类文件复制到tomcat目录下的common/lib目录下；   <br />
④重新启动tomcat,访问http://localhost:8080/axis/happyaxis.jsp,如果能访问，表示安装成功；   <br />
注意，axis有几个可选的包，如email.jar....，你可以找来放到tomcat目录下的common/lib目录下，如果不使用相关的功能也可以不用。   <br />
这样，开发环境就搭建好了。   <br />
<br />
<br />
2.如何部署Web Service<br />
部署有三种方式：Dynamic Invocation
Interface(DII)、Stubs方式、Dynamic Proxy方式；这里就介绍一下简单，也是我使用的方式：DII。   <br />
DII方式中，先写好服务的JAVA文件（假设名字为helloworld.java），然后把它（注意是源文件）拷贝到webapps/axis目录
中，后缀改成jws(此时文件名为：helloworld.jws)，然后访问连接http://localhost:
8080/Axis/helloworld.jws?wsdl，页面显示Axis自动生成的wsdl，这样一个Web
Service就部署好了。怎么样，是不是很简。 <br />
我的计数器服务就是以这种方式部署的，下文中我会只说将计数器服务部署好，你可不要说：怎么部署，我不会呀。那在古代就要被打手板了。所以我想，古代只学四书五经也是件好事呀。现在要学这么多东西，半天学不会，手要被打烂了。   </p>
<p><strong>三、计数器服务的编写</strong> <br />
计数器大家都知道了，比较简单。我的计数器也同样简单，有以下功能及特点：提供四种计数器（总数器、月计数器、周计数器及日计数器）；考虑到Web
Service要服务于多种应用，这个计数器还支持多个用户；使用XML文件来记录数据。<br />
记录文件名为：d:"counter.xml。注意，此文件在服务里是硬编码，如果修改名字，请在服务程序中也进行相应的修改。文件内容格式如下：   <br />
&lt;?xml version="1.0"
encoding="UTF-8"?&gt;<br />
&lt;counter&gt;<br />
&lt;item&gt;<br />
&lt;name&gt;wallimn&lt;/name&gt;<br />
&lt;password&gt;123&lt;/password&gt;<br />
&lt;dc&gt;59&lt;/dc&gt;<br />
&lt;wc&gt;59&lt;/wc&gt;<br />
&lt;mc&gt;59&lt;/mc&gt;<br />
&lt;tc&gt;59&lt;/tc&gt;<br />
&lt;rt&gt;2007-4-16
16:01:29&lt;/rt&gt;<br />
&lt;/item&gt;<br />
&lt;counter&gt;<br />
说是计数器服务，其实跟编写普通的JAVA应用没有什么两样。我的计数器代码比较简单，我就不做过多的介绍了，把它贴在下面，源码中有少量注释，相信大家不看注释也看得懂。服务有只有一个接口：Counter(String
name, String
password),以后在客户端拿来用就可以了。还多说一句，我和程序使用到了dom4j解析xml包，要调试的请自行准备好jar包。部署方法请参照上文。   <br />
import java.io.File;<br />
import java.io.FileWriter;<br />
import
java.io.IOException;<br />
import java.text.DateFormat;<br />
import
java.text.ParseException;<br />
import java.util.Calendar;<br />
import
java.util.Date;<br />
import java.util.Iterator;<br />
import
org.dom4j.Document;<br />
import org.dom4j.DocumentException;<br />
import
org.dom4j.Element;<br />
import org.dom4j.io.SAXReader;<br />
import
org.dom4j.io.XMLWriter;<br />
/**<br />
*功能：提供计数器服务的WebService，可以为多用户提供服务。&lt;br/&gt;<br />
*
@version : V1.0<br />
* @author : 王力猛(Email: wallimn@sohu.com QQ: 54871876)<br />
*
@date : 2007-4-16 下午04:32:45<br />
*/<br />
public class WsCounterByWallimn
{<br />
//计数器文档，注意名字名路径。<br />
private final String FileN =
"d:/counter.xml";<br />
private final static DateFormat DATEFORMATER =
DateFormat.getDateTimeInstance();<br />
//出错的情况下返回的值<br />
private final static String
ERRORINFO="-1;-1;-1;-1";<br />
public WsCounterByWallimn(){
}<br />
<br />
<br />
/**<br />
*功能：打开计数器文档&lt;br/&gt;<br />
*编码：王力猛 时间：2007-4-16
下午04:44:29&lt;br/&gt;<br />
*/<br />
private Document openDocument(){<br />
Document
doc=null;<br />
SAXReader reader = new SAXReader();<br />
try {<br />
File xmlfile = new
File(FileN);<br />
doc = reader.read(xmlfile);<br />
xmlfile=null;<br />
} <br />
catch
(DocumentException e) {<br />
e.printStackTrace();<br />
}<br />
return
doc;<br />
}<br />
<br />
<br />
/**<br />
*功能：取指定名称计数器的详细信息，并设置计数器加1。&lt;br/&gt;<br />
*编码：王力猛
时间：2007-4-16 下午04:49:57&lt;br/&gt;<br />
*/<br />
private synchronized String
countertick( String name, String password){<br />
Document doc =
openDocument();<br />
Date currdt = new java.util.Date();<br />
//mc:month
counter(月计数器); dc: day counter(日计数器); <br />
//tc: total counter(总计数器); wc: week
counter(周计数器);<br />
//rt: registe time登记时间<br />
String
mc="-1",dc="-1",tc="-1",wc="-1",rt="-1";<br />
Element root =
doc.getRootElement();<br />
Element selitem=null,item=null;<br />
for(Iterator it =
root.elementIterator("item"); it.hasNext();){<br />
item =
(Element)it.next();<br />
if(name.equals(item.element("name").getText())){ <br />
selitem=item;<br />
String pwd =
item.elementText("password");<br />
if(!password.equals(pwd)){<br />
return
ERRORINFO;//密码不对，直接返回<br />
}<br />
mc=item.element("mc").getText();<br />
dc=item.element("dc").getText();<br />
tc=item.element("tc").getText();<br />
wc=item.element("wc").getText();<br />
rt=item.element("rt").getText();<br />
break;<br />
}<br />
}<br />
<br />
//如果selitem为空，说明没有个名字的计数器。则添加一个。<br />
if(selitem==null){<br />
//System.out.println("没有找到这个名字的计数器："+name);<br />
rt=DATEFORMATER.format(currdt);<br />
selitem
=
doc.getRootElement().addElement("item");<br />
selitem.addElement("name").setText(name);<br />
selitem.addElement("tc").setText("0");<br />
selitem.addElement("mc").setText("0");<br />
selitem.addElement("wc").setText("0");<br />
selitem.addElement("dc").setText("0");<br />
selitem.addElement("rt").setText(rt);<br />
selitem.addElement("password").setText(password);<br />
mc="0";<br />
wc="0";<br />
dc="0";<br />
tc="0";<br />
}<br />
<br />
//处理计数器加一操作。<br />
Calendar
currcr=Calendar.getInstance();<br />
//总数器总是加1。<br />
tc
=String.valueOf(Integer.parseInt(tc)+1);<br />
selitem.element("tc").setText(tc);<br />
Date
lastdt = null;<br />
try {<br />
lastdt = DATEFORMATER.parse(rt);<br />
} <br />
catch
(ParseException e) {<br />
lastdt = new java.util.Date();<br />
}<br />
Calendar lastcr =
Calendar.getInstance();<br />
lastcr.setTime(lastdt);<br />
currcr.setTime(currdt);<br />
//System.out.println("上次登记时间："+DATEFORMATER.format(lastdt));<br />
//System.out.println("本次登记时间："+DATEFORMATER.format(currdt));<br />
if(lastcr.get(Calendar.YEAR)==currcr.get(Calendar.YEAR)){<br />
//月相同，月计数加1<br />
if(lastcr.get(Calendar.MONTH)==currcr.get(Calendar.MONTH)){<br />
mc
=
String.valueOf(Integer.parseInt(mc)+1);<br />
}<br />
else{<br />
mc="1";<br />
}<br />
//日相同，日计数加1<br />
if(lastcr.get(Calendar.DAY_OF_YEAR)==currcr.get(Calendar.DAY_OF_YEAR))<br />
dc
= String.valueOf(Integer.parseInt(dc)+1);<br />
else<br />
dc =
"1";<br />
<br />
if(lastcr.get(Calendar.WEEK_OF_YEAR)==currcr.get(Calendar.WEEK_OF_YEAR))<br />
wc
= String.valueOf(Integer.parseInt(wc)+1);<br />
else<br />
wc = "1";<br />
} <br />
else{//年不一样，则月计数器、周计数器日计数器肯定也不一样。<br />
mc="1"; dc="1"; wc="1"; <br />
}<br />
selitem.element("mc").setText(mc);<br />
selitem.element("wc").setText(wc);<br />
selitem.element("dc").setText(dc);<br />
//登记记录时间<br />
selitem.element("rt").setText(DATEFORMATER.format(currdt)); </p>
<p>try {<br />
XMLWriter xw = new XMLWriter(new
FileWriter(FileN));<br />
xw.write(doc);<br />
xw.close();<br />
} <br />
catch (IOException
e) {<br />
e.printStackTrace();<br />
} <br />
return
tc+";"+mc+";"+wc+";"+dc;<br />
}<br />
/**<br />
*功能：服务暴露的接口，也就是指定名称、密码，返回指定的计数，并将计数器加1。&lt;br/&gt;<br />
*编码：王力猛
时间：2007-4-17 上午10:05:22&lt;br/&gt;<br />
*/<br />
public String Counter(String name,
String password){<br />
if(password==null || name==null)return ERRORINFO;<br />
return
countertick(name, password);<br />
}<br />
}</p>
<p><strong>四、客户端编写</strong><br />
客户端是个页面，为了条理清晰，我先写个调用Web
Service的类，其内容如下：<br />
package com.wallimn.WebService;//调试请注意包名</p>
<p>import org.apache.axis.client.Call;<br />
import
org.apache.axis.client.Service;</p>
<p>public class CounterServiceClient {<br />
private String counterarr[];</p>
<p>public boolean getCounter(String CounterName, String password) {<br />
boolean
res = false;<br />
try {<br />
String endpoint =
"http://localhost:8080/axis/WsCounterByWallimn.jws";//此处注意，请与你的开发环境匹配<br />
Service
service = new Service();<br />
Call call = (Call)
service.createCall();<br />
call.setTargetEndpointAddress(new
java.net.URL(endpoint));<br />
call.setOperationName("Counter");<br />
//
填写你要调用的方法名称<br />
String counter = (String) call.invoke(new Object[] { CounterName,
password });<br />
counterarr = counter.split(";");<br />
res = (counterarr != null
&amp;&amp; counterarr.length == 4);<br />
} <br />
catch (Exception e)
{<br />
}<br />
return res;<br />
}</p>
<p>public String getDc() {<br />
return counterarr[3];<br />
}</p>
<p>public String getMc() {<br />
return counterarr[1];<br />
}</p>
<p>public String getTc() {<br />
return counterarr[0];<br />
}</p>
<p>public String getWc() {<br />
return counterarr[2];<br />
}<br />
}</p>
<p>　　到页面(test.jsp)上就简单了，我也把它贴在下面：<br />
&lt;%@ page language="java"
import="com.wallimn.WebService.CounterServiceClient"
pageEncoding="GB18030"%&gt;<br />
&lt;%<br />
CounterServiceClient client = new
CounterServiceClient();<br />
client.getCounter("hello","123");<br />
%&gt;</p>
<p>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01
Transitional//EN"&gt;<br />
&lt;html&gt;<br />
&lt;head&gt;<br />
&lt;title&gt;计数器测试页面&lt;/title&gt;<br />
<br />
&lt;meta
http-equiv="pragma" content="no-cache"&gt;<br />
&lt;meta
http-equiv="cache-control" content="no-cache"&gt;<br />
&lt;meta
http-equiv="expires" content="0"&gt; <br />
&lt;meta http-equiv="keywords"
content="wallimn,计数器,WebService"&gt;<br />
&lt;meta http-equiv="description"
content="计数器使用示例"&gt;<br />
&lt;/head&gt;<br />
<br />
&lt;body&gt;<br />
&lt;h2
align="center"&gt;计数器详情&lt;/h2&gt;<br />
&lt;hr/&gt; <br />
总访问量:&lt;%=client.getTc()%&gt;
&lt;br/&gt;<br />
今天访问量:&lt;%=client.getDc()%&gt;
&lt;br/&gt;<br />
本周访问量:&lt;%=client.getWc()%&gt;
&lt;br/&gt;<br />
本月访问量:&lt;%=client.getMc()%&gt; &lt;br/&gt; <br />
&lt;hr/&gt; <br />
&lt;p&gt;欢迎交流&lt;br/&gt;博客：http://blog.csdn.net/wallimn&lt;br/&gt;电邮：wallimn@sohu.com&lt;/p&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</p>
<p>五、结束语</p>
至此一个完整计数器的Web
Service开发、使用的程序的全部完成了。将上面的类、及页面部署到任意的一个上下文中，通过浏览器打开test.jsp，就可以看了结果了。<br />
欢迎访问我的博客(http://blob.csdn.net/wallimn)留言或发邮件(wallimn@sohu.com)交流。
<img src ="http://www.blogjava.net/supercrsky/aggbug/196012.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/supercrsky/" target="_blank">々上善若水々</a> 2008-04-25 17:02 <a href="http://www.blogjava.net/supercrsky/articles/196012.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XFire完整入门教程</title><link>http://www.blogjava.net/supercrsky/articles/195670.html</link><dc:creator>々上善若水々</dc:creator><author>々上善若水々</author><pubDate>Thu, 24 Apr 2008 10:00:00 GMT</pubDate><guid>http://www.blogjava.net/supercrsky/articles/195670.html</guid><wfw:comment>http://www.blogjava.net/supercrsky/comments/195670.html</wfw:comment><comments>http://www.blogjava.net/supercrsky/articles/195670.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/supercrsky/comments/commentRss/195670.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/supercrsky/services/trackbacks/195670.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 网上关于XFire入门的教程不少，要么是讲得很简单，就像Hello World一样的程序，要么就是通过IDE集成的工具来开发的，这对于不同的人群有诸多不便，关于XFire的一些详细的信息就不再多讲，可以参考官方网站和相关的文档，这里讲一个完整的入门实例。实例中包括三个情况，我想基本上可以概括所有的需求，或者自己稍加扩展即可。先来看看我们的Interface。&nbsp;1package...&nbsp;&nbsp;<a href='http://www.blogjava.net/supercrsky/articles/195670.html'>阅读全文</a><img src ="http://www.blogjava.net/supercrsky/aggbug/195670.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/supercrsky/" target="_blank">々上善若水々</a> 2008-04-24 18:00 <a href="http://www.blogjava.net/supercrsky/articles/195670.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XFire 最新生火指南（上)</title><link>http://www.blogjava.net/supercrsky/articles/195669.html</link><dc:creator>々上善若水々</dc:creator><author>々上善若水々</author><pubDate>Thu, 24 Apr 2008 09:59:00 GMT</pubDate><guid>http://www.blogjava.net/supercrsky/articles/195669.html</guid><wfw:comment>http://www.blogjava.net/supercrsky/comments/195669.html</wfw:comment><comments>http://www.blogjava.net/supercrsky/articles/195669.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/supercrsky/comments/commentRss/195669.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/supercrsky/services/trackbacks/195669.html</trackback:ping><description><![CDATA[<p><a name="XFire-XFire最新生火指南（上）">本文来自</a><a href="http://wiki.springside.org.cn/">SpringSide WIki</a><a name="XFire-XFire最新生火指南（上）">，请留意</a><a href="http://wiki.springside.org.cn/display/springside/XFireGuide2">Wiki上的最新版本</a><a name="XFire-XFire最新生火指南（上）">。</a></p>
<p>基于发布在JavaEye的敬畏心情，本文又修改了一遍，与前两天发在blogjava和csdn的版本稍有不同。</p>
<h2>1. 概述</h2>
<p>&nbsp;&nbsp; <a title="Visit page outside Confluence" rel="nofollow" href="http://xfire.codehaus.org/">XFire<sup><img alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" align="absmiddle" border="0" height="7" width="7" /></sup></a> 是全球众多牛人在与axis系列对比后一致投票的选择。我比较欣赏的特性有：</p>
<ol>
    <li><a title="Visit page outside Confluence" rel="nofollow" href="http://xfire.codehaus.org/Spring">与Spring整合<sup><img alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" align="absmiddle" border="0" height="7" width="7" /></sup></a>，无须生成一堆文件，无须打包独立war，直接将应用中的Pojo导出为Web服务。 </li>
    <li><a title="Visit page outside Confluence" rel="nofollow" href="http://xfire.codehaus.org/Aegis+Binding">Aegis<sup><img alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" align="absmiddle" border="0" height="7" width="7" /></sup></a>--超简约的默认Java XML 绑定机制，且可以Plugin其他绑定机制。 </li>
    <li><a title="Visit page outside Confluence" rel="nofollow" href="http://xfire.codehaus.org/JSR+181+Annotations">JSR181--annotatiton驱动<sup><img alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" align="absmiddle" border="0" height="7" width="7" /></sup></a>的POJO WebService配置。 </li>
    <li><a title="Visit page outside Confluence" rel="nofollow" href="http://xfire.codehaus.org/Performance">基于Stax的高性能框架<sup><img alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" align="absmiddle" border="0" height="7" width="7" /></sup></a>。 </li>
    <li>脱离Web服务器的单元测试能力。 </li>
</ol>
<p>&nbsp;&nbsp; 网上的文档与例子总是不新，请大家抛开所有的文档，所有的Axis习惯，单看这份代表XFire1.2.2最简约做法的指南。</p>
<h2>2. 生火指南</h2>
<h3>2.1 修改web.xml，在Web应用中增加XFire的入口</h3>
<p>&nbsp;&nbsp; 注意XFire有了自己的Servlet，不再依赖Spring MVC的DispatchServlet，也就远离了大家不熟悉的Spring MVC URL Mapping，与Spring达致完美的整合。</p>
<p>&nbsp;&nbsp; 这里指定了路径为/service/* ，即WebService的URL会被默认生成为<a title="Visit page outside Confluence" rel="nofollow" linktext="http://www.springside.org.cn/bookstore/service/BookService" linktype="raw" mce_href="http://www.springside.org.cn/bookstore/service/BookService" href="http://www.springside.org.cn/bookstore/service/BookService">http://www.xxx.com/yyy/service/BookService</a>service/ServiceName<sup><img alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" align="absmiddle" border="0" height="7" width="7" /></sup>，其中ServiceName默认为下文中的接口名。</p>
<div>
<div>
<pre>
<div>xml 代码</div>
<div>
<ol>
    <li>&lt;servlet&gt;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet-name&gt;xfireservlet-name&gt;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet-class&gt;org.codehaus.xfire.spring.XFireSpringServletservlet-class&gt;&nbsp;&nbsp;</li>
    <li>&nbsp;servlet&gt;&nbsp;&nbsp;</li>
    <li>&nbsp;&lt;servlet-mapping&gt;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet-name&gt;xfireservlet-name&gt;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;url-pattern&gt;/service/*url-pattern&gt;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;servlet-mapping&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li>
</ol>
</div>
</pre>
<pre>&nbsp;&nbsp; 如果应用使用了Hibernate，使用了OpenSessionInView Filter，注意配置OSIV Filter Filter覆盖xfire servlet的路径，即本例中的/service/*.</pre>
</div>
</div>
<h3>2.2 编写窄接口，抽取POJO中要导出的服务</h3>
<p>&nbsp;&nbsp; 从已有的BookManager.java中，抽取出一个窄接口，仅暴露需要导出为Web Service的方法。而BookManger.java是POJO，不需要任何WebService相关代码。</p>
<p>&nbsp; 窄接口一方面满足了安全要求，不用整个BookManager所有方法导出为Web Service；另一方面，XFire暂时也只支持基于接口的Proxy。</p>
<div>
<div>
<pre>public interface BookService {<br />
List findBooksByCategory(String cateoryId);<br />
}</pre>
</div>
</div>
<h3>&nbsp;2.3 配置Java-XML Binding</h3>
<p>&nbsp;&nbsp; XFire默认的Aegis Binding语法非常简单，在SpringSide的例子里几乎一行配置都不用写，是我见过最简单的binding定义，大大优于其他以设计复杂为终极目标的方案。</p>
<p>&nbsp;&nbsp; 对象的属性、函数的参数和返回值如果为int、String、Date等普通类型以及由普通类型组成的复杂对象都无需定义。我见到只有两种情况需要定义：</p>
<ul>
    <li>无法使用泛型定义Collection中元素的类型时--如List findBooks()。如果能写成List findBooks()就也不需要了。 </li>
    <li>需要为属性定义不同的名字，或者定义复杂对象里的某些属性不要输出。 </li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果实在需要aegis配置， XFire以约定俗成代替配置(CoC)，所有Service和Entity Bean的binding文件要求命名为xxx.aegis.xml，而且要和原来的类sit together在同一目录里。</p>
<div>
<div>
<ol>
    <li>&lt;mapping&gt;&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="products"&nbsp;ignore="true"/&gt;&nbsp;&nbsp; </li>
    <li>mapping&gt;&nbsp;&nbsp; </li>
</ol>
</div>
</div>
<p>&nbsp;&nbsp; 其他语法详见<a title="Visit page outside Confluence" rel="nofollow" href="http://xfire.codehaus.org/Aegis+Binding">Aegis<sup><img alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" align="absmiddle" border="0" height="7" width="7" /></sup></a>&nbsp;参考。</p>
<h3>2.4 配置Spring导出</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;为了节约配置代码，先配置一个基类。注意导出Web服务的Bean不能lazy-init：</p>
<div>
<div>
<pre>&nbsp;&nbsp;
<li>&lt;import&nbsp;resource="classpath:org/codehaus/xfire/spring/xfire.xml"/&gt;&nbsp;&nbsp;</li>
<li>&nbsp;&nbsp;</li>
<li>&lt;bean&nbsp;id="baseWebService"&nbsp;class="org.codehaus.xfire.spring.remoting.XFireExporter"&nbsp;lazy-init="false"&nbsp;abstract="true"&gt;&nbsp;&nbsp;</li>
<li>&nbsp;&nbsp;&lt;property&nbsp;name="serviceFactory"&nbsp;ref="xfire.serviceFactory"/&gt;&nbsp;&nbsp;</li>
<li>&nbsp;&nbsp;&lt;property&nbsp;name="xfire"&nbsp;ref="xfire"/&gt;&nbsp;&nbsp;</li>
<li>&nbsp;bean&gt;&nbsp;&nbsp;</li>
</pre>
</div>
&nbsp;
</div>
<p>&nbsp;每个Web服务的定义：parent为前面定义的基类，serviceClass 为Web Service的接口，serviceBean为Web Service的接口实现类。</p>
<div>xml 代码</div>
<div>
<ol>
    <li>&lt;bean&nbsp;id="bookService"&nbsp;parent="baseWebService"&gt;&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&lt;property&nbsp;name="serviceBean"&nbsp;ref="bookManager"/&gt;&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&lt;property&nbsp;name="serviceClass"&nbsp;value="org.springside.bookstore.components.xfire.server.simple.BookService"/&gt;&nbsp;&nbsp; </li>
    <li>&nbsp;bean&gt;&nbsp;&nbsp; </li>
</ol>
</div>
<p><br />
&nbsp;</p>
<hr />
<p>Web服务导出完毕，用户可在<a title="Visit page outside Confluence" rel="nofollow" href="http://localhost/service/BookService?WSDL">http://localhost/service/BookService?WSDL<sup><img alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" align="absmiddle" border="0" height="7" width="7" /></sup></a>查看自动生成的WSDL。&nbsp;</p>
<p>上半章完，关于JSR181,Client API与测试部分请看<a title="XFireGuide2" href="http://wiki.springside.org.cn/display/springside/XFireGuide2">XFire 生火指南(下)</a></p>
<img src ="http://www.blogjava.net/supercrsky/aggbug/195669.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/supercrsky/" target="_blank">々上善若水々</a> 2008-04-24 17:59 <a href="http://www.blogjava.net/supercrsky/articles/195669.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XFire生火指南下半部</title><link>http://www.blogjava.net/supercrsky/articles/195667.html</link><dc:creator>々上善若水々</dc:creator><author>々上善若水々</author><pubDate>Thu, 24 Apr 2008 09:56:00 GMT</pubDate><guid>http://www.blogjava.net/supercrsky/articles/195667.html</guid><wfw:comment>http://www.blogjava.net/supercrsky/comments/195667.html</wfw:comment><comments>http://www.blogjava.net/supercrsky/articles/195667.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/supercrsky/comments/commentRss/195667.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/supercrsky/services/trackbacks/195667.html</trackback:ping><description><![CDATA[<div> XFire生火指南下半部，主要包括JSR181,Client API与测试部分。</div>
<p>作者：江南白衣</p>
<p>本文来自SpringSide WIki，请留意Wiki上的最新版本。(wiki于11.27更新)。</p>
<p>请先阅读：XFire生火指南(上)</p>
<h2>1. JSR181</h2>
<p>&nbsp;&nbsp;&nbsp;&nbsp; JSR181式通过annotated POJO ，零配置文件的导出Web服务，是BEA倡导的，JavaEE5里的正规方式， XFire作了良好的支持。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 但是，XFire关于JSR181方式的文档还不够清晰，请完整阅读本节以避免其中的数个陷阱。</p>
<h3>1.1 参考文章</h3>
<ul>
    <li>Spring, Hibernate and XFire<sup><img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547211.gif" align="absmiddle" border="0" height="7" width="7" /></sup> </li>
    <li>Webservices with Spring, XFire and jsr181<sup><img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547211.gif" align="absmiddle" border="0" height="7" width="7" /></sup> </li>
    <li>Basic Spring Web services with XFire and JSR 181<sup><img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547211.gif" align="absmiddle" border="0" height="7" width="7" /></sup> </li>
    <li>XFire JSR181参考文档<sup><img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547211.gif" align="absmiddle" border="0" height="7" width="7" /></sup> </li>
</ul>
<h3>1.2 ApplicationContext.xml</h3>
<p>&nbsp;&nbsp;&nbsp; 因为配置都写在annotation，applicationContext.xml文件的内容比较固定。需要注意JSR181WebAnnotations与HandlerMapping不能lazy init.</p>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" /><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">beans&nbsp;</span><span style="color: #ff0000;">default-autowire</span><span style="color: #0000ff;">="byName"</span><span style="color: #ff0000;">&nbsp;&nbsp;default-lazy-init</span><span style="color: #0000ff;">="true"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />&nbsp;&nbsp;</span><span style="color: #008000;">&lt;!--</span><span style="color: #008000;">引入XFire的预配置文件</span><span style="color: #008000;">--&gt;</span><span style="color: #000000;"><br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">import&nbsp;</span><span style="color: #ff0000;">resource</span><span style="color: #0000ff;">="classpath:org/codehaus/xfire/spring/xfire.xml"</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;">&nbsp;<br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" /><br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />&nbsp;</span><span style="color: #008000;">&lt;!--</span><span style="color: #008000;">&nbsp;获得applicationContext中所有bean的JSR181&nbsp;annotation&nbsp;</span><span style="color: #008000;">--&gt;</span><span style="color: #000000;"><br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">bean&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="webAnnotations"</span><span style="color: #ff0000;">&nbsp;class</span><span style="color: #0000ff;">="org.codehaus.xfire.annotations.jsr181.Jsr181WebAnnotations"</span><span style="color: #ff0000;">&nbsp;&nbsp;lazy-init</span><span style="color: #0000ff;">="false"</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" /><br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" /><br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />&nbsp;</span><span style="color: #008000;">&lt;!--</span><span style="color: #008000;">&nbsp;定义handler&nbsp;mapping,将所有JSR181定义的bean导出为web&nbsp;service&nbsp;</span><span style="color: #008000;">--&gt;</span><span style="color: #000000;"><br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">bean&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="jsr181HandlerMapping"</span><span style="color: #ff0000;">&nbsp;class</span><span style="color: #0000ff;">="org.codehaus.xfire.spring.remoting.Jsr181HandlerMapping"</span><span style="color: #ff0000;">&nbsp;&nbsp;lazy-init</span><span style="color: #0000ff;">="false"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">property&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="xfire"</span><span style="color: #ff0000;">&nbsp;ref</span><span style="color: #0000ff;">="xfire"</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">property&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="webAnnotations"</span><span style="color: #ff0000;">&nbsp;ref</span><span style="color: #0000ff;">="webAnnotations"</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">bean</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" /></span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">beans</span><span style="color: #0000ff;">&gt;</span></div>
</div>
<h3>1.3 Interface+Impl模式</h3>
<p>&nbsp;&nbsp; 不同于XFire传统模式，窄接口不是必须的，只是考虑到client如果也使用XFire时，有个接口好生成Client而已。</p>
<p>&nbsp;&nbsp;&nbsp;如果采用Interface，Interface将担任主要的配置工作。</p>
<p>&nbsp;&nbsp; 首先定义@WebService，可定义自己的NameSpace，如果不定义将采用NameSpace的默认生成算法。</p>
<p>&nbsp;&nbsp; 接口中的函数将默认全部导出，不需要再用@WebMethod注释，可以如下例般进行更进一步配置：</p>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><span style="color: #000000;">@WebService(targetNamespace&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">"</span><span style="color: #000000;">http://www.springside.org.cn</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />
</span><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">interface</span><span style="color: #000000;">&nbsp;BookService&nbsp;{<br />
&nbsp;&nbsp;@WebResult(name&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">"</span><span style="color: #000000;">SearchResult</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;List</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Book</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;findBooksByCategory(@WebParam(name&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">"</span><span style="color: #000000;">category</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;header&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #0000ff;">true</span><span style="color: #000000;">)String&nbsp;cateoryId);<br />
}</span></div>
</div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Manager不是纯粹的POJO，需要带上@WebService注释，指明InterFace。</p>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><span style="color: #000000;">@WebService(serviceName&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">"</span><span style="color: #000000;">BookService</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;<br />
endpointInterface&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">"</span><span style="color: #000000;">org.springside.bookstore.components.xfire.server.jsr181.BookService</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />
</span><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;BookManager&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;BookService&nbsp;{...}</span></div>
</div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 陷阱一：XFire JSR181参考文档<sup><img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547211.gif" align="absmiddle" border="0" height="7" width="7" /></sup>&nbsp;中在Interface中以@WebService(name="<font color="#009100">BookService</font>")来定义ServiceName，这个做法看起来也比较合理，但实际上需要在Manager中以@WebService(serviceName ="BookService") 来定义，比较古怪。</p>
<h3>1.4 纯POJO模式</h3>
<p>&nbsp;&nbsp;&nbsp; 参考文档中的例子，需要配置@WebMethod 指定需要导出的服务</p>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><span style="color: #000000;">@WebService(name&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">"</span><span style="color: #000000;">EchoService</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;targetNamespace&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">"</span><span style="color: #000000;">http://www.openuri.org/2004/04/HelloWorld</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Jsr181EchoService<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;@WebMethod(operationName&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">"</span><span style="color: #000000;">echoString</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;action&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">"</span><span style="color: #000000;">urn:EchoString</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;@WebResult(name&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">"</span><span style="color: #000000;">echoResult</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String&nbsp;echo(@WebParam(name&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">"</span><span style="color: #000000;">echoParam</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;header&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #0000ff;">true</span><span style="color: #000000;">)&nbsp;String&nbsp;input)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;input;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
</div>
<h3>1.5 Client注意事项</h3>
<p>&nbsp;&nbsp;&nbsp; 陷阱二：和传统模式的client有一点最大的区别，第3个参数需要是实际的Manager类，而不是接口类：</p>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" /><span style="color: #000000;">Service&nbsp;serviceModel&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;AnnotationServiceFactory().create(BookManager.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">);</span></div>
</div>
<h2>2. Client</h2>
<p>XFire的Client并不算强项，一共有三种模式：</p>
<h3>2.1 Client开发者拥有Web服务端的class</h3>
<p>&nbsp; Client与Server是同一个开发团队也好，Server端团队以jar形式提供开发包也好，反正如果能拿到服务端的接口Class和Entity类及aegis 配置文件的话。</p>
<p>&nbsp; 传统模式：</p>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" /><span style="color: #000000;">Service&nbsp;serviceModel&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ObjectServiceFactory().create(BookService.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">);<br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />BookService&nbsp;service&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(BookService)&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;XFireProxyFactory().create(serviceModel,&nbsp;serviceURL);<br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />service.findBooksByCategory(cateoryId);</span></div>
</div>
<p>&nbsp;&nbsp;JSR181模式，注意这里Server端开发组需要向Client提供BookService的实现类BookManager，而不止于接口类，有点危险：&nbsp;</p>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" /><span style="color: #000000;">Service&nbsp;serviceModel&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;AnnotationServiceFactory().create(BookManager.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">);<br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />BookService&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(BookService)&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;XFireProxyFactory().create(serviceModel,&nbsp;serviceURL);<br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />service.findBooksByCategory(cateoryId);</span></div>
</div>
<p>&nbsp; SpringSide&nbsp;用泛型封装了一个XFireClientFactory，调用代码如下：</p>
<div>
<div>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" /><span style="color: #000000;">BookService&nbsp;service&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;XFireClientFactory.getClient(serviceURL,&nbsp;BookService.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">);<br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />BookService&nbsp;service&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;XFireClientFactory.getJSR181Client(serviceURL,&nbsp;BookService.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">,&nbsp;BookManager.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">);</span></div>
</div>
</div>
</div>
<h3>2.2 动态模式</h3>
<p>&nbsp;&nbsp;&nbsp; 动态模式不需要服务端的class，不过性能和复杂对象映射等估计做得不会太好。</p>
<div>
<div>
<pre>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><span style="color: #000000;">Client&nbsp;client&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Client(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;URL(</span><span style="color: #000000;">"</span><span style="color: #000000;">http://www.webservicex.net/CurrencyConvertor.asmx?WSDL</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br />
<br />
Object[]&nbsp;results&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;client.invoke(</span><span style="color: #000000;">"</span><span style="color: #000000;">ConversionRate</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Object[]&nbsp;{</span><span style="color: #000000;">"</span><span style="color: #000000;">BRL</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">UGX</span><span style="color: #000000;">"</span><span style="color: #000000;">});</span></div>
</div>
</pre>
</div>
</div>
<h3>2.3 根据WSDL生成Client Stub</h3>
<p>&nbsp;&nbsp;&nbsp; 这才是Web Service Client的王道，可以访问任意编写下的Web Service，将在下一个版本中演示。</p>
<h2>3. 测试</h2>
<p>XFiire很重要的一个特性是提供了无须启动Web容器也能进行单元测试的能力。</p>
<p>原理就是利用XFire的JVM模式，以xfire.local://BookService channel而不是http://localhost/service/BookService<sup><img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547211.gif" align="absmiddle" border="0" height="7" width="7" /></sup>来访问服务。</p>
<p>测试的方式分两种：</p>
<p>一种是纯服务器角度，不编写客户端代码，以SOAP XML形式发送请求，返回的也是SOAP XML字串，直接对XML进行测试。</p>
<p>一种是编写2.1 中Client代码来进行测试。</p>
<p>前一种的测试的隔离度较高，而后一种比较简便。</p>
<h3>3.1&nbsp;测试基类&nbsp;</h3>
<p>无论那种方式，都使用Xfire的<strong>AbstractXFireSpringTest</strong>基类，实现createContext()回调函数。</p>
<div>
<div>
<pre>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;ApplicationContext&nbsp;createContext()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;ClassPathXmlApplicationContext(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;String[]{</span><span style="color: #000000;">"</span><span style="color: #000000;">classpath*:applicationContext*.xml</span><span style="color: #000000;">"</span><span style="color: #000000;">});<br />
&nbsp;}</span></div>
</div>
</pre>
</div>
</div>
<p>另外测试基类还要完成一个很重要的工作就是要解决Hibernate的LazyLoad问题，做到OpenSession In Test。因此，SpringSide专门封装了一个XFireTestCase的基类。</p>
<h3>3.2 用Client代码直接测试</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 下文直接用client代码调用findBooksByCategory方法，得到返回值后进行各种Assert判断。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 注意和普通client code的两处区别：servericeURL换成local，factory须加入getXFire()作参数。</p>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><span style="color: #000000;">Service&nbsp;serviceModel&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ObjectServiceFactory().create(BookService.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;XFireProxyFactory&nbsp;factory&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;XFireProxyFactory(getXFire());<br />
&nbsp;&nbsp;BookService&nbsp;service&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(BookService)&nbsp;factory.create(serviceModel,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">xfire.local://BookService</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;List&nbsp;list&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;service.findBooksByCategory(</span><span style="color: #000000;">"</span><span style="color: #000000;">0</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;assertNotNull(list);<br />
&nbsp;&nbsp;...</span></div>
</div>
<h3>3.3 纯服务端测试</h3>
<p>&nbsp;&nbsp; 编写一段SOAP XML，以任意命名保存，下文以"Java"作参数，调用findBooksByName方法。</p>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><span style="color: #000000;">&lt;</span><span style="color: #000000;">env:Envelope&nbsp;xmlns:env</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">http://schemas.xmlsoap.org/soap/envelope/</span><span style="color: #000000;">"</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">env:Header</span><span style="color: #000000;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">env:Body</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">findBooksByName&nbsp;xmlns</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">http://www.springside.org.cn</span><span style="color: #000000;">"</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">in1</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">Java</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">in1</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">findBooksByName</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">env:Body</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">env:Envelope</span><span style="color: #000000;">&gt;</span></div>
</div>
<p>&nbsp;&nbsp; 测试代码调用前面的XML，返回XML Document对象，再用基类提供的一些Assert方法检查结果：</p>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" /><span style="color: #000000;">&nbsp;&nbsp;Document&nbsp;doc&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;invokeService(</span><span style="color: #000000;">"</span><span style="color: #000000;">BookService</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">"</span><span style="color: #000000;">/org/springside/xfire/BookService.FindBooksByName.xml</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />&nbsp;&nbsp;assertNoFault(doc);<br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />&nbsp;&nbsp;addNamespace(</span><span style="color: #000000;">"</span><span style="color: #000000;">ss</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">http://domain.commons.bookstore.springside.org</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<img alt="" src="http://www.qqgb.com/Program/image/200701/20071183547177.gif" align="top" />&nbsp;&nbsp;assertValid(</span><span style="color: #000000;">"</span><span style="color: #000000;">//ss:Book/ss:category/ss:descn=&nbsp;"Java&nbsp;Book"</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;doc);</span></div>
</div>
<img src ="http://www.blogjava.net/supercrsky/aggbug/195667.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/supercrsky/" target="_blank">々上善若水々</a> 2008-04-24 17:56 <a href="http://www.blogjava.net/supercrsky/articles/195667.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于XFire开发WebServices</title><link>http://www.blogjava.net/supercrsky/articles/195122.html</link><dc:creator>々上善若水々</dc:creator><author>々上善若水々</author><pubDate>Wed, 23 Apr 2008 07:25:00 GMT</pubDate><guid>http://www.blogjava.net/supercrsky/articles/195122.html</guid><wfw:comment>http://www.blogjava.net/supercrsky/comments/195122.html</wfw:comment><comments>http://www.blogjava.net/supercrsky/articles/195122.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/supercrsky/comments/commentRss/195122.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/supercrsky/services/trackbacks/195122.html</trackback:ping><description><![CDATA[<a>　问一下.Net的开发者，开发Web
Services有多困难?他们会被你的问题逗乐，他们会告诉你所有步骤花费的时间不会超过一分钟。再问一下Java开发者，运气好的话你会碰到上面的回
答，一般情况下，你会得到一个完全不同的答案。从Web
Services引入到Java中至今已经5年了，然而它仍然被认为是一门较新的技术，一个主要的原因就是使用Java实现Web
Services太困难了。现在，随着新一代Web
Services引擎XFire的发布，这种情况将会发生明显的变化。使用XFire，你可以把Java类方法发布为Web
Services而不需要编写额外的代码。在这篇文章中，你将会看到XFire使Web Services开发变得多么容易和简单。</a>
<p><a>　　Web
Services使我们能够在网络上建立分布式系统，应用程序组件可以通过任何平台、任何语言和任何方式访问。无论应用程序如何开发，使用了什么语言，以
及运行在什么操作系统平台上，只要它作为Web
Service，并且为协同解决问题而设计，那么你的应用程序，以任何语言开发或在任何平台上，都可以利用它的服务。这是Web
Service的主要概念。</a></p>
<p><a>　　为了实现Web Services的平台无关性和实现访问独立性，软件行业需要遵循一些作为标准的技术。其中一些包括:</a></p>
<p><a>　　---XML:在Web Services环境中各层之间进行传递的默认数据格式。</a></p>
<p><a>　　---SOAP:封装和交换信息的默认协议。第一次被提出时，它是只取Simple Object
Access
Protocol(简单对象访问协议)的首字母。但是现在SOAP更多被认为是一个特定的名词，以它自己而命名，同样很多人认为这是用词不当:SOAP实
际上不是用来访问对象的。另外，它也不再简单。</a></p>
<p><a>　　---WSDL(Web Services Description Language，Web Services描述语言):描述Web Services的语言。尽管基于XML并且可以被人理解，WSDL主要是由机器处理，由客户端程序读取和理解。</a></p>
<p><a>　　下面的高级层次图表，基于WWW协会发布的&#8220;Web Services Architecture&#8221;(Web Services架构)文档，显示了这些技术在实际的工作环境中是如何发挥作用:</a></p>
<p><a href="http://searchwebservices.techtarget.com.cn/TLimages/picview/?/imagelist/06/39/6fu472rkvoe2.jpg" target="_blank"><img style="border-color: #000000;" alt="点击放大此图片" src="http://www.360doc.com/DownloadImg/73/228251_1.jpg" border="0" /></a></p>
<p>　　这个流程图显示了Web Services中的核心技术是如何工作的。</p>
<p>　　这里，Provider是提供服务的应用程序组件，Requ