使用 Apache CXF 和 Aegis 开发 Web 服务
了解如何使用 CXF 和 Aegis 数据绑定开发 Web 服务
Aegis 是什么?
Apache CXF Web 服务提供了对各种数据绑定工具的支持,Aegis 就是 这些工具中的一个。Aegis 是一个数据绑定 API,用于在 Java 对象与 XML 文档之间执行映射。CXF 框架源自 XFire 项目,而 Aegis 是该项目的基础。XFire 现在也称为 CXF 。在使用或不使用注释的情况下,Aegis 都允许开发人员通过使用外部映射文件来执行数据绑定 。外部映射文件使开发人员能够定制数据映射,从而获得对映射派生方式的更多控制。外部映射文件配置为开发人员提供了许多灵活性并满足了数据绑定需求。对 Web 服务而言,数据也可称为消息,是方法参数或返回类型的一部分。映射文件允许定制 bean、方法名称、方法参数和返回类型。Aegis 还可以在 CXF 环境以外的单独应用程序中使用。
使用 Aegis 的好处
- Aegis 使用外部映射文件为开发人员提供更多的控制权和灵活性,使他们能够根据其项目需要来定制映射。
- Aegis 可以保持 Java 类的整洁。与 JAXB 不同的是,无需提供注释便可满足数据绑定需求。用户可以使用外部映射文件控制绑定。
- Aegis 可以对传入的消息或请求执行模式验证。该验证功能是随最新版的 CXF 发布的 Woodstox 4.x Stax 解析器一起提供的一项功能。
- Aegis 允许您选择是否使用注释。因此,如果您不想使用外部映射文件,那么可以使用注释来满足您的数据绑定需求。
- Aegis 可以在 CXF 环境以外的地方单独使用。它是一种更为独立的数据绑定工具,是 XFire 项目的基本组成部分。
- 非 Aegis 客户端可以使用 Aegis 支持的 Web 服务。客户端应用程序可以在使用 JAXB 或其他任何数据绑定工具的同时调用基于 Aegis 的服务。
- 借助 Aegis,您可以在服务级别上指定绑定。与 JAXB 不同的是,使用 JAXB 时更多是在属性和参数级别上指定绑定。Aegis 可能允许指定一般的绑定。例如,在服务级别上定义的
nillable=false
将确保所有属性或参数都不允许使用 null。
使用代码进行示例说明
我会通过在线教育系统的一个 “创建课程” 用例来说明如何使用 Aegis。如我们所知,在每个教育系统中,都有一些由各大学定义的、让学生学习的课程。这些课程可分为不同的学科领域,比如管理、艺术、科学、数学等等。 我们将定义一项 Web 服务功能,允许课程创建者自行创建课程。为了简便起见,我们提供的功能仅包括在控制台上显示课程属性。通过此功能,我将解释 Aegis 的应用,以及如何控制或定制数据绑定。定制通常包括更改服务方法参数名称和 bean 属性。
为了更为直观一些,您可以开发一个名为 CourseManager
的 Web 服务,它附带一个称为 addCourse 的函数。addCourse
方法将 Course
bean 用作一个参数。Course
bean 将有两个属性,分别用于定义 viz. 代码和名称。通过 Aegis 外部映射文件,您可以重新命名方法参数和 bean 属性,并在 SOAP 有效负载中查看结果。
操作环境应该是 Windows 和 Apache Maven,可以使用它们来完成构建和执行。在 Maven pom 文件中您还需要以下依赖项:
清单 1. 所需的 Maven 依赖项
<dependencies> <!-- Embedded Jetty server --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>${cxf.version}</version> </dependency> <!-- Aegis databinding JAR --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-databinding-aegis</artifactId> <version>${cxf.version}</version> </dependency> </dependencies>
完整的工作流程分为以下步骤:
- 设置环境
- 开发 Web 服务接口和实现类
- 开发客户端和服务器
- 构建并执行
- 创建一个映射文件来定制数据绑定需求
- 通过构建和执行来查看数据绑定变化
设置环境
首先需要适用于 Windows 平台的 Apache CXF 发布版,可以从 http://cxf.apache.org/download.html 下载。您还要下载 CXF 的最新版本 CXF 2.4.0。在下载发布版存档文件之后,请提取该文件,将它放在适当的位置,比如说 C:\apache-cxf-2.4.0
。然后,您需要下载 Java 6.0 版本,可以从 http://java.com/en/download/index.jsp 下载。为了完成构建,还要使用 Apache Maven,可以从 http://maven.apache.org/download.html 下载。Maven 希望您设置 JAVA_HOME
环境变量,该变量将指向安装 JDK 的文件夹。最后,要将每个安装各自的 bin 文件夹都设置为 PATH
环境变量所指向的位置。
开发 Web 服务接口和实现类
您将开发一个简单的 POJO 类 CourseManagerImpl
和接口 CourseManager
。该接口定义了一个方法 addCourse
,它使用 Course
bean 作为参数。而该实现类将如下所示:
清单 2. CourseManagerImpl 实现类
public class CourseManagerImpl implements CourseManager { public void addCourse(Course course) { System.out.println("Course code: " + course.getCode()); System.out.println("Course name: " + course.getName()); } }
如您在上述代码中所见,这里没有提及 @Webservice
注释。这意味着您将使用 CXF 的简易前端来发布和使用 CourseManager
Web 服务。该简易前端允许开发人员在不使用注释的情况下以纯 POJO 形式对 Web 服务类进行编码。addCourse
方法仅在控制台上打印 course
属性。当然,实际上您可能想提供逻辑,以便将 course
添加到数据库。但如前面所述,我们保留它是因为我们有更长远的目标,即使用 Aegis 绑定来定制 Web 服务消息部分。
开发客户端和服务器
首先,您要开发一个用来发布 CourseManager
Web 服务的服务器。该服务器代码如下所示:
清单 3. 服务器代码
public final class Server { public static void main(String args[]) throws Exception { CourseManagerImpl implementor = new CourseManagerImpl(); ServerFactoryBean svrFactory = new ServerFactoryBean(); svrFactory.setAddress("http://localhost:9000/CourseManager"); svrFactory.setServiceBean(implementor); svrFactory.create(); System.out.println("Server ready..."); } }
上述服务器代码非常简单明了。服务器由 ServerFactoryBean
类代表,该类是 CXF 的简易前端 API 的一部分。通过这个类,您可以设置一些必要的属性,比如 Web 服务实现类和端点 URL。该服务实现类将是 CourseManagerImpl
,而端点 URL 将是 http://localhost:9000/CourseManager
。端点 URL 是发布 CourseManager
Web 服务的地方。create
方法将在端口 9000
上启动嵌入式 Jetty 服务器。
下一步是编写将使用 CourseManager
Web 服务的客户端代码。
清单 4. 客户端代码
public final class Client { public static void main(String args[]) throws Exception { ClientProxyFactoryBean factory = new ClientProxyFactoryBean(); factory.setServiceClass(CourseManager.class); factory.setAddress("http://localhost:9000/CourseManager"); factory.getOutInterceptors().add(new LoggingOutInterceptor()); CourseManager client = (CourseManager) factory.create(); Course course = new Course(); course.setCode("C01"); course.setName("English Grammer"); client.addCourse(course); } }
客户端代码与服务器代码非常相似,除了此处将使用 LoggingOutInterceptor
拦截器类在控制台上记录 SOAP 消息。该代码是必需的,在我们应用 Aegis 绑定之后,您能用它在 SOAP 中查看变化。
构建和执行
您可以使用 Maven 构建上述代码。服务器和客户端类是主要 Java 应用程序,允许在单独的命令窗口中运行。当然,您也可以使用 Maven java:exec goal 运行它们。首先启动服务器,然后运行客户端程序。您会看见从客户端传递到服务器的以下 SOAP 消息。
图 1. SOAP 有效负载

