我在 http://maven.apache.org/plugins/maven-ear-plugin/examples/skinny-wars.html 偶然发现了maven主题skinnyWars
。如前所述,我可以使用此方法将选定的依赖项从 WAR 模块移动到 EAR 模块。它们将可用于位于 EAR 中的所有其他 WAR 模块。
正如我所发现的那样,移动的依赖项必须在 EAR 模块中声明,并且必须包含在META-INFlib
目录中。这不适用于 EJB 模块,这些模块位于 EAR 模块的根目录中。
我的问题是如何从 WAR 中删除重复的 EJB 模块并将引用指向位于 EAR 文件中的模块?
现在的结构是这样的:
-EAR
-ejb.jar
-META-INFlib
-shared libraries
-web.war
-WEB-INFlib
-ejb.jar
-other non-shared libraries
我已经回答了一个类似的问题:如何让 maven 将所有战争通用的罐子放在同一个 EAR 到 EAR 根中?
不幸的是,这似乎不适用于 ejb 模块。正如您已经提到的,它们将被复制。
您还可以使用的一件事是 maven-war-plugin 的配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes>
</configuration>
</plugin>
这将完全删除 WAR 的 lib 文件夹中的所有内容,但在您必须在没有周围 EAR 的情况下将 WAR 本身另外部署到单独的机器上,它也可能有其缺点。
这里的问题是,从将用于将其部署到服务器的 ear 模块引用 EJB 与从需要 EJB 类与服务器接口的客户端引用 EJB 是不一样的。
如果在 ear 模块中包含依赖关系,它将认为您正在声明要部署的 EJB 模块。它会将其放在 EAR 的根目录中,并在应用程序中声明它.xml。
例如,如果你在war模块中包含依赖关系,你将得到完全相同的工件,但它将被视为一个库并放置在WEB-INF/lib中。
现在,当你生成瘦战争时,对 ejb 模块的显式依赖与 WAR 中的依赖不匹配,因为 Maven 不认为它们是一回事。这导致JAR被保存在使用它的WAR/s中。
我知道的唯一解决方案是始终为 ejb 模块生成客户端工件,即使客户端工件与主工件相同。
现在,您只需在 EAR 中使用<type>ejb</type>
依赖项。对于客户端,您始终使用<type>ejb-client</type>
客户端。
要从 WAR/s 中删除客户端并将其定位在 EAR 的 lib 目录中,您必须将依赖项显式添加到 ear 模块。
因此,在 ear 模块中,您将有两个对 ejb 模块的依赖关系:一个是 ejb 本身的依赖项,另一个是客户端的依赖项。第一个将 EJB 放在 EAR 的根目录中,并在应用程序中声明它.xml。第二个会将客户端放在 EAR 的 lib 目录中,并在必要时更新 WAR/s 清单。
但是,如果客户端和主工件相同,您会复制它吗?
简短的回答是肯定的。长答案是肯定的。它确实会被复制,但只有一次,而不是在每次使用它的 WAR 中。我认为没有一种干净的方法来避免这种情况,我不确定它在概念上是否有意义。当然,您可以使用打包排除和自定义清单,但拥有两次 JAR 是有意义的。
如果您的客户端 JAR 确实更薄(例如,只有接口(,则客户端 JAR 引用 WAR/s 实际上不允许它们访问 EJB 实现,这始终是一个好主意。
您可以将相同的 JAR 视为前一个 JAR 的特例,将它们分开在概念上是有意义的。
因此,我的建议是始终为 ejb 生成一个客户端工件,并按照说明进行操作。总有一些东西你可以从中排除,至少是任何不需要的非类文件,如package.html或ejb-jar.xml。