Spring 最佳实践 - Spring提供的远程访问(三)

来源:互联网 发布:表格不同行数据相加 编辑:程序博客网 时间:2024/06/05 23:44

8.3WEB服务

 

WEB服务(Web Service)最近年来炙手可热的技术,本质上说,WEB服务就是一个中能够实现跨平台远程的带哦用的技术标准,即应用程序通过向外界暴露一个可以通过WEB来远程调用的API接口,客户端就可以调用这个服务接口来实现相应的功能。

 

可以把WEB服务堪称是基于因特网的远程调用,有了WEB服务,WEB网站和WEB网站之间就不在是简单的用超链接连接起来,而是可以互相调用的WEB应用程序。

 

 

例如,在没有WEB服务钱,如果需要在women你自己的网站上集成Google搜索功能,唯一的办法是通过HTML将用户导向到Google的站点,而有了WEB服务后,网站可以通过调用Google的WEB服务获得搜索结果,然后将结果以任意的方式展示给用户,对于用户而言,完全不知道该搜索结果实际上市重Google得到的。

 

WEB服务是一种面向服务的架构技术,由于XML是一种平台无关的描述语言,因此,在WEB服务中,XML被用来描述如何传递数据。这样,调用双方就可以是任意的异构平台,例如,在.Net应用程序中调用Java应用发布的WEB服务,或者在Java应用程序中调用.Net应用程序发布的WEB服务。

 

随着因特网的迅速发展,WEB服务也得到了越来越广泛的应用。目前,WEB服务大致可以应用在以下领域。

 

(1)面向企业的WEB服务,包括企业内容部各种ERP系统和企业间合作伙伴的系统对接。由于大型企业内部或企业之间常常是异构平台,因此,采用WEB服务来实现系统集成非常合适。

(2)面向消息的WEB服务,尤其是B2C站点,通过WEB服务,第三方桌面应用程序就可以为用户提供更方便的服务,例如,个人理财软件可以通过WEB服务获得最新的股票价格。

(3)面向终端设备的WEB服务。八块收集、PDA等各种移动终端,可以通过WEB服务轻松实现天气预报、酒店预订等服务。

 

使用WEB服务带来的最大的好处是能够实现跨平台的易购协作,由于WEB服务使用了一系列的标准协议,因此,不同平台、不同语言之间都可以互相调用。一个WEB服务是如何在发布者和调用者之间实现的如下图所示:

 

 

 

 

WEB服务的发布者首先必须提供一个WSDL文件,即Web Servcies Description Languange(Web 服务描述语言),这个XML文件定义了调用Web服务的所有信息,包括所有的方法名称,参数类型、返回类型和数据类型的映射等。WEB服务的调用者只要获得了WSDL文件,就可以根据WSDL文件通过相应的工具生成客户端支持类,因此,无论服务段以任何技术实现该WEB服务,客户端都可以用任何编程语言来调用它。

 

JavaEE平台从1.3 版本开始就完整地支持WEB服务,包括调用和发布WEB服务两部分。为了让Java应用程序获得访问和发布WEB服务的能力,Sun定义了一系列相关的API标准,包括SAAJ、JAXB、JAX-RPC和最新的JAX-WS。SAAJ(SOAP with Attachments API for Java)已经完整的实现了SOAP协议,可以直接使用SAAJ实现的WEB服务的底层传输。JAXB(JavaArchitecture for XML Binding)则实现了XML数据到Java类的绑定,通常我们不直接使用这两种API,而是调用高层的JAX-RPC(Java API for XML-Based RPC)和 JAX – WS(Java API for XML-Base Web Servcie)。JAX-WS 是JavaEE最新的WEB服务标准,不过仍向下兼容JAX-RPC.

 

和其他Java标准类似,为了在java中实现WEB服务,还必须获得一个具体的实现。Axis和Xfire都是实现了完整的WEB服务协议的库,可以用于访问和发布WEB服务。稍后我们会分别看到这连个库的使用方法。

 

下面我们首先介绍如何使用Axis访问Amaon站点提供的WEB服务,然后介绍如何通过XFire对外发布我们自己的WEB服务。

 

 

 

 

