5.3. 在捆绑包中打包 Web 服务
5.3.1. 概述
本节介绍如何为 Apache CXF 应用程序修改现有 Maven 项目,以便项目生成适合在 Red Hat Fuse OSGi 容器中部署的 OSGi 捆绑包。要转换 Maven 项目,您需要修改项目的 POM 文件和项目的 Blueprint 文件(位于 META-INF/spring
中)。
5.3.2. 修改 POM 文件来生成捆绑包
要配置 Maven POM 文件来生成捆绑包,基本上有两个更改,您需要进行两个更改:将 POM 的软件包类型改为 bundle
; 并将 Maven 捆绑包插件添加到 POM 中。详情请查看 第 5.1 节 “生成捆绑包项目”。
5.3.3. 必需的导入软件包
为了让应用程序使用 Apache CXF 组件,您需要将其软件包导入到应用程序的捆绑包中。由于 Apache CXF 中依赖项的复杂性质,您无法依赖 Maven 捆绑包插件或 bnd
工具来自动确定所需的导入。您需要显式声明它们。
您需要将以下软件包导入到捆绑包中:
javax.jws javax.wsdl javax.xml.bind javax.xml.bind.annotation javax.xml.namespace javax.xml.ws org.apache.cxf.bus org.apache.cxf.bus.spring org.apache.cxf.bus.resource org.apache.cxf.configuration.spring org.apache.cxf.resource org.apache.cxf.jaxws org.springframework.beans.factory.config
5.3.4. Maven 捆绑插件指令示例
例 5.1 “配置强制导入软件包” 演示了如何在 POM 中配置 Maven 捆绑包插件来导入强制软件包。必需的导入软件包在 Import-Package
元素中以逗号分隔的列表的形式出现。请注意通配符的外观,即 *
,作为列表的最后一个元素。通配符可确保扫描当前捆绑包中的 Java 源文件,以发现需要导入哪些额外软件包。
例 5.1. 配置强制导入软件包
<project ... > ... <build> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <extensions>true</extensions> <configuration> <instructions> ... <Import-Package> javax.jws, javax.wsdl, javax.xml.bind, javax.xml.bind.annotation, javax.xml.namespace, javax.xml.ws, org.apache.cxf.bus, org.apache.cxf.bus.spring, org.apache.cxf.bus.resource, org.apache.cxf.configuration.spring, org.apache.cxf.resource, org.apache.cxf.jaxws, org.springframework.beans.factory.config, * </Import-Package> ... </instructions> </configuration> </plugin> </plugins> </build> ... </project>
5.3.5. 添加代码生成插件
Web 服务项目通常需要生成代码。Apache CXF 为 JAX-WS 前端提供了两个 Maven 插件,它可让您将代码生成步骤集成到您的构建中。插件选择取决于您是否使用 Java 优先方法或 WSDL 优先方法开发您的服务,如下所示:
-
java -first 方法- 使用
cxf-java2ws-plugin
插件。 -
WSDL-first 方法- 使用
cxf-codegen-plugin
插件。
5.3.6. OSGi 配置属性
OSGi 配置管理服务定义了将配置设置传递给 OSGi 捆绑包的机制。您不必将此服务用于配置,但通常是配置捆绑包应用程序的最便捷方式。蓝图支持 OSGi 配置,可让您使用 OSGi 配置管理服务获得的值替换蓝图文件中的变量。
有关如何使用 OSGi 配置属性的详情,请参考 第 5.3.7 节 “配置捆绑包插件” 和 第 9.6 节 “向该功能添加 OSGi 配置”。
5.3.7. 配置捆绑包插件
概述
捆绑包插件需要很少的信息才能正常工作。所有必要属性都使用默认设置来生成有效的 OSGi 捆绑包。
虽然您只能使用默认值创建有效的捆绑包,但您可能需要修改一些值。您可以在插件的 instructions
元素中指定大多数属性。
配置属性
一些常用的配置属性是:
设置捆绑包的符号名称
默认情况下,捆绑包插件将 Bundle-SymbolicName
属性的值设置为 groupId + "." +
artifactId,但有以下例外:
如果 groupId 只有一个部分(没有点),则返回第一个带有类的软件包名称。
例如,如果组 Id 是
commons-logging:commons-logging
,则捆绑包的符号名称为org.apache.commons.logging
。如果 artifactId 等于 groupId 的最后部分,则使用 groupId。
例如,如果 POM 将组 ID 和工件 ID 指定为
org.apache.maven:maven
,则捆绑包的符号名称为org.apache.maven
。如果 artifactId 以 groupId 的最后部分开头,则会删除该部分。
例如,如果 POM 将组 ID 和工件 ID 指定为
org.apache.maven:maven-core
,则捆绑包的符号名称为org.apache.maven.core
。
要为捆绑包的符号名称指定您自己的值,请在插件的 instructions
元素中添加一个 Bundle-SymbolicName
子级,如 例 5.2 “设置捆绑包的符号名称” 所示。
例 5.2. 设置捆绑包的符号名称
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
...
</instructions>
</configuration>
</plugin>
设置捆绑包名称
默认情况下,捆绑包的名称设置为 ${project.name}
。
要为捆绑包的名称指定您自己的值,请在插件的 instructions
元素中添加一个 Bundle-Name
子对象,如 例 5.3 “设置捆绑包名称” 所示。
例 5.3. 设置捆绑包名称
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-Name>JoeFred</Bundle-Name>
...
</instructions>
</configuration>
</plugin>
设置捆绑包的版本
默认情况下,捆绑包的版本设置为 ${project.version}
。任何短划线(-
)替换为点(.
),数字会加到四位。例如,4.2-SNAPSHOT
变为 4.2.0.SNAPSHOT
。
要为捆绑包的版本指定您自己的值,请在插件的 instructions
元素中添加一个 Bundle-Version
子对象,如 例 5.4 “设置捆绑包的版本” 所示。
例 5.4. 设置捆绑包的版本
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-Version>1.0.3.1</Bundle-Version>
...
</instructions>
</configuration>
</plugin>
指定导出的软件包
默认情况下,OSGi 清单的 Export-Package
列表由您的本地 Java 源代码中的所有软件包填充(在 src/main/java
下),除了默认软件包.. 以及包含
.impl
或 .internal
的任何软件包。
如果您在插件配置中使用 Private-Package
元素,且您没有指定要导出的软件包列表,则默认行为仅包含捆绑包中 Private-Package
元素中列出的软件包。没有导出软件包。
默认行为可能会导致软件包非常大,并导出应保持私有的软件包。要更改导出的软件包列表,您可以在插件的 instructions
元素中添加 Export-Package
子子。
Export-Package
元素指定要包含在捆绑包中的软件包列表,以及要导出的软件包列表。可以使用 *
通配符符号指定软件包名称。例如,条目 com.fuse.demo
需要包括以 com.fuse.demo
开头的项目的 classpath 中的所有软件包。
您可以使用 !
指定要排除的软件包作为前缀。例如,条目 !com.fuse.demo.private
排除软件包 com.fuse.demo.private
。
在排除软件包时,列表中条目的顺序非常重要。从开始顺序处理列表,并忽略后续字典条目。
例如,要包含以 com.fuse.demo
开头的所有软件包,软件包 com.fuse.demo.private
除外,请使用以下方法列出软件包:
!com.fuse.demo.private,com.fuse.demo.*
但是,如果您使用 com.fuse.demofuse,!com.fuse.demo.private 列出软件包
,那么 com.fuse.demo.private
将包含在捆绑包中,因为它与第一个模式匹配。
指定私有软件包
如果要在 不 导出捆绑包中指定要包含的软件包列表,您可以在捆绑插件配置中添加 Private-Package
指令。默认情况下,如果您没有指定 Private-Package
指令,则捆绑包中包含本地 Java 源中的所有软件包。
如果软件包与 Private-Package
元素和 Export-Package
元素中的条目匹配,则 Export-Package
元素将具有优先权。软件包被添加到捆绑包中并导出。
Private
元素的工作方式与您要包含在捆绑包中的软件包列表类似。bundle 插件使用列表来查找要包含在捆绑包中的项目的 classpath 中的所有类。这些软件包打包在捆绑包中,但不会导出(除非它们也由 -Package
Export-Package
指令选择)。
例 5.5 “在捆绑包中包含私有软件包” 显示在捆绑包中包含私有软件包的配置
例 5.5. 在捆绑包中包含私有软件包
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Private-Package>org.apache.cxf.wsdlFirst.impl</Private-Package>
...
</instructions>
</configuration>
</plugin>
指定导入的软件包
默认情况下,捆绑包插件使用由捆绑包内容引用的所有软件包列表填充 OSGi 清单的 Import-Package
属性。
虽然默认行为通常足以满足大多数项目,但您可能会找到您想导入没有自动添加到列表中的软件包的实例。默认行为还会导致导入不需要的软件包。
要指定捆绑包要导入的软件包列表,请在插件的 instructions
元素中添加 Import-Package
子级。软件包列表的语法与 Export-Package
元素和 Private-Package
元素的语法相同。
使用 Import-Package
元素时,插件不会自动扫描捆绑包的内容,以确定是否有所需的导入。要确保扫描捆绑包的内容,您必须在软件包列表中放置一个 *
作为最后一个条目。
例 5.6 “指定捆绑包导入的软件包” 显示指定捆绑包导入的软件包的配置
例 5.6. 指定捆绑包导入的软件包
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Import-Package>javax.jws, javax.wsdl, org.apache.cxf.bus, org.apache.cxf.bus.spring, org.apache.cxf.bus.resource, org.apache.cxf.configuration.spring, org.apache.cxf.resource, org.springframework.beans.factory.config, * </Import-Package>
...
</instructions>
</configuration>
</plugin>
更多信息
有关配置捆绑包插件的更多信息,请参阅:
5.3.8. OSGI configAdmin 文件命名规则
PID 字符串(symbolic-name 语法)允许 OSGI 规格中的连字符。但是,连字符由 Apache Felix.fileinstall
和 config:edit
shell 命令解释,以区分"受管服务"和"受管服务工厂"。因此,建议您不要在 PID 字符串中使用连字符。
配置文件名称与 PID 和工厂 PID 相关。