使用Maven复制文件的最佳做法

时间:2009-02-25 14:38:01

标签: maven maven-2 build-process release-management

我有使用Maven2从dev环境复制到dev-server目录的配置文件和各种文档。奇怪的是,Maven在这项任务中看起来并不强大。


一些选项:

  • 在Maven中简单使用 copy 任务
  

<copy file="src/main/resources/config.properties" tofile="${project.server.config}/config.properties"/>

  • 使用Ant插件从Ant执行 copy

  • 构造一个 zip 类型的工件,以及POM的“主”工件,通常是 jar 类型,然后 unpack 该工件从存储库到目标目录。

  • maven-resources 插件,如下所述。

  • Maven程序集插件 - 但这似乎需要大量的手动定义,当我想简单地执行“常规”时。

  • This page甚至展示了如何构建一个插件来进行复制!

  • maven-upload 插件,如下所述。

  • maven-dependency-plugin copy ,如下所述。


所有这些看起来都是不必要的:Maven应该擅长完成这些标准任务,而不用大惊小怪。

有什么建议吗?

14 个答案:

答案 0 :(得分:131)

<build>
    <plugins>
        ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.3</version>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include> **/*.properties</include>
            </includes>
        </resource>
    </resources>
    ...
</build>

答案 1 :(得分:109)

不要回避Antrun插件。仅仅因为有些人倾向于认为Ant和Maven是对立的,他们不是。如果您需要执行一些不可避免的一次性自定义,请使用复制任务:

<project>
  [...]
  <build>
    <plugins>
      [...]
      <plugin>
        <artifactId>maven-antrun-plugin</artifactId>
        <executions>
          <execution>
            <phase>deploy</phase>
            <configuration>
              <tasks>

                <!--
                  Place any Ant task here. You can add anything
                  you can add between <target> and </target> in a
                  build.xml.
                -->

              </tasks>
            </configuration>
            <goals>
              <goal>run</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  [...]
</project>

在回答这个问题时,我会关注你所问的细节。如何复制文件?问题和变量名称引出了一个更大的问题,例如:“有没有更好的方法来处理服务器配置?”使用Maven作为构建系统来生成可部署工件,然后在单独的模块中或完全在其他位置执行这些自定义。如果您分享了更多的构建环境,可能有更好的方法 - 有插件来配置多个服务器。你能附加一个在服务器根目录中解压缩的程序集吗?你用的是什么服务器?

同样,我确信有更好的方法。

答案 2 :(得分:29)

要复制文件,请使用:

        <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.7</version>
            <executions>
                <execution>
                    <id>copy-resource-one</id>
                    <phase>install</phase>
                    <goals>
                        <goal>copy-resources</goal>
                    </goals>

                    <configuration>
                        <outputDirectory>${basedir}/destination-folder</outputDirectory>
                        <resources>
                            <resource>
                                <directory>/source-folder</directory>
                                <includes>
                                    <include>file.jar</include>
                                </includes>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
           </executions>
        </plugin>

要使用子文件夹复制文件夹,请使用下一个配置:

           <configuration>
              <outputDirectory>${basedir}/target-folder</outputDirectory>
              <resources>          
                <resource>
                  <directory>/source-folder</directory>
                  <filtering>true</filtering>
                </resource>
              </resources>              
            </configuration>  

答案 3 :(得分:18)

maven依赖插件让我花了很多时间来处理蚂蚁任务:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>install-jar</id>
            <phase>install</phase>
            <goals>
                <goal>copy</goal>
            </goals>
            <configuration>
                <artifactItems>
                    <artifactItem>
                        <groupId>...</groupId>
                        <artifactId>...</artifactId>
                        <version>...</version>
                    </artifactItem>
                </artifactItems>
                <outputDirectory>...</outputDirectory>
                <stripVersion>true</stripVersion>
            </configuration>
        </execution>
    </executions>
</plugin>

dependency:copy是文档,并且有更多有用的目标,比如解包。

答案 4 :(得分:15)

对于简单的复制任务,我可以推荐copy-rename-maven-plugin。它直截了当且易于使用:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>com.coderplus.maven.plugins</groupId>
        <artifactId>copy-rename-maven-plugin</artifactId>
        <version>1.0</version>
        <executions>
          <execution>
            <id>copy-file</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>copy</goal>
            </goals>
            <configuration>
              <sourceFile>src/someDirectory/test.environment.properties</sourceFile>
              <destinationFile>target/someDir/environment.properties</destinationFile>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

如果您要复制多个文件,请将<sourceFile>...</destinationFile>部分替换为

<fileSets>
  <fileSet>
    <sourceFile>src/someDirectory/test.environment.properties</sourceFile>
    <destinationFile>target/someDir/environment.properties</destinationFile>
  </fileSet>
  <fileSet>
    <sourceFile>src/someDirectory/test.logback.xml</sourceFile>
    <destinationFile>target/someDir/logback.xml</destinationFile>
  </fileSet>                
</fileSets>

此外,如果需要,您可以在多个阶段指定多个执行,第二个目标是&#34;重命名&#34;,它只是执行它所说的,而其余配置保持不变。有关更多用法示例,请参阅Usage-Page

注意:此插件只能复制文件,而不能复制目录。 (感谢@ james.garriss找到这个限制。)

答案 5 :(得分:6)

上面的ant解决方案最容易配置,但我很幸运使用了Atlassian的maven-upload-plugin。我无法找到好的文档,这是我如何使用它:

<build>
  <plugin>
    <groupId>com.atlassian.maven.plugins</groupId>
    <artifactId>maven-upload-plugin</artifactId>
    <version>1.1</version>
    <configuration>
       <resourceSrc>
             ${project.build.directory}/${project.build.finalName}.${project.packaging}
       </resourceSrc>
       <resourceDest>${jboss.deployDir}</resourceDest>
       <serverId>${jboss.host}</serverId>
       <url>${jboss.deployUrl}</url>
     </configuration>
  </plugin>
</build>

上面引用的“$ {jboss.host}”等变量在我的〜/ .m2 / settings.xml中定义,并使用maven配置文件激活。这个解决方案不仅限于JBoss,这正是我命名的变量。我有dev,test和live的个人资料。因此,为了将我的耳朵上传到测试环境中的jboss实例,我将执行:

mvn upload:upload -P test

这是来自settings.xml的snipet:

<server>
  <id>localhost</id>
  <username>username</username>
  <password>{Pz+6YRsDJ8dUJD7XE8=} an encrypted password. Supported since maven 2.1</password>
</server>
...
<profiles>
  <profile>
    <id>dev</id>
    <properties>
      <jboss.host>localhost</jboss.host> 
      <jboss.deployDir>/opt/jboss/server/default/deploy/</jboss.deployDir>
      <jboss.deployUrl>scp://root@localhost</jboss.deployUrl>
    </properties>
  </profile>
  <profile>
    <id>test</id>
    <properties>
       <jboss.host>testserver</jboss.host>
       ...

注意: 拥有此插件的Atlassian maven repo位于:https://maven.atlassian.com/public/

我建议下载源代码并查看里面的文档,以查看该插件提供的所有功能。

`

答案 6 :(得分:5)

嗯,maven不应该做好细粒度的任务,它不是像bash或ant这样的脚本语言,而是声明性的 - 你说 - 我需要一场战争,或者一个耳朵,你得到它。但是,如果您需要自定义战争或耳朵在内部的样子,那么您就会遇到问题。它不像蚂蚁那样程序化,而是声明性的。 这在一开始就有一些优点,最终会有很多缺点。

我想最初的概念是拥有精美的插件,“只是工作”,但如果你做非标准的东西,现实是不同的。

如果你在你的poms和很少的自定义插件中投入了足够的精力,那么你将获得一个更好的构建环境,例如蚂蚁(当然取决于你的项目,但对于更大的项目它会变得越来越真实)

答案 7 :(得分:4)

我对copy-maven-plugin有很好的体验。与maven-resources-plugin相比,它具有更方便,更简洁的语法。

答案 8 :(得分:4)

复制任意文件的一般方法是利用Maven Wagon传输抽象。它可以通过fileHTTPFTPSCPWebDAV等协议处理各种目的地。

有一些插件提供了通过Wagon复制文件的功能。最值得注意的是:

  • 开箱即用的Maven Deploy Plugin

    deploy-file目标。它非常不灵活但可以完成工作:

    mvn deploy:deploy-file -Dfile=/path/to/your/file.ext -DgroupId=foo 
    -DartifactId=bar -Dversion=1.0 -Durl=<url> -DgeneratePom=false
    

    使用Maven Deploy Plugin的重大缺点是它被指定与Maven存储库一起使用。它假设特定的结构和元数据。您可以看到该文件位于foo/bar/1.0/file-1.0.ext下,并创建了校验和文件。没有办法解决这个问题。

  • Wagon Maven Plugin

    使用upload-single goal

    mvn org.codehaus.mojo:wagon-maven-plugin:upload-single
    -Dwagon.fromFile=/path/to/your/file.ext -Dwagon.url=<url>
    

    使用Wagon Maven Plugin进行复制很简单,似乎是最通用的。


在上面的示例中,<url>可以是任何支持的协议。查看现有Wagon Providers列表。例如

  • 在本地复制文件:file:///copy/to
  • 将文件复制到运行SSH的远程主机:scp://host:22/copy/to


上面的示例在命令行中传递插件参数。或者,可以在POM中直接配置插件。然后调用就像mvn deploy:deploy-file@configured-execution-id一样。或者它可以绑定到特定的构建阶段。


请注意,要使SCP等协议生效,您需要在POM中定义一个扩展程序:

<build>
  [...]
  <extensions>
    <extension>
      <groupId>org.apache.maven.wagon</groupId>
      <artifactId>wagon-ssh</artifactId>
      <version>2.12</version>
    </extension>
  </extensions>


如果要复制的目标位置需要身份验证,则可以通过Server settings提供凭据。传递给插件的repositoryId / serverId必须与设置中定义的服务器匹配。

答案 9 :(得分:3)

我只能假设您的$ {project.server.config}属性是自定义的,并且不在标准目录布局中。

如果是,那么我将使用复制任务。

答案 10 :(得分:2)

另一种方法是使用程序集插件将这些东西捆绑到工件中。然后,您可以使用依赖项插件将这些文件解压缩到您想要的位置。依赖插件中还有复制目标来复制工件。

答案 11 :(得分:1)

我能够为这个答案拼凑出许多不同的来源:

...
<repository>
    <id>atlassian</id>
    <name>Atlassian Repo</name>
    <url>https://maven.atlassian.com/content/repositories/atlassian-public</url>
</repository>
...
<dependency>
    <groupId>com.atlassian.maven.plugins</groupId>
    <artifactId>maven-upload-plugin</artifactId>
    <version>1.1</version>
</dependency>
...
<plugin>
    <groupId>com.atlassian.maven.plugins</groupId>
    <artifactId>maven-upload-plugin</artifactId>
    <version>1.1</version>
    <configuration>
        <serverId>jira-repo</serverId>
        <resourceSrc>
            ${project.build.directory}/${project.build.finalName}.${project.packaging}
        </resourceSrc>
        <resourceDest>opt/jira/webapps</resourceDest> <!-- note: no leading slash -->
        <url>scp://root@jira</url>
    </configuration>
</plugin>
...

来自~/.m2/settings.xml

...
<servers>
  <server>
    <id>jira-repo</id>
    <username>myusername</username>
    <password>mypassword</password>
  </server>
</servers>
...

然后运行命令:( -X用于调试)

mvn -X upload:upload

答案 12 :(得分:0)

如果有人想要完全控制源路径和目标路径,那么使用 maven-antrun-plugincopy 任务是最好的选择。这种方法将允许您在系统上的任何路径之间进行复制,而不管相关路径是否在 mvn 项目中。我遇到过一些不寻常的事情,例如将生成的源文件从 target 目录复制回 src 目录以进行进一步处理。在我的情况下,这是唯一可以毫不费力地工作的选择。来自 pom.xml 的示例代码片段:

<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-antrun-plugin</artifactId>
        <version>1.8</version>
        <executions>
            <execution>
                <phase>process-resources</phase>
                <configuration>
                <tasks>
                    <copy file="${basedir}/target/myome/minifyJsSrcDir/myome.min.js" todir="${basedir}/src/main/webapp/app/minifyJsSrcDir"/>
                </tasks>
                </configuration>
                <goals>
                <goal>run</goal>
                </goals>
            </execution>
        </executions>
</plugin>

答案 13 :(得分:-1)

总结一些上面的好答案: Maven 旨在构建模块并将结果复制到Maven存储库。将模块复制到部署/安装程序输入目录必须在Maven核心功能的上下文之外完成,例如,使用Ant / Maven 复制命令。