关于 Apache CXF
Apache CXF = Celtix + XFire,Apache CXF 的前身叫 Apache CeltiXfire,现在已经正式更名为 Apache CXF 了,以下简称为 CXF。CXF 继承了 Celtix 和 XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且提供了多种 Binding 、DataBinding、Transport 以及各种 Format 的支持,并且可以根据实际项目的需要,采用代码优先(Code First)或者 WSDL 优先(WSDL First)来轻松地实现 Web Services 的发布和使用。目前它仍只是 Apache 的一个孵化项目。
Apache CXF 是一个开源的 Services 框架,CXF 帮助您利用 Frontend 编程 API 来构建和开发 Services ,像 JAX-WS 。这些 Services 可以支持多种协议,比如:SOAP、XML/HTTP、RESTful HTTP 或者 CORBA ,并且可以在多种传输协议上运行,比如:HTTP、JMS 或者 JBI,CXF 大大简化了 Services 的创建,同时它继承了 XFire 传统,一样可以天然地和 Spring 进行无缝集成。
功能特性
CXF 包含了大量的功能特性,但是主要集中在以下几个方面:
支持 Web Services 标准:CXF 支持多种 Web Services 标准,包含 SOAP、Basic Profile、WS-Addressing、WS-Policy、WS-ReliableMessaging 和 WS-Security。
Frontends:CXF 支持多种“Frontend”编程模型,CXF 实现了 JAX-WS API (遵循 JAX-WS 2.0 TCK 版本),它也包含一个“simple frontend”允许客户端和 EndPoint 的创建,而不需要 Annotation 注解。CXF 既支持 WSDL 优先开发,也支持从 Java 的代码优先开发模式。
容易使用: CXF 设计得更加直观与容易使用。有大量简单的 API 用来快速地构建代码优先的 Services,各种 Maven 的插件也使集成更加容易,支持 JAX-WS API ,支持 Spring 2.0 更加简化的 XML 配置方式,等等。
支持二进制和遗留协议:CXF 的设计是一种可插拨的架构,既可以支持 XML ,也可以支持非 XML 的类型绑定,比如:JSON 和 CORBA。
项目目标
下面列出了来自 Apache CXF 官方网站(参见 参考资源)的项目目标。
概要
高性能
可扩展
简单且容易使用
支持多种标准
支持 JAX-WS、 JAX-WSA、JSR-181 和 SAAJ;
支持 SOAP 1.1、1.2、WS-I BasicProfile、WS-Security、WS-Addressing、WS-RM 和 WS-Policy;
支持 WSDL 1.1 、2.0;
支持 MTOM;
多种传输方式、Bindings、Data Bindings 和 Format
Bindings:SOAP、REST/HTTP;
Data Bndings:目前支持 JAXB 2.0、Aegis 两种,默认是 JAXB 2.0。XMLBeans、Castor 和 JiBX 数据绑定方式将在 CXF 2.1 版本中得到支持;
格式(Format):XML、JSON;
传输方式:HTTP、Servlet、JMS 和 Jabber;
可扩展的 API 允许为 CXF 增加其它的 Bindings,以能够支持其它的消息格式,比如:CSV 和固定记录长度。
灵活部署
轻量级容器:可在 Tomcat 或基于 Spring 的容器中部署 Services;
集成 JBI:可以在如 ServiceMix, OpenESB or Petals 等等的 JBI 容器中将它部署为一个服务引擎;
集成 SCA:可以部署在如 Tuscany 之类的 SCA 容器中;
集成 J2EE:可以在 J2EE 应用服务器中部署 Services,比如:Geronimo、JOnAS、JBoss、WebSphere Application Server 和 WebLogic Application Server,以及 Jetty 和 Tomcat;
独立的 Java 客户端/服务器。
支持多种编程语言
全面支持 JAX-WS 2.0 客户端/服务器编程模型;
支持 JAX-WS 2.0 synchronous、asynchronous 和 one-way API's;
支持 JAX-WS 2.0 Dynamic Invocation Interface (DII) API;
支持 wrapped and non-wrapped 风格;
支持 XML messaging API;
支持 JavaScript 和 ECMAScript 4 XML (E4X) ,客户端与服务端均支持;
通过 Yoko 支持 CORBA;
通过 Tuscany 支持 SCA;
通过 ServiceMix 支持 JBI ;
代码生成
Java to WSDL;
WSDL to Java;
XSD to WSDL;
WSDL to XML;
WSDL to SOAP;
WSDL to Service;
CXF 安装包
下载及目录结构
CXF 框架目前的最新版本是 2.0.2,可以访问 Apache 站点(链接请见 参考资源)下载 CXF 框架的安装包,下载时请选择“二进制发布包(Binary distribution)”,当然如果您有兴趣也可以下载相应版本的“源代码发布包(Source distribution)”。
下载完成后,将下载的文件解压缩到任意的文件夹中,比如:C:/Java/CXF,在后面的章节中使用 %CXF_HOME% 表示 CXF 框架的存放目录,解压缩后形成的文件目录结构按名称排序如下:
文件目录结构及相关文件的详细说明:
bin(目录)
bin 目录中是 CXF 框架中所提供的代码生成、校验、管理控制台工具:
Java to WSDL : java2wsdl
CXF Management Console Tool : mc
WSDL to Java : wsdl2java
WSDL to Service : wsdl2service
WSDL to SOAP : wsdl2soap
WSDL to XML : wsdl2xml
WSDL Validation : wsdlvalidator
XSD to WSDL : xsd2wsdl
docs(目录)
CXF 所有类(class)对应的 API 文档,为开发者使用 CXF 完成应用开发提供应有的帮助。
etc(目录)
包含一个基本的 Service 暴露所需要的 web.xml 文件,及其它的配置文件。
lib(目录)
lib 目录中包含 CXF 及其运行时所需要的和可选的第三方支持类包(.jar 文件),可以根据不同项目所需的 CXF 特性选择所需要的支持类包。如果不想一一去区分的话,可以直接在 Web 项目中包含所有的 CXF 及其运行时所需要的第三方支持类包(.jar 文件)即可。
其中 cxf-2.0.2-incubator.jar 是 CXF 框架的二进制包文件,包含了全部的模块(modules),cxf-manifest-incubator.jar 是列表清单文件 manifest jar 。
以下的 jar 包是所有 CXF 项目所必需的:
对于 Java2WSDL 和 WSDL2Java,除了必需的之外,还需要再增加如下 jar 包:
为了支持 JAX-WS ,除了必需的之外,还需要再增加如下 jar 包:
为了支持 XML 配置,除了必需的之外,还需要再增加如下 jar 包:
为了独立的 HTTP 服务支持,除了必需的之外,还需要再增加如下 jar 包:
为了支持 Aegis ,除了必需的之外,还需要再增加如下 jar 包:
为了支持 WS-Security ,除了必需的之外,还需要再增加如下 jar 包:
为了支持 HTTP Binding ,除了必需的之外,还需要再增加如下 jar 包:
jra.jar
jettison.jar (仅为 JSON 服务所需的)
bcprov-jdk14.jar
wss4j.jar
xalan.jar
xmlsec.jar
jaxen.jar
jdom.jar
stax-utils.jar
geronimo-servlet.jar
jetty.jar
jetty-sslengine.jar
jetty-util.jar
sl4j.jar & sl4j-jdk14.jar (可选的,但是可以提升日志 logging)
aopalliance.jar
spring-beans.jar
spring-context.jar
spring-core.jar
spring.web.jar
jaxws-api.jar
saaj-api.jar
saaj-impl.jar
asm.jar (可选的,但是可以提升包装类型的性能)
jaxb-xjc.jar
veliocity.jar
velocity-dep.jar
cxf.jar
commons-logging.jar
geronimo-activation.jar (Or the Sun equivalent)
geronimo-annotation.jar (Or the Sun equivalent)
geronimo-javamail.jar (Or the Sun equivalent)
neethi.jar
jaxb-api.jar
jaxb-impl.jar
stax-api.jar
XmlSchema.jar
wstx-asl.jar
xml-resolver.jar
licenses(目录)
列表了引用第三方 jar 包的相关许可协议。
modules(目录)
modules 目录中包含了 CXF 框架根据不同特性分开进行编译的二进制包文件。发布基于 CXF 框架的 Web 项目时,可以选择使用该目录下的所有 .jar 文件,也可以选择 lib 目录中的 cxf-2.0.2-incubator.jar 文件。
samples(目录)
samples 目录中包含了所有随 CXF 二进制包发布的示例,包含这些示例的源代码和相关 Web 应用配置文件,可以方便地用 Ant 来编译运行测试这些示例,来了解 CXF 的开发和使用的方法。可以通过 samples 目录和它各个子目录下的 README.txt 的文件来详细了解示例的编译与运行的步骤。
DISCLAIMER 由于仍是处于 Apache 孵化状态的项目,这里描述了一些说明。
LICENSE 文件中包含了 CXF 框架的授权协议 Apache License Version 2.0 。
NOTICE 罗列了 CXF 框架用到的相关第三方组件的授权协议以其它的相关信息。
README 文件中包含了 CXF 框架本身的一些简要说明。
release_notes.txt 包含了 CXF 发布时的一些信息,包括运行时所需要的环境,修复 BUG 的列表等。
CXF 框架支撑环境
CXF 框架是一种基于 Servlet 技术的 SOA 应用开发框架,要正常运行基于 CXF 应用框架开发的企业应用,除了 CXF 框架本身之外,还需要 JDK 和 Servlet 容器的支持。
JDK 版本选择、下载和安装
CXF 支持非常多的特性,其中不同的特性对 JDK 版本的要求有所不同,但是 JDK 最低的版本是需要选择 JDK 5 或者以上版本。JDK 各版本均可以在 Sun 公司网站上下载(链接见 参考资源),如何安装 JDK 请参考 SUN 公司的相关技术文档和 JDK 的帮助文档。为了运行 CXF 携带的 samples 目录下的所有示例,还需要 Apache Ant 1.6.5 或以上的版本(下载链接见 参考资源)。为了使用 CXF 的 WS-Security 特性,还需要 Bouncy Castle ,可以从网站下载(下载链接见 参考资源),并增加到 CLASSPATH 中。
Servlet 容器下载和安装
CXF 是一种基于 Servlet 技术的 SOA 应用开发框架,需要 Servlet 容器的支持。CXF 支持在多种 Servlet 容器中运行,包括 WebSphere、WebLogic、Tomcat、Jetty 等。为了说明的简单,我们选择使用 Tomcat 5.5.25 和 Jetty 作为 CXF 的运行容器,所有配置过程和发布步骤的说明也均是针对 Tomcat 和 Jetty,如果读者使用 Tomcat 之外的其它 Servlet 容器或者选择了 Tomcat 的其它版本,下面的配置过程和步骤可能需要做出调整,请读者根据实际 Servlet 容器的帮助文档进行相应调整。
Tomcat 与 Jetty 的各个版本均可以在网上下载(下载链接见 参考资源),如何正确安装 Tomcat 与 Jetty 服务器请参考相关的帮助文档。
CXF 之初体验
下面我们将通过直接运行与简单修改 CXF 自带的例子体验一下服务的发布与消费。
配置与检查环境变量
UNIX 上:
CXF_HOME=/opt/Java/CXF JAVA_HOME=/opt/JDK/1.5.0 ANT_HOME=/opt/Java/Ant export PATH=$JAVA_HOME/bin:$ANT_HOME/bin:$CXF_HOME/bin:$PATH export CLASSPATH=.:$CXF_HOME/lib/cxf-manifest-incubator.jar:./build/classes
Windows 上:
set CXF_HOME=C:\Java\CXF set JAVA_HOME=C:\JDK\1.5.0 set ANT_HOME=C:\Java\Ant set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin;%CXF_HOME%\bin;%PATH% set CLASSPATH=.;%CXF_HOME%\lib\cxf-manifest-incubator.jar;.\build\classes
为了部署到 Java EE 的容器中进行测试,示例采用 Tomcat 来进行,同样设置 CATALINA_HOME 变量:
UNIX 上:
CATALINA_HOME=/opt/OpenSource/Tomcat-5.5.25 export CATALINA_HOME
Windows 上:
set CATALINA_HOME=C:\OpenSource\Tomcat-5.5.25
如果以上环境变量您没有并没有直接设置到系统的变量中,可以将之另存为一个文件,保存起来,比如存为:%CXF_HOME%/env.sh或者%CXF_HOME%/env.bat,这样在运行示例前,先运行它来设置环境变量即可。
通过 Ant 来构建和运行示例
构建与启动 Server
首先,进入到 %CXF_HOME%/java_first_pojo/ 目录下。在 UNIX 或 Windows 下的命令都是一样的,如下:
ant server
最后可以看到如下信息:
build: server: [java] Server ready...
如果看不到这些信息,请检查环境变量设置是否正确。
运行 Client
再打开一个命令窗口,运行:
ant client
最后可以看到如下信息:
client: [java] Invoke sayHi().... [java] Hello user BUILD SUCCESSFUL
如果看不到这些信息,问题应当是出现在环境变量的设置上,需要再次检查一下您的环境变量设置是否正确。
体验改变
通过上面的构建,运行 Server ,再运行 Client ,我们可以体会到利用 CXF 发布与使用 Web Services 是如此简单。下面我们将开始进行简单地代码修改。
修改 Client 端
打开 %CXF_HOME%/samples/java_first_pojo/src/demo/hw/client 目录下的 Client.java 文件,在最后面修改为:
System.out.println(client.sayHi("World , 利用 Apache CXF 实现 Web Services"));
修改并保存后,再运行:
ant client
现在可以看到您修改后的信息,如下:
client: [java] Invoke sayHi().... [java] Hello World , 利用 Apache CXF 实现 Web Services BUILD SUCCESSFUL
修改 Server 端代码
Ctrl + C 直接停止刚才启动的 ant server 启动端,然后打开 %CXF_HOME%/samples/java_first_pojo/src/demo/hw/server 目录下的 HelloWorldImpl.java 文件,修改
return "Hello " + text;
为
return "Hello " + text + new java.util.Date();
我们在返回信息时增加了一个时间戳上去,然后再次分别运行 ant server 与 ant client ,可以看到返回的信息后面增加了时间,如下:
client: [java] Invoke sayHi().... [java] Hello World , 利用 Apache CXF 实现 Web ServicesThu Sep 27 21:40:49 CST 2007 BUILD SUCCESSFUL
以上只是一个简单的示例,体验一下利用 CXF 进行发布与使用 Web Services,并尝试修改了 Server 端与 Client 端的代码。下面让我们更进一步,通过查看 Server.java 及 Client.java 的代码,来了解一下 CXF 的运作过程。
代码简单分析
Server.java 中主要的代码片断如下,它利用 ServerFactoryBean 来进行 Web Services 的发布,实例化一个实现类 HelloWorldImpl,设置将要进行发布的地址 address,最后通过 ServerFactoryBean 的 create() 方法就成功地发布了 Web Services,如此简单而已,只有六行代码:
HelloWorldImpl helloworldImpl = new HelloWorldImpl(); ServerFactoryBean svrFactory = new ServerFactoryBean(); svrFactory.setServiceClass(HelloWorld.class); svrFactory.setAddress("http://localhost:9000/Hello"); svrFactory.setServiceBean(helloworldImpl); svrFactory.create();
Client.java 中的主要代码片断如下,通过 ClientProxyFactoryBean 代理工厂类来创建一个服务,绑定到 endPointAddress 地址,就可以 create 并得到服务,并进行服务消费了:
ClientProxyFactoryBean factory = new ClientProxyFactoryBean(); factory.setServiceClass(HelloWorld.class); factory.setAddress("http://localhost:9000/Hello"); HelloWorld client = (HelloWorld)factory.create(); System.out.println("Invoke sayHi()...."); System.out.println(client.sayHi("user"));
最后,停止 Server,并清除构建过程中产生的一些文件,直接运行 ant clean 即可。
构建和运行在 Servlet 容器里的示例
接下来我们尝试编译打包一个示例,并部署到 Java EE 的容器里进行测试。
构建 Web 应用程序包
停止掉前面运行的 Server ,然后在命令行运行:
ant war
将在 %CXF_HOME%/samples/java_first_pojo/build/war/ 目录下生成 helloworld.war 文件。
部署应用
先运行如下命令,将运行部署到 Tomcat 容器中:
ant deploy -Dtomcat=true
启动 Tomcat
然后在 Windows 下通过 startup.bat 或在 Unix 下通过 startup.sh 来启动 Tomcat,CXF 的应用也就随之启动。通过 Tomcat 管理控制台 http://localhost:8080/manager/html/ 可以看到已经成功部署了 helloworld.war 的应用程序,如下图所示:
图 2. 在 Tomcat 5.5.25 上面成功部署 CXF Web Service 的示意图
校验服务
假设您的 Tomcat 服务端口是 8080 ,那运行以下命令就可以调用部署到 Java EE 容器里的 CXF 所提供的 Web Services 的服务了。
http://localhost:8080/helloworld/services/hello_world?wsdl
查看 wsdl 文件的信息内容如下:
图 3. 在 Tomcat 5.5.25 上面成功部署 CXF Web Service 的示意图
运行 Client
接下来我们来运行 Client 来使用它,运行:
ant client-servlet
如果您的端口不是 8080,可以使用:
ant client-servlet -Dbase.url=http://localhost: 端口号
或者
ant client-servlet -Dhost=localhost -Dport= 端口号
来调用 Web Services ,返回结果如下:
client-servlet: [java] Invoke sayHi().... [java] Hello World , 利用 Apache CXF 实现 Web ServicesThu Sep 27 21:56:32 CST 2007 BUILD SUCCESSFUL
在 Tomcat 后台可以看到一些 Exception 的信息,这是正常的,是因为public void pingMe() throws PingMeFault特意抛出来的,不必理会,没有抛出异常信息才是不正常的,需要重新检查以上各个步骤是否正确执行了。
卸载应用
从 Tomcat 中卸载应用,运行:
ant undeploy -Dtomcat=true
最后,停止 Tomcat,然后清除构建过程中产生的一些文件,直接运行ant clean即可。
CXF 应用开发
下面就将开始我们的 CXF Web Services 的开发之旅!首先,要有一个基于 Eclipse 的开发环境;然后,我们将利用这个开发环境开发一个简单的“调查投票”示例,同时我们将解释一些 CXF 在开发中进行配置的基本方法。
开发环境准备
在开发之前我们通常需要做些准备工作,比如搭建好开发环境。在本教程中,我们将在 Eclipse 3.2 环境中开发,当然如果您是使用 Eclipse Europa(Eclipse 3.3)也是可以的,我们假设您已经下载并且在计算机中安装好了 Eclipse 开发环境(关于如何下载和安装 Eclipse,请参见 参考资源)。
创建项目骨架
启动 Eclipse,创建一个 Java Project,如果是 WTP 的话,可以直接创建一个 J2EE 的 Web 项目,我们取名为 CXF_Spring_Survey,并设置编译的 output 路径为 WEB-INF/classes 目录,方便直接部署应用程序。
目录结构如下图所示:
图 4. 利用 CXF 开发 Web Services 的工程骨架示意图
为了方便起见,我们直接拷贝 %CXF_HOME%/lib 目录下的所有 .jar 文件到 CXF_Spring_Survey 项目的 WEB-INF/lib 目录下,也可以根据前面“CXF 安装包”章节所述的各个 jar 包的作用范围选择仅需要的 .jar 文件。在 Eclipse 里刷新后,可以看到如下结构:
图 5. 利用 CXF 开发 Web Services 的工程引入所有 .jar 文件后的骨架示意图
并在 CXF_Spring_Survey 项目属性里将这些 .jar 加到 Java Build Path 当中去,如下图:
图 6. Eclipse 中引入所有 .jar 文件后的示意图
这样,项目的基本骨架已经创建完成,接下来开始编写接口与具体实现的代码了。
接口类创建
在项目的 src 目录中新建一个ws.cxf包,并在里面创建接口类ISurveyService.java,为了简单示示例起见,我们仅创建一个方法public String vote(String username,int point);这里要注意的是我们在接口上用@WebService注解标明这是一个即将暴露为 Web Service 的接口,并将里面的方法都暴露出去。完整的接口代码清单如下:
package ws.cxf; import javax.jws.WebService; @WebService public interface ISurveyService { /** * @param username 名字 * @param point 分数 * @return */ public String vote(String username,int point); }
接下来,我们根据接口的定义,来实现它。
具体类实现
针对接口的定义,我们创建一个相应的实现类,并将其定义在sw.cxf.impl包中,完整的代码清单如下:
package ws.cxf.impl; import javax.jws.WebService; import ws.cxf.ISurveyService; @WebService public class SurveyService implements ISurveyService { private String excludeName = "Michael"; private int leastPonit = 5; public String vote(String username,int point) { String result = ""; if(excludeName.equals(username)) { result = " 您不能重复进行投票!"; } else { result = " 谢谢您的投票!"; if(point < leastPonit) { result += " 您的投票分数太低!"; } else { result += " 您的投票分数通过审核!"; } } return result; } // For IoC public String getExcludeName() { return excludeName; } public void setExcludeName(String excludeName) { this.excludeName = excludeName; } public int getLeastPonit() { return leastPonit; } public void setLeastPonit(int leastPonit) { this.leastPonit = leastPonit; } }
接口定义与具体的实现就这样简单完成了,接下来就是相关的配置工作了,首先进行 Spring 的 Bean 配置。
回页首
Spring 配置
在 src 目录中创建 beanRefServer.xml 文件,用来定义 Spring 的 Bean 的配置,CXF 支持 Spring 2.0 Schema 标签配置方式,并且提供快捷暴露 Web Services 的标签。
首先,我们需要引入 Spring 与 CXF 的命名空间(namespace),如下:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
这样,我们可以使用 Spring 与 CXF 的标签配置了。接着,我们需要引入我们所需要的 CXF 的 Bean 定义文件,如下:
<!-- Import Apache CXF Bean Definition --> <import resource="classpath:META-INF/cxf/cxf.xml"/> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/> <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
接着定义我们具体实现的 Bean ,这个 Bean 的定义与 Spring 普通的 Bean 定义是一样的:
<!-- SurveyService --> <bean id="surveyService" class="ws.cxf.impl.SurveyService"> <property name="excludeName" value="Michael"/> <property name="leastPonit" value="10"/> </bean>
最后,将定义的 Bean 暴露出去成为 Web Service 服务,通过 CXF 提供的 Schema 标签配置<jaxws:server>,这样定义的配置显得更加简洁与方便,定义如下:
<!-- Expose SurveyWebService --> <jaxws:server id="surveyWebService" serviceClass="ws.cxf.ISurveyService" address="/SurveyWebService"> <jaxws:serviceBean> <ref bean="surveyService"/> <!-- 要暴露的 bean 的引用 --> </jaxws:serviceBean> </jaxws:server>
在配置中,serviceClass的值是我们的接口类的名称,address为将要暴露出去的 Web Service 访问地址。比如:/SurveyWebService,那么客户端消费 Web Service 的地址就会成为 http://host:port/WebAPPName/SurveyWebService ,与之相应的 WSDL 地址则为: http://host:port/WebAPPName/SurveyWebService?wsdl 。
Web 应用配置
由于我们的示例是需要通过 Servlet 容器进行服务暴露,因此需要配置相对应的 web.xml 文件,首先是增加 Spring 的配置文件加载 Listener,如下:
<!-- Spring Config Location --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/classes/beanRefServer.xml</param-value> </context-param> <!-- Spring ContextLoaderListener --> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>
接下来配置 CXF Servlet 的定义,以及它的映射,如下:
<!-- Apache CXFServlet --> <servlet> <servlet-name>CXFServlet</servlet-name> <display-name>CXF Servlet</display-name> <servlet-class> org.apache.cxf.transport.servlet.CXFServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- CXFServlet Mapping --> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
我们将之映射为/*。这样,服务端的代码与配置就全部完成了,接下来就是将应用程序部署到 Web 容器中去,并验证服务是否正常发布。
应用部署
我们将应用部署到 Tomcat 5.5.25 当中,在这里,我们采用链接(Link)的部署方式,简单而方便,在 %TOMCAT_HOME%/conf/Catalina/localhost/ 目录下创建与项目名称 CXF_Spring_Survey 一致的 xml 文件:CXF_Spring_Survey.xml,内容为:
<?xml version="1.0" encoding="UTF-8"?> <Context docBase="F:/JavaProject/WebService/CXF/CXF_Spring_Survey"/>
docBase 里的内容根据您的实际项目所在的目录进行更改,注意使用/而不是\即可。
启动服务
这时开始启动 Tomcat ,在启动的过程中,可以在启动窗口上看到以链接方式部署的应用在启动中会打印出一些相关信息来,最后显示启动成功。 通过访问 http://localhost:8080/CXF_Spring_Survey/ 可以看到 CXF 暴露的服务链接:
可以直接点击进去,或者手工输入 WSDL 的地址进行访问:http://localhost:8080/CXF_Spring_Survey/SurveyWebService?wsdl ,可以看到如下的 WSDL 内容:
图 8. SurveyWebService 的 WSDL 内容示意图
这样,我们可以确定我们的服务真正发布成功了,接下来就可以利用客户端进行消费了。
消费服务
回到 Eclipse 开发平台,开始编写消费服务相关的代码,首先通过 Spring 与 CXF 的配置来定义 Web Service 的客户端 Bean,在 src 目录下创建 beanRefClient.xml 配置文件,同样,我们也需要引入 Spring 与 CXF 命名空间的声明,并引入 CXF 的 Bean 的定义文件,最后通过与服务端配置相对的 CXF 标签<jaxws:client>来定义客户端访问服务的声明,完整的定义内容如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- Import Apache CXF Bean Definition --> <import resource="classpath:META-INF/cxf/cxf.xml"/> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/> <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/> <!-- SurveyWebService Client --> <jaxws:client id="surveyServiceClient" serviceClass="ws.cxf.ISurveyService" address="http://localhost:8080/CXF_Spring_Survey/SurveyWebService"/> </beans>
定义说明:id为 Spring 定义的 id,用来在程序里进行获取它的标识,serviceClass仍是为服务端定义的接口类,address为完整的 Web Service 地址,这个与服务端的定义不一样。
定义完配置文件,接下来我们编写访问的具体代码,在 test 目录下创建ws.cxf.client包,然后创建 SurveyServiceClient.java,完整的代码如下:
package ws.cxf.client; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import ws.cxf.ISurveyService; public class SurveyServiceClient { public static void main(String[] args) { // 加载客户端的配置定义 ApplicationContext context = new ClassPathXmlApplicationContext("beanRefClient.xml"); // 获取定义的 Web Service Bean ISurveyService surveyService = (ISurveyService)context.getBean("surveyServiceClient"); // 1、定义调查投票的变量与内容,用来发送给服务 String username = "Test"; int point = 88; // 调用方法进行服务消费 String result = surveyService.vote(username,point); System.out.println("Result:" + result); // 2、传递不一样的调查投票内容 username = "Michael"; point = 100; // 再次调用方法进行服务消费,得到不一样的结果 result = surveyService.vote(username,point); System.out.println("Result:" + result); // 3、第三次传递与调用 username = "Jordan"; point = 9; result = surveyService.vote(username,point); System.out.println("Result:" + result); } }
直接运行以上客户端消费程序,一共调用了三次 Web Service,并得到结果如下:
Result: 谢谢您的投票!您的投票分数通过审核! Result: 您不能重复进行投票! Result: 谢谢您的投票!您的投票分数太低!
于是服务正常地得到了调用,并且能够正确地返回结果,完整的代码及配置文件可以在本教程的 下载链接 里进行下载。
结束语
本文教程中,我们结合了一个简单的例子,将 CXF 与 Spring 的简单配置与整合完整地演示出来,最后我们完成了对 Web Services 的发布与消费。在各种 Web Services 实现框架共存的开源社区与商业实现中,CXF 整合了 Celtix 与 XFire 的精华,相信凭借它简单的配置,与 Spring 无缝整合,肯定会在 Web Services 领域中占有一席之地。但作为一个新的项目,要被广大开发者所接受并在企业应用开发中使用,仍有一段比较长的路要走,让我们拭目以待吧!