让我们来仔细看一下这个 SOAP 消息。方法名称 addCourse 以元素形式包含在 SOAP 正文中。而方法参数 Course bean 则是以子元素形式编写在 <addCourse> 元素中,该子元素被命名为 <arg0>。<arg0> 元素的子元素 Course bean viz. <code> 和 <name> 的属性。
现在,您可以调整 SOAP 消息,通过重新命名这些元素名称使这些名称变得更有意义。在此处会将 Aegis 应用于 CourseManager
Web 服务。您会在下一步中看到它们。
创建一个映射文件来定制数据绑定需求
在这一步中,将使用 Aegis 数据绑定来定制 SOAP 元素。因为元素 <arg0> 代表了我们的 Course bean,我们会将该名称重命名为 <course>,而不是 <arg0>。您还应该将 <code> 和 <name> 元素分别重命名为 <courseCode> 和 <courseName>。然后使用 Aegis 外部映射文件执行这些元素定制。Aegis 提供了外部映射文件的概念,在此您可以根据自己的绑定需要该文件指定不同定制。
第一步是将元素 <arg0> 重命名为 <course>。因为该元素代表了 Course bean,是 addCourse 服务方法的第一个参数。您需要为 CourseManager
服务编写一个映射文件,该映射文件的名称(nomenclature )为 <classname>.aegis.xml
。该映射文件必须与映射的类一起放在同一程序包中。因此,以下 CourseManager.aegis.xml
将成为 demo.cxf.aegis 程序包的一部分。
清单 5. CourseManager.aegis.xml 映射文件
<mappings> <mapping name="CourseManager"> <method name="addCourse"> <parameter index="0" mappedName="course" nillable='false' /> </method> </mapping> </mappings>
上面的映射文件很容易理解。映射名称 CourseManager
指示您将映射一个 CourseManager
Web 服务。方法 addCourse 有一个参数,即 Course bean,该参数的索引为 0。因此,在进行编组的时候,需要将此零索引参数重命名为 course
。这样便可确保元素 <arg0> 将被重命名为 <course>。nillable=false
意味着参数不得为 null。
您现在便可重命名 SOAP 元素 <code> 和 <name>,它们是 <arg0> 元素的一部分。您可以编写目前映射 Course
bean 的另一个映射文件,根据其属性需要在绑定期间对其重新命名。以下 Course.aegis.xml
文件将是 demo.cxf.aegis
程序包的一部分。
清单 6. Course.aegis.xml 映射文件
<mappings> <mapping name="Course"> <property name="code" mappedName="courseCode" nillable='false' /> <property name="name" mappedName="courseName" nillable='false' /> </mapping> </mappings>
上面的映射文件映射了 Course
bean,并将其已编组的参数 code
和 name
重命名为 courseCode
和 courseName
。至此,您已成功定义了 CourseManager
Web 服务和 Course
bean 的绑定规则。
最后,您需要将 Aegis 功能添加到客户端和服务器代码中。
清单 7. 将 Aegis 数据绑定添加到服务器代码中
. . . CourseManagerImpl implementor = new CourseManagerImpl(); ServerFactoryBean svrFactory = new ServerFactoryBean(); svrFactory.setAddress("http://localhost:9000/CourseManager"); svrFactory.setServiceBean(implementor); svrFactory.getServiceFactory().setDataBinding(new AegisDatabinding()); svrFactory.create(); System.out.println("Server ready..."); } }
清单 8. 将 Aegis 数据绑定添加到客户端代码中
. . . ClientProxyFactoryBean factory = new ClientProxyFactoryBean(); factory.setServiceClass(CourseManager.class); factory.setAddress("http://localhost:9000/CourseManager"); factory.getServiceFactory().setDataBinding(new AegisDatabinding()); . . . } }
通过构建和执行查看数据绑定变化
构建修改后的代码,您会看见以下输出。
图 2. 应用 Aegis 数据绑定后的 SOAP Payload

上述 SOAP 有效负载现在看起来更有意义。在应用 Aegis 数据绑定之后,您可以看见元素 <arg0> 被更改为 <course>,而子元素 <code> 和 <name> 被分别更改为 <courseCode> 和 <courseName>。
借助 Aegis 绑定,您可以做许多事情,而不仅仅是重命名 SOAP 有效负载元素。您可以使元素作为一个属性,使方法参数或 bean 属性为 nillable 或非 nillable 。您还可以向元素或属性添加名称空间,可以指定是否序列化某个 bean 属性。除此之外,您还可以提供定制类型,先于默认 Aegis 类型执行映射。
相关主题
- 使用 Spring 和 Apache CXF 设计和实现 POJO Web 服务,第 1 部分:使用 CXF 和 Spring 创建 Web 服务的简介。
- 使用 Spring 和 Apache CXF 设计和实现 POJO Web 服务,第 2 部分:创建 RESTful Web 服务
- 加入IBM developerWorks Live! 技术加油站,获取最新的 IBM 产品,工具以及 IT 行业趋势的资讯。
- 以最适合您的方式评估 IBM 产品:下载产品试用版,在线试用产品,在云环境下试用产品,或者在 SOA Sandbox 中花费几个小时来学习如何高效实现面向服务架构。