使用Maven复制文件的最佳实践

我有一些配置文件和各种文档,我想使用Maven2将它们从开发环境复制到dev-server目录。奇怪的是,Maven在这项任务上似乎并不强大。

以下是一些选项:

  • 在Maven中简单地使用复制任务
<copy file="src/main/resources/config.properties" tofile="${project.server.config}/config.properties"/>
  • 使用Ant插件从Ant执行复制

    • 构造一个类型为zip的工件,与POM的“主要”工件一起,通常类型为jar,然后解包,该工件从存储库到目标目录。

    • maven-resources plugin,如下所述。

    • Maven Assembly插件——但这似乎需要大量的手动定义,当我想简单地和“常规地”做事情时。

    • 本页甚至展示了如何构建一个插件来做复制!

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

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

    • 李< / ul > < / >
    < p > < br > 所有这些似乎都是不必要的特别任务:Maven应该擅长于毫不费力地完成这些标准任务。< / p >

    任何建议吗?

338621 次浏览

我只能假设你的${project.server. server。Config}属性是自定义的,并且在标准目录布局之外。

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

好吧,maven不应该擅长做细粒度的任务,它不像bash或ant那样是一种脚本语言,它是一种声明性的语言——你说——我需要一场战争,或者一个耳朵,然后你得到了它。然而,如果你需要自定义战争或耳朵应该看起来像内部,你有一个问题。它不像ant那样是程序性的,而是声明性的。 这在一开始有一些好处,但到最后可能会有很多坏处。< / p >

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

然而,如果你在poms上投入足够的精力和少量的自定义插件,你会得到一个更好的构建环境,比如ant(当然这取决于你的项目,但对于更大的项目来说越来越正确)。

不要回避Antrun插件。仅仅因为有些人倾向于认为Ant和Maven是对立的,但事实并非如此。如果你需要执行一些不可避免的一次性定制,请使用copy任务:

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


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


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

在回答这个问题时,我主要是针对你所提问题的细节。如何复制文件?这个问题和变量名让我想到了一个更大的问题,比如:“有没有更好的方法来处理服务器配置?”使用Maven作为构建系统来生成可部署的工件,然后在单独的模块中或完全在其他地方执行这些定制。如果你多分享一点你的构建环境,可能会有更好的方法——有一些插件可以提供一些服务器。您能否附加在服务器根目录中解包的程序集?您使用的服务器是什么?

再说一次,我相信有更好的办法。

另一种方法是使用汇编插件将这些东西捆绑到工件中。然后你可以使用依赖插件在你想要的地方解包这些文件。在依赖插件中也有复制目标来复制工件。

上面的蚂蚁解决方案是最容易配置的,但我有幸使用了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,这只是我给变量命名的方式。我有开发,测试和现场的资料。因此,要在测试环境中上传我的耳朵到jboss实例,我将执行:

mvn upload:upload -P test

下面是settings.xml的一个片段:

<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>
...
< p >指出: 有这个插件的Atlassian maven repo在这里:https://maven.atlassian.com/public/

我建议下载源代码,并查看其中的文档,以了解插件提供的所有功能。

<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>

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

我能够拼凑出一些不同的来源来回答这个问题:

...
<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

maven依赖插件为我节省了大量处理ant任务的时间:

<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>

依赖:副本是documentend,有更多有用的目标,比如解包。

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

为了复制一个文件使用:

        <plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</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>

对于简单的复制任务,我可以推荐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>

此外,如果需要,您可以在多个阶段指定多个执行,第二个目标是“重命名”,它只是做它所说的,而其余配置保持不变。有关更多用法示例,请参考用法页面

请注意:这个插件只能复制文件,不能复制目录。(感谢@james。Garriss发现了这一局限性。)

复制任意文件的通用方法是利用Maven马车传输抽象。它可以通过诸如fileHTTPFTPSCPWebDAV之类的协议来处理各种目的地。

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

  • < h3 >的开箱即用Maven部署插件

    这里有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下,并且校验和文件被创建。

  • < h3 > 货车Maven插件

    使用upload-single目标:

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

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

< p >
在上面的例子中,<url>可以是任何支持的协议。查看现有的车供应商列表。例如< / p >
  • 在本地复制文件:file:///copy/to
  • 将文件复制到运行SSH的远程主机:scp://host:22/copy/to
< p >
上面的例子在命令行中传递插件参数。或者,插件可以直接在POM中配置。然后调用将简单地像mvn deploy:deploy-file@configured-execution-id一样。或者它可以绑定到特定的构建阶段 < p >
请注意,像SCP这样的协议要工作,你需要在你的POM中定义一个扩展:

<build>
[...]
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>2.12</version>
</extension>
</extensions>
< p >
如果要复制到的目标需要身份验证,则可以通过Server设置提供凭据。传递给插件的repositoryId/serverId必须与设置中定义的服务器匹配

如果有人想要完全控制源路径和目标路径的路径,那么使用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>