8.3.1 访问Amazon的WEB服务

目前略。

 

8.3.2 在Spring中调用WEB服务

目前略。

 

 

 

 

 

8.3.3 发布WEB服务

 

前面已经介绍了如何访问已有的WEB服务,women你很自然的向导如果需要发布自己的WEB服务,应该如何实现。

发布WEB服务本质上就是最终生成WEB服务的描述文件,即WSDL文件,然后告知客户该文件的URL。客户端如果要调用我们发布的WEB服务,只需要获取WSDL文件,然后从总获得调用WEB服务所需的全部信息。WSDL文件格斯非常复杂,根本不可能手动编写,更不可能手动维护,因为WSDL文件设计的目标之一就是能使用工具自动生成让机器识别的XML。所以要发布WEB服务,必须借助工具从现有的Java接口及支持自动生成WSDL文件。

 

如果读者使用Microsoft Visual Studio 2005来发布一个WEB服务,通过几个简单的向导页面,整个发布过程将不着过一分钟。遗憾的是,对于JavaEE开发者来说,虽然WEB服务的标准早已被引入到JavaEE体系中,然后,长期以来,在javaEE环境中发布WEB服务是极其困难的,如果使用Axis发布一个WEB服务,至少需要手动编写一个复杂的deploy.wsdd配置文件,然后需啊哟手动运行AdminClient来生成Axis需要的支持文件,整个过程比较复杂。

 

 

 

       幸运的是,随着新一代的Java WEB服务引擎XFire的发布,在JavaEE中发布WEB服务将变得轻而易举,和其他JavaEE的WEB服务引擎相别,XFire的配置非常简单,它使得JavaEE开发人员终于可以获得和.Net开发人员一样的开发效率,但是在功能上,XFire却丝毫不逊色于其他的WEB服务引擎,由于使用了StAX(theStreaming API for XML,基于流的XML解析)作为XML解析器,XFire的运行速度优优了质的提高,并且XFire支持最新的JSR181的WEB服务注解。如果使用Java5,只需要在源代码中编写相应的JSR181注解,XFire就可以根据Java5注解自动提取所需要的全部信息。由于JSR181也是JavaEE WEB服务框架的一部分,使用它最大的好处在于不仅极大的简化了配置,而且避免了配置文件和某个特定的WEB服务引擎锁定(例如,deploy.wsdd是Axis 的配置文件,在其他WEB服务引擎中不能使用。)

 

在下面的例子中,我们将看到如何使用XFire发布WEB服务,并且在Spring环境中集成它。

 

 

1.      使用XFire发布WEB服务

 

我们首先在单独的XFire中发布一个WEB服务,要获得最新的XFire,请从http://xfire.codehaus.org/ 下载,然后解压到本地即可。在Eclipse 中建立工程ExportWS工程。

 

 

 

 

其中,web/WEB-INF/lib目录下存放了XFire需要的库文件,请复制XFire根目录下的xfire-all-1.2.6.jar及lib目录下的所有jar文件。需要注意的是,单独使用Xfire还需要Spring1.2.x的jar文件,因为Xfire用到了Spring框架提供的一些功能,不过不用担心在于Spring2.X框架集成,就不需要Spring1.2.x了,经过测试,XFire与Spring2.0配合的相当好。

 

有些jar文件时可选的,可以参考XFire的文档,删除不必要的Jar文件,这样可以减小WEB应用程序的发布文件。

 

以在线书店为例,假定我们的WEB引用程序也准备对外提供了一个书籍查询的功能,可以根据关键字返回对应的书籍信息,因此,我们首先编写一个BookService接口,作为WEB服务的接口。

 

public interface BookService {

    Book[] search(String keyword); 

}

 

 

然后,编写一个相应的实现类,这里,我们的服务几口还只能返回以”j2ee”作为关键字书籍的信息,对于其他的关键字,一律返回一个空数组。

 

public class BookServiceImpl implements BookService {

    @Override

