【问题标题】:Using profiles in multimodule project在多模块项目中使用配置文件
【发布时间】:2012-08-13 19:06:52
【问题描述】:

我有一个多模块 Maven 项目。项目布局描述如下:

PARENT
  |-CHILD1
  |-CHILD2

父项目具有 pom 打包类型,并将 CHILD1CHILD2 项目声明为模块。 PARENT 项目还声明了配置文件 dev,它声明了一些属性。 CHILD1 项目具有 jar 包装类型,并通过添加一些依赖项(例如对 commons-collections 的依赖项)“覆盖”PARENT dev 配置文件。 CHILD2 项目具有战争包装类型,并依赖于 CHILD1 项目。此外,CHILD2 通过添加另一个依赖项“覆盖”父 dev 配置文件(例如,commons-io 上的依赖项,我的意思是与项目 CHILD1 中的那个不相关的依赖项)。 然后,当我运行 mvn clean install -Pdev 时,maven 不会将 commons-collections.jar(在 CHILD1 项目中声明的依赖项)放到 CHILD2 项目的 WEB-INF/lib 中,但是 commons-io.jar 在那里。

所以,问题是:如果目标项目在该配置文件中声明了另一组依赖项,为什么 maven 不从在目标项目的依赖项目中声明的配置文件中放置依赖项?

实际上,我有更多的项目和更多的依赖项,这些依赖项在不同的配置文件中有所不同。我想在该项目 pom.xml 中声明项目特定的依赖项(假设在项目中声明配置文件将“覆盖”父配置文件声明)

【问题讨论】:

  • 使用配置文件添加依赖项是主要的反模式,在原始 POM 格式规范中不应被允许。
  • 在不同profile需要不同依赖的情况下如何操作?我需要在一些配置文件中排除一些依赖项
  • 使用不同的模块和 webapp 覆盖通过配置文件将模块添加到反应器中。 IOW 您将拥有三个或四个 webapp 模块,除了一个之外,所有模块都是“空的”,仅依赖于基础 webapp 和您需要的其他依赖项
  • 您需要记住,当工件被部署到存储库时,您会丢失活动的配置文件信息,因此从存储库中拉取依赖项的消费者不会拉取通过profile (除非他们碰巧有一个同名的 profile 处于活动状态)所以你真的需要单独的工件来拥有单独的依赖关系
  • 所以,我必须为每个配置文件创建一个项目,我的意思是如果一个模块的依赖项在配置文件中有所不同,我必须创建该模块的子模块并向该模块添加特定的依赖项(没有源的模块和资源,仅声明依赖项)并在模块中仅声明公共依赖项?

标签: maven-3 maven-profiles


【解决方案1】:

我假设您希望能够在开发时进行本地测试,针对暂存环境测试您的更改并最终部署到生产环境。

您需要记住的关键是,当工件被部署到本地/远程存储库时,活动配置文件不是部署内容的一部分,因此当您通过配置文件添加依赖项时,事情变得非常危险,因为你无法知道 webapp 是在 DEV 配置文件激活还是 PROD 配置文件激活的情况下构建的,然后当构建的工件部署到生产环境中时,你可能会被彻底搞砸。

因此,这样做的不足是确保您的工件独立于部署环境。

这意味着,例如,您将从以下位置获取配置:

  • 类路径中的文件
  • 系统属性
  • jndi 条目

例如,如果部署到 Tomcat,您可以将 configuration.properties 放入 $CATALINA_HOME/lib

您的 webapp 在启动时将使用 getClass().getResource('/configuration.properties') 来解析属性文件,如果文件丢失,则无法启动(快速失败)

您可以通过将 configuration.properties 的测试版本放入 src/test/resources 来让您的单元/集成测试使用不同的配置。

您对应用程序的<scope>provided</scope> 样式依赖项使用相同的原则。换句话说,容器与提供的契约签订的依赖关系应该由容器提供。因此,您也可以使用 Maven 为自己构建 tomcat/jetty 的生产版本,并将所需的依赖项添加到该程序集中。这就像生产版本使用 MySQL 数据库一样,因此您需要将 mysql-jdbc 驱动程序添加到$CATALINA_HOME/lib。使用程序集插件执行此操作相对容易,因为您实际上只是重新打包一个包含一些位和排除其他位的 zip。

在本地测试时,您将需要使用辅助插件的run 目标,例如jetty:runtomcat:run。这里的解决方案是通过配置文件给这些插件依赖关系没有任何问题因为你没有影响工件的依赖关系你只是影响了插件的类路径。

例如

<project>
  <!-- ... some stuff .. -->
  <profiles>
     <profile>
       <id>DEV</id>
       <build>
         <plugins>
           <plugin>
             <groupId>org.mortbay.jetty</groupId>
             <artifactId>jetty-maven-plugin</artifactId>
             <dependencies>
               <dependency>
                 <groupId>commons-dbcp</groupId>
                 <artifactId>commons-dbcp</artifactId>
                 <version>1.4</version>
               </dependency>
               <dependency>
                 <groupId>mysql</groupId>
                 <artifactId>mysql-connector-java</artifactId>
                 <version>5.1.18</version>
               </dependency>
             </dependencies>
           </plugin>
         </plugins>
       </build>
     </profile>
   </profiles>
 </project>

您还可以配置系统属性或类路径添加以拉入所需的配置文件。

所有这一切的最终结果是工件保持环境独立,您可以轻松地针对各种环境进行测试

希望这能回答你的问题(即使是横向)

【讨论】:

  • 它不依赖于环境。我只是想排除一些依赖项或提供没有一些传递的依赖项,或者根据(例如)maven build 命令的输入参数提供具有不同范围的依赖项。为了向工件提供有关配置文件的信息,我可以使用分类器并在不同的配置文件中激活它(分类器)。所以问题仍然存在
  • 分类器与主要工件具有相同的依赖关系,因此分类器是错误的解决方案。 Maven 固执己见,你正在尝试做一些它坚信是“坏事”的事情,所以最终结果是你会一直与之抗争......祝你好运......祝你好运 6 个月后尝试弄清楚你做了什么!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-16
  • 2020-03-01
  • 2011-09-03
  • 2012-02-14
  • 2017-09-21
  • 1970-01-01
  • 2015-09-07
相关资源
最近更新 更多