Maven资源插件设置为不同的阶段

3
我正在尝试强制执行 maven-resources-plugin 以进行不同阶段的操作,如下所示:
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>2.6</version>
    <executions>
        <execution>
            <id>copy-resources</id>
            <phase>test</phase>
            ...

我在日志中看到这个插件是在我的maven-compiler-plugin:2.3.2:compile之前首先执行的:

[INFO] --- maven-resources-plugin:2.6:resources (default-resources)
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource

这是为什么呢? (我以上内容的基础是这份文档:http://maven.apache.org/plugins/maven-resources-plugin/examples/copy-resources.html)
我还是不太明白。我将描述一下我问题的根本原因。我的任务如下:
  1. maven-war-plugin 在编译阶段生成WAR文件 (<phase>compile</phase>)
  2. maven-resources-plugin 我想在此处强制执行
  3. checksum-maven-plugin 在打包阶段为我生成一个校验和文件 (<phase>package</phase>)。
通常情况下,由于观察到maven-resources-pluginwar被创建之前就已经执行了,所以我无法达到这个目的。我想把这个插件放到test阶段。但你有什么建议?哪个阶段更合适?应该怎么做?
潜在问题的描述。我想提供两个文件作为应用程序:
  • WAR文件。
  • JAR文件,用于在部署之前通过校验和验证WAR文件。

关于您的编辑,正如我在我的答案中指定的那样,没有“强制插件”这样的东西。给定插件的给定目标(每个插件可以有多个)可以在构建中执行多次,每次都有独立的配置。一个目标的例子是maven-resources-plugin:resources,它表示来自maven-resources-plugin插件的resources目标。就像我说的那样,重新排列默认值可能会搞乱你的构建。你想要实现什么? - mikołak
我有两个由Maven创建的目标文件。一个是WAR,另一个是部署WAR的JAR。我尝试向JAR文件添加一些校验和文件,以便在执行时验证WAR。 - Knight of Ni
WAR是否应包含在JAR中? - mikołak
maven-war-plugin 会在 target 目录下生成 WAR 文件。不确定如何将其添加到 JAR 文件中。这可能会解决我的问题(我可以跳过校验和计算)。 - Knight of Ni
2个回答

5

因为父POM或生命周期规范中定义了此插件的目标的另一个执行过程。

在您的项目目录中检查mvn help:effective-pom,您将看到您的POM实际上是什么样子的。

听起来你认为插件执行过程是这样的:“这是我想要执行插件的地方,只有这里”。

然而,它实际上更像是这样的:“我正在定义这个执行过程。这个执行过程应该在以下阶段完成,并且在此配置下的这些插件目标将被执行。哦,还有一个ID供你使用,因为你说你需要它。”

换句话说:插件执行过程不是专属于一个插件,甚至不是一个插件目标

然而,正如rec正确指出的那样,您可以通过指定具有相同ID的自己的执行来覆盖父POM设置的插件执行设置。再次检查Effective POM以查找这些ID。目前,对于Maven 3,在JAR打包类型中有两个“预定义”的resources插件执行:default-resourcesdefault-testResources

请注意,这不是您通常应该为resources插件执行的操作,因为这可能会破坏您的构建。


编辑:在您的情况下,很明显您的项目有两个部分:

  • 一个包含一些应用程序的WAR文件,
  • 一个将您的WAR文件部署到某个容器中的JAR文件。

Maven与make不同(以我的理解),它将构建过程与构件解耦。换句话说,您应该创建两个项目:一个使用WAR打包,另一个使用JAR打包。后者应该将WAR包复制到其JAR中。此外还有所谓的多模块项目

具体而言,您可以执行以下操作:

  1. Separate the project into two: the one building the JAR and the one building the WAR.
  2. Create the multi-module project that specifies the other two as modules. The JAR project should be after the WAR project. You can set the multi-module project as a parent to the other two, it will let you to synchronize versions and other configuration.
  3. In your JAR project, add a plugin goal execution that copies the WAR to your package. You can use the dependency:copy goal for this, e.g.:

    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.8</version>
    <executions>
      <execution>
        <id>copy-war</id>
        <phase>generate-resources</phase>
        <goals>
          <goal>copy</goal>
        </goals>
        <configuration>
          <artifactItems>
            <artifactItem>
              <groupId>[your-war-group-id]</groupId>
              <artifactId>[your-war-artifact-id]</artifactId>
              <version>${project.version}</version>
              <type>war</type>
              <overWrite>true</overWrite>
              <outputDirectory>${basedir}/src/main/resources</outputDirectory>
              <destFileName>install.war</destFileName>
            </artifactItem>
          </artifactItems>
        </configuration>
      </execution>
    </executions>
    </plugin>
    

    (an alternative is to specify the package as a dependency and use the assembly plugin)

  4. Run the build for the multi-module project with the install target. You need install because it ensures that the latest version of the WAR project will find its way into your local m2 repository, for the JAR project to pick up.

你可以跳过多模块部分,直接创建两个独立的项目。但是,在这种情况下,每当前者发生更改时,你需要手动运行WAR项目的install目标,然后再运行JAR项目的package

1
你忘了提到一个关键点:如果你知道ID,那么你可以在相同的ID下重新定义执行,基本上是覆盖之前或默认的定义。 - rec
1
@flyer:是的,不过请注意,在您的示例中,您正在定义一个新的执行,而不是覆盖任何内容(至少不是来自打包配置的内容)。 - mikołak
我认为我可以通过GNU make的经验来筛选Maven机制。也许我应该设置一些“依赖项”而不是重新定义“阶段”? - Knight of Ni
@flyer:很难猜测。现在已经明显有一些潜在问题需要你解决。请编辑你的问题,明确指定你想要做什么(而不是你认为哪里出了问题),否则恐怕帮助你会很困难。 - mikołak
@flyer:copy目标会从你的Maven仓库中复制给定的构件,因此首先必须存在于那里。除此之外,很难确定问题的具体原因。如果你遇到困难,我建议你提出另一个相关的问题来寻求帮助。 - mikołak
显示剩余5条评论

1
你提到了两个不同的目标:copy-resourcesresources。对于大多数打包类型,后者绑定到process-resources阶段。这是您在日志中看到的阶段。 要在test阶段执行copy-resources,还需要添加。
<goals>
  <goal>copy-resources</goal>
</goals>

因此,您也可以在这里阅读它。

根据我的观察,maven-resources-plugin在我的“编译”之前执行。这可能是真的吗?为什么要提到“资源”? - Knight of Ni
1
你必须理解插件和目标之间的区别:插件是目标的集合,它们彼此属于。maven-resource-plugin 有三个目标:resourcestestResourcescopy-resources。(还有一个 help 目标)。你不能将插件绑定到阶段,只能将目标绑定到阶段。resources 目标绑定到 process-resources 阶段,该阶段在 compile 阶段之前。 - Robert Scholte
是的!你读懂了我的想法,对吗? :) 恰恰是我认为这个阶段在某个时间点(在其他阶段之间)生成目标... - Knight of Ni
1
对于每种打包类型(jar、war、ear),都绑定了一组预定义的目标到特定的阶段。开发人员可以将更多的目标绑定到阶段中。为此,请将插件添加到pom文件的“plugins”部分,并定义应执行哪个目标。现在重要的部分:有些目标已经配置了默认阶段。如果您喜欢该阶段,请保持不变。否则,在所有其他情况下,指定需要执行此目标的阶段。 - Robert Scholte

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接