    public Book[] search(String keyword) {

        if("j2ee".equalsIgnoreCase(keyword)) {

            return new Book[] {

                new Book("Core J2EE Patterns","Dan Malks"),

                new Book("The J2EE Tutorial","Bode Carson"),

                new Book("J2EE Design Patterns","William Crawford"),

                new Book("J2EE Platform Web Services","Ray Lai")

            };

        }

        return new Book[0];

    }

}

 

 

下一步,编写XFire必须的一个WEB服务描述文件services.xml,该文件必须放到ClassPaht中的META-INF/xfire/目录下,在这个工程中,我们将其放到src/META-INF/xfire/目录下。这个文件将为XFire提供生成WEB服务的描述信息,其内容非常简单,只需要指定WEB服务的接口和实现类即可。

 

<beansxmlns="http://xfire.codehaus.org/config/1.0"> 

    <service>

        <name>BookService</name>       <namespace>http://www.livebookstore.net/BookService</namespace>

        <serviceClass>com.zsw.service.BookService</serviceClass>

      <implementationClass>com.zsw.service.BookServiceImpl</implementationClass>

    </service>

</beans>

 

 

最后,在web.xml文件中加入XFireConfigurableServlet的生命,并映射到指定的路径。

<servlet>

    <servlet-name>XFireServlet</servlet-name>

    <servlet-class>

        org.codehaus.xfire.transport.http.XFireConfigurableServlet

    </servlet-class>

    <load-on-startup>0</load-on-startup>

</servlet>

 

<servlet-mapping>

    <servlet-name>XFireServlet</servlet-name>

    <url-pattern>/servlet/XFireServlet/*</url-pattern>

</servlet-mapping>

 

<servlet-mapping>

    <servlet-name>XFireServlet</servlet-name>

    <url-pattern>/services/*</url-pattern>

</servlet-mapping>

 

 

传统的处理XML的API有DOM和SAX两种,DOM速度慢,占用内存资源极大,SAX虽然比DOM快,但速度仍不理想,现在,一种新的基于流的Stream API for XML(简称StAX)极大的提高了XML的处理速度,并且已经成为JSR173标准,目前,StAX最好的开源实现是Woodstox,它完整的支持StAX API。Resin3.1 也内置了StAxAPI的定义,就会视图定位一个StAX的实现,为了让XFire不适用Resin3.1内置的StAX实现,而使用Woodstox的实现,就必须在Resin服务器启动的时,指定以下参数。

-Djavax.xml.stream.XMLInputFactory=com.ctc.wstx.stax.WstxInputFactory

-Djavax.xml.stream.XMLOutputFactory=com.ctc.wstx.stax.WstxOutputFactory

-Djavax.xml.stream.XMLEventFactory=com.ctc.wstx.stax.WstxEventFactory

 

 

 

 

 

我们需要确保ClassPath包含了StAX API 和Woodtox实现,即/web/lib/目录下必须有stax-api.jar和wstx-asx-3.0.1.jar.

 

启动Resin服务器,然后打开浏览器,输入地址:

http://localhost:8080/services/BookService?wsdl,就可以看到BookServiceWEB服务的WSDL描述文档,如图示。

 

 

这正是在客户端调用BookService所需要的唯一信息,任何需要调用BookService的客户端只需要知道这个URL即可调用它。为了测试我们发布的WEB服务是否能够正常的在客户端被调用,下面使用Visual Studio2005 作为客户端开发环境,直接在C#工程中调用WEB服务。

 

在Visual Studio2005中创建一个C#Console Application工程,命名为”CallBookService”,然后选择菜单”Project”- > “Add Web Reference…”,在弹出的对话框框中输入WSDL的地址并回车,等待几秒后,VisualStudio 2005就会自动发动发现BookService并找到search()方法,如图所示:

 

 

单击”添加引用”按钮后,BookService就被自动添加进了工程中,Visual Studio2005会自动为该WEB服务生成客户端支持文件/WebReferences/localhost/Reference.cs,其命名空间为CallBookService.localhost,如图:

 

 

打开Program.cs文件,编写代码调用BookService,如图

namespace CallBookService

{

    class Program

    {

        static void Main(string[] args)

        {

            Book[] books = new BookService().search("j2ee");

            foreach (Book bookin books)

            {

                Console.WriteLine("书的作者:{0},     书的名称:{1}",book.author,book.name);   

            }

        }

    }

}

 

 

运行C#代码,在控制台窗口可以看到如下输出:

 

书的作者:Dan Malks,      书的名称:Core J2EE Patterns

书的作者:Bode Carson,      书的名称:The J2EE Tutorial

书的作者:William Crawford,      书的名称:J2EE Design Patterns

书的作者:Ray Lai,      书的名称:J2EE Platform Web Services

请按任意键继续. . .

 

 

调用成功!说明我们发布的WEB服务确实能够被异构平台正确调用。也可以使用其他任何支持WEB服务的语言来调用该WEB服务u,包括前面介绍的在Spring中访问WEB服务的方法。

 

 

 

 

2.      在Spring中集成XFire

 

在前面我们看到了XFire作为WEB服务引擎能极大的简化WEB服务的发布。由于WEB服务不过是为了将系统内部的某些功能暴露给外部,是其他的易购客户端能够调用系统那个的某些功能,因此,仅仅编写了一个简单的JavaBean作为WEB服务端实现是不符合实际应用的,一个实际应用程序的WEB服务必然要设计调用系统内部的逻辑组件,包括访问数据库以获取必要的数据等。我们知道如何在Spring的IOC容器中完成所有组件的部署,如果希望将某些组件的功能暴露为WEB服务,就必须以某种方式将XFire集成到Spring应用程序中。

 

幸运的是,XFire提供了对Spring的完善支持,并且在Spring2.0环境下没有任何问题。下面的例子将描述如何在Spring2.x框架中集成XFire并发布WEB服务。

 

 

我们将ExportWS工程复制一份,重新命名为ExportWS_Spring,然后将web/WEB-INF/lib目录下的Spring-1.2.x.jar替换为Spring2.0的jar文件,此外,src/META-INF/xfire/services.xml也不需要了,直接将整个META-INF目录删掉,WEB服务的相关信息稍后将直接在Spring的XML配置文件dispatcher-servlet.xml中定义。

 

 

 

在上一个例子中,我们仍使用了传统的XML配置文件来声明WEB服务,现在,我们使用JSR181WEB服务注解来直接标注WEB服务。对BookServieImpl增加了如下注解。

@WebService(

       name="BookService",

       serviceName="BookService",

       targetNamespace="http://www.livebookstore.net/BookService"

)

public class BookServiceImpl implements BookService {

 

    @Override

    @WebMethod

    @WebResult

    public Book[] search(String keyword) {

        if("j2ee".equalsIgnoreCase(keyword)) {

            return new Book[] {

                new Book("Core J2EE Patterns","Dan Malks"),

                new Book("The J2EE Tutorial","Bode Carson"),

                new Book("J2EE Design Patterns","William Crawford"),

                new Book("J2EE Platform Web Services","Ray Lai")

            };

        }

        return new Book[0];

    }

}

 

JSR181 的注解非常简单,读者可以很容的猜出各个注解的含义。

和普通的Spring WEB应用程序一样,在web.xml文件中声明Spring的DispatcherServlet。

<servlet>

    <servlet-name>dispatcher</servlet-name>

    <servlet-class>

        org.springframework.web.servlet.DispatcherServlet

    </servlet-class>

    <load-on-startup>0</load-on-startup>

</servlet>

 

<servlet-mapping>

    <servlet-name>dispatcher</servlet-name>

    <url-pattern>/*</url-pattern>

</servlet-mapping>

 

然后编写Spring的XML配置文件dispatcher-servlet.xml,内容如下:

<!-- 引用XFire预定义的Bean配置 -->

<importresource="classpath:org/codehaus/xfire/spring/xfire.xml"/>

 

<!-- Web服务实现类 -->

<beanid="bookService"class="com.zsw.service.BookServiceImpl"/>

 

<!-- 定义URL映射 -->

<beanclass="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

    <propertyname="urlMap">

        <map>

            <entrykey="/BookService"value="bookExporter"/>

        </map>

    </property>

</bean>

 

<!-- bookExporter将处理来自客户端的调用 -->

<beanid="bookExporter"class="org.codehaus.xfire.spring.remoting.XFireExporter">

    <!-- 对外提供的Web服务的接口 -->

    <propertyname="serviceClass"value="com.zsw.service.BookService"/>

    <!-- 实现Web服务的Bean -->

    <propertyname="serviceBean"ref="bookService"/>

    <!-- 下面引用的Bean都已被import引入了 -->

    <propertyname="serviceFactory"ref="xfire.serviceFactory"/>

    <propertyname="xfire"ref="xfire"/>

</bean>

 

需要注意的是,这个XML配置文件必须首先通过<import>引入XFire的一些预定义的Bean,这样就可以直接使用XFireExporter来处理WEB服务请求。这个配置详单简单。由于是在Spring的容器中配置的,对于bookService来说,只要注入了访问数据库的组件(例如,BookDao),就以整整实现一个有用的WEB服务。

 

 

 

读者仍可以使用Microsoft Visual Studio 2005来测试这个通过Spring集成的XFire发布的WEB服务,不过请注意,这个工程的BookService WEB服务的URL地址变为http://localhost:8080/BookService?wsdl。

 

 

 

现在,我们已经详细介绍了WEB服务的原理,如何调用和发布WEB服务,以及如何在Spring框架中集成Web服务。在调用WEB服务时,我们使用的是Axis,但客户端代码使用的是标准的JAX-RPC接口,因此,不存在绑定Axis的问题。如果系统使用XFire来调用WEB服务,可以使用XFire提供的wsdl2java工具来生成相应的支持类,客户端代码是不变的。在发布WEB服务时,我们只介绍如何使用XFire来实现,因为相比其他的Web服务引擎,XFire在实现WEB服务上有巨大的配置和性能优势,因此XFire应当作为JavaEE环境下发布WEB服务的首选。

 

Spring 框架的另一个子项目Spring WEB Services(http://www.springframework.org/spring-ws)的目标就是一个提供了一个与Spring紧密结合的WEB服务模块,并与Spring的MVC框架集成,这个项目可以作为Spring框架下发布WEB服务的一个选择。

 

在Java6中有一个重大的特性就是对WEB服务的内在支持,发布和访问WEB服务都变得轻而易举。如果采用基于Java6的WEB服务,那么不必使用任何第三方WEB服务的支持库,就可以直接将WEB服务完美的集成进来。

 

 demo下载地址:http://download.csdn.net/detail/sz_bdqn/4255985


 

8.4 小结

在这里主要介绍了JavaEE平台的各种远程的调用技术,以及如何在Spring框架中方便的集成他们,即包括了作为客户端带哦用远程服务,也包括了如何在Spring环境中发布远程服务。下面,我们来比较以下各种远程调用的特点和适用范围。

 

 

(1)RMI:RMI协议是专门为Java设计的一种二进制协议,这意味着RMI只能在Java应用程序间通信,而无法与非Java应用程序通信。此外,RMI使用专用的端口,这使得RMI很难穿透防火墙。RMI的好处在于可以直接传输Java对象,因此实现起来非常的简单。

(2)Hessian、Burlap和Spring HTTP Invoker:这3中协议都是基于HTTP的轻量级协议,因此,很容易穿透防火墙,并且理论上采用XML格式的Burlap可以和其他任意应用程序通信,只要对方能正确解析XML。但是。由于这3中协议都是私有协议,没有成为标准,实际应用较少,因此不土建使用这3中协议来实现远程调用。

(3)Web Service : Web服务早已经成为工业标准,被所有的大厂商支持,并且在因特网上得到广泛的应用。由于以HTTP为基础,因此可以很容易穿透防火墙,并且由于XML的平台无关性,通信双方可以而使用任何平台。Web Service的缺点在于部署和调用都相对困难,而且效率较低。

基于上述考虑,我们建议,如果尽在企业内部网中使用,并且通信双方都是Java平台,可以考虑使用RMI,如果需要通过因特网调用,或者通信双方是异构系统(例如Java系统和.Net系统),则WEB服务几乎是唯一的选择。

 

 

 

 

 

 

 

 

原创粉丝点击