【问题标题】:Using Maven for deployment使用 Maven 进行部署
【发布时间】:2010-11-27 05:15:01
【问题描述】:

我有这个使用 Maven 的包含 4 个嵌套子项目的项目的任务:

  1. 对于每个子项:jar-up 资源目录,包括项目依赖项
  2. 上移到父项目
  3. 使用单个命令将所有创建的档案提取到各种远程目标(完整安装),其中可能包括 http 服务器、应用程序服务器、文件服务器等(主要是 *NIX)。目的地在子项目级别提供
  4. 还应该可以从单个子项目中解压缩/复制(部分安装)

文件不是 Java - 主要是各种脚本和 HTML

我正在查看各种插件来帮助完成任务:程序集、依赖项、antrun、解压缩。依赖项看起来很有希望,但我不仅需要解压缩依赖项 jar,还需要解压缩(子)项目内容。另外,由于我不能真正将操作严格限制在 Maven 生命周期中,我将如何触发远程安装? mvn 依赖:解压?这不是很具有描述性或直观性。是否可以在不编写插件的情况下创建自定义目标(例如项目:安装)?

使用 Maven 是公司的标准,所以请不要提供替代方案 - 我几乎被我所拥有的东西所困扰

【问题讨论】:

  • 哈哈。我希望我在公司里被 Maven“困住”。
  • 我没有贬义的意思:)
  • 我不明白“在子项目级别提供目标”是什么意思。您是否将所有文件传送到每个目的地?
  • 4 个子项目。一个部署到 http 服务器,另外 3 个部署到一个不同的文件服务器。目标设置在子 POM 中提供
  • 所以一个子项目中的所有文件都交付到一个目的地

标签: deployment maven-2


【解决方案1】:

好的,我认为以下内容可能会满足您的需求。这种方法的缺点是在执行后续构建时,每次部署之间会有一个间隔。这可以接受吗?

在每个项目中定义一个具有相同名称的配置文件(例如“发布”)。在该配置文件中,您可以定义配置以使用 antrun-plugin 通过 FTP 传送文件(见下文)。

在父项目中,您将拥有一个 modules 元素,将每个项目定义为一个模块。如果您运行mvn install -P publish,每个项目将在启用发布配置文件的情况下依次构建,并在安装阶段将最终工件发布到目标。如果您需要部署额外的文件,请相应地修改包含element

请注意,FTP 任务的参数已设置为属性,这允许它们从命令行覆盖和/或从父 POM 继承。

<profiles>
  <profile>
    <id>publish</id>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-antrun-plugin</artifactId>
      <executions>
        <execution>
          <id>ftp</id>
          <phase>install</phase>
          <configuration>
            <tasks>
              <ftp action="send" 
                  server="${ftp.host}" remotedir="${ftp.remotedir}" 
                  userid="${ftp.userid}" password="${ftp.password}" 
                  depends="${ftp.depends}" verbose="${ftp.verbose}">
                <fileset dir="${project.build.directory}">
                  <include 
                    name="${project.build.finalName}.${project.packaging}"/>
                </fileset>
              </ftp>
            </tasks>
          </configuration>
          <goals>
            <goal>run</goal>
          </goals>
        </execution>
      </executions>
      <dependencies>
        <dependency>
          <groupId>commons-net</groupId>
          <artifactId>commons-net</artifactId>
          <version>1.4.1</version>
        </dependency>
        <dependency>
          <groupId>ant</groupId>
          <artifactId>ant-commons-net</artifactId>
          <version>1.6.5</version>
        </dependency>
        <dependency>
          <groupId>ant</groupId>
          <artifactId>ant-nodeps</artifactId>
          <version>1.6.5</version>
        </dependency>
      </dependencies>
    </plugin>
    <properties>
      <ftp.host>hostname</ftp.host>
      <ftp.remotedir>/opt/path/to/install</ftp.remotedir>
      <ftp.userid>user</ftp.userid>
      <ftp.password>mypassword</ftp.password>
      <ftp.depends>yes</ftp.depends>
      <ftp.verbose>no</ftp.verbose>          
    </properties>
  </profile>
</profiles>

更新:根据您的评论:您可以使用依赖插件下载每个依赖项,除了父级不能对子级有依赖项,它将在子级之前构建。这必须是另一个项目。您还需要在某处了解将它们部署到何处的信息。目前,您在各个项目中都有目标信息,因此在部署者项目中无法访问。

采用这种方法,您可以在新项目中定义多个配置文件,每个工件一个。每个配置文件都定义了一个依赖项:复制执行以获取其中一个项目的 jar 和 antrun 执行。可以从配置文件中提取通用配置(例如 antrun 插件的依赖项)。另请注意,如果您定义多个配置文件,属性将被合并,因此您可能需要使用工件名称来限定它们,例如 ftp.artifact1.host

<profiles>
  <profile>
    <id>deploy-artifact1</id>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <executions>
        <execution>
          <id>copy-dependency</id>
          <phase>prepare-package</phase>
          <goals>
            <goal>copy</goal>
          </goals>
          <configuration>
            <artifactItems>
              <artifactItem>
                <groupId>name.seller.rich</groupId>
                <artifactId>artifact1</artifactId>
                <version>1.0.0</version>
                <type>jar</type>
                <overWrite>false</overWrite>
              </artifactItem>
            </artifactItems>
            <outputDirectory>${project.build.directory}/deploy-staging</outputDirectory>
            <overWriteReleases>false</overWriteReleases>
          </configuration>
        </execution>
      </executions>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-antrun-plugin</artifactId>
      <executions>
        <execution>
          <id>ftp</id>
          <phase>install</phase>
          <configuration>
            <tasks>
              <ftp action="send" 
                  server="${ftp.host}" remotedir="${ftp.remotedir}" 
                  userid="${ftp.userid}" password="${ftp.password}" 
                  depends="${ftp.depends}" verbose="${ftp.verbose}">
                <fileset dir="${project.build.directory} includes="deploy-staging/"/>
              </ftp>
            </tasks>
          </configuration>
          <goals>
            <goal>run</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    <properties>
      <!--if the properties differ between targets, qualify them with the artifact name-->
      <ftp.host>hostname</ftp.host>
      <ftp.remotedir>/opt/path/to/install</ftp.remotedir>
      <ftp.userid>user</ftp.userid>
      <ftp.password>mypassword</ftp.password>
      <ftp.depends>yes</ftp.depends>
      <ftp.verbose>no</ftp.verbose>          
    </properties>
  </profile>
</profiles>  

【讨论】:

  • 这应该可以。个人资料是我一直缺少的。这是另一个有助于解决“打嗝”的想法——而不是将子项目定义为模块,而是将它们定义为父 POM 中的依赖项,并使用依赖项插件将工件 JAR 提取到它们的目的地。这行得通吗?
  • 我忘了提到,在我们的企业中,我们使用 NAC 能够映射/访问任何服务器,就像映射目录一样(Win/*NIX),所以真的不需要 FTP 或 SSH跨度>
  • 在这种情况下,依赖插件的复制目标就是你所需要的,只需将 outputDirectory 属性修改为目标的路径
  • 太棒了!感谢您的时间和建议 Rich,一旦我完成我正在做的事情,我会更新帖子,但我接受您的建议作为解决方案
  • 没有什么比使用 XML 执行脚本 - 剪掉阴囊 :(
【解决方案2】:

我会考虑使用maven-assembly-plugin 来执行此操作。

这样的东西可用于从子项目中获取文件并将它们填充到输出目录中。

<assembly>
  <id>xyzzy</id>
  <formats>
   <format>zip</format>
  </formats>
  <fileSets>
   <fileSet>
      <directory>../subproject1/target/</directory>
      <outputDirectory>/foo</outputDirectory>
      <includes>
        <include>*.jar</include>
      </includes>
   </fileSet>
   <fileSet>
      <directory>../subproject1/target/html-output/</directory>
      <outputDirectory>/foo</outputDirectory>
      <includes>
        <include>*.html</include>
        <include>*.js</include>
        <include>*.css</include>
      </includes>
    </fileSet>     
    <fileSet>
      <directory>../subproject2/target/</directory>
      <outputDirectory>/bar</outputDirectory>
      <includes>
        <include>**/**</include>
      </includes>
      <excludes>
        <exclude>**/*.exclude-this</exclude>
      </excludes>
    </fileSet>
  </fileSets> 
</assembly>

【讨论】:

  • 据我了解 - 程序集插件将创建某种存档(jar、war、zip) - 这对我不起作用 - 我需要将实际文件/文件夹复制到目的地。实际上 - maven-dependency 插件似乎更合适,因为它可以“解包”,但后来我被卡住了,因为我无法将子项目定义为模块和依赖项。所以我要走的路线实际上是在 Rich 的建议之后 - 在安装阶段定义配置文件和复制文件。
【解决方案3】:

Maven 并不是真正设计用于将 jar 部署到远程位置;它的主要用途是编译和打包工件。程序集和依赖项目标主要用于收集依赖项和文件以打包到工件中。

话虽如此,maven 确实有一个部署目标,它使用一个名为 wagon 的组件。这主要用于部署到 Maven 存储库。有一个名为 Cargo 的插件可用于将工件部署到远程服务器,但它本身不会爆炸 jar 内容(它依赖于目标应用服务器来完成所有这些工作)。您也许可以自己扩展 Maven Wagon 功能。

此外,可以打包自定义生命周期,但这会涉及到一些相当低级的 maven mojo(双关语)。

【讨论】:

  • 我最终使用了配置文件和 antrun - 两全其美!
  • 太棒了!我猜 Antrun 是回避整个 Maven 需求的方法;)
【解决方案4】:

没有密码就无法工作。

    <profile>
        <id>publish</id>
        <build>
            <plugins>
                <plugin>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>scp</id>
                            <phase>deploy</phase>
                            <configuration>
                                <tasks>
                                    <scp todir="user@host:some/remote/dir"
                                         sftp="true"
                                         keyfile="${user.home}/.ssh/devel-deploy.id_dsa"
                                         failonerror="false"
                                         verbose="true"
                                         passphrase="nopass"
                                    >
                                        <fileset dir="${project.build.directory}">
                                            <include
                                                name="${project.build.finalName}.${project.packaging}"/>
                                        </fileset>
                                    </scp>
                                </tasks>
                            </configuration>
                            <goals>
                                <goal>run</goal>
                            </goals>
                        </execution>
                    </executions>
                    <dependencies>
                        <dependency>
                            <groupId>org.apache.ant</groupId>
                            <artifactId>ant-jsch</artifactId>
                            <version>1.9.4</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </build>
    </profile>

不过,我最喜欢的是

    <profile>
        <id>upload-devel</id>
        <build>
            <plugins>
                <plugin>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>upload-devel</id>
                            <phase>deploy</phase>
                            <configuration>
                                <target>
                                    <exec executable="rsync" failonerror="false">
                                        <arg value="-aiz" />
                                        <arg value="${project.build.directory}/${project.artifactId}.${project.packaging}" />
                                        <arg value="user@host:some/remote/dir/." />
                                    </exec>
                                </target>
                            </configuration>
                            <goals>
                                <goal>run</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>

虽然我不知道它在不同平台上的兼容性如何。

【讨论】:

  • 为了让rsync 以这种方式工作,我必须在&lt;artifactId&gt;maven-antrun-plugin&lt;/artifactId&gt; 之后添加&lt;version&gt;1.8&lt;/version&gt;。没有它,它实际上并没有执行命令,即使它确实打印了[INFO] Executed tasks
【解决方案5】:

下面的 POM 将有助于将 jar 文件从项目构建目录复制到远程 SFTP/FTP 服务器。

  1. 使用命令mvn install -Dftp.password=password

由于出于安全原因我想从命令提示符传递密码,所以我使用了 -Dftp.password=password 执行上述命令后,maven 项目目标文件夹中的所有 jar 文件将部署在 server.com 上的 MAVEN 文件夹中

    <plugin>          <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-antrun-plugin</artifactId>

    <executions>
        <execution>
            <id>ftp</id>
            <phase>install</phase>
            <configuration>
                <tasks>
                    <scp todir="user@server.com:/MAVEN/"
                        sftp="true" port="22" trust="true" password="${ftp.password}"
                        failonerror="false" verbose="true" passphrase="">
                        <fileset dir="${project.build.directory}">
                            <include name="*.jar" />
                        </fileset>
                    </scp>
                </tasks>
            </configuration>
            <goals>
                <goal>run</goal>
            </goals>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>org.apache.ant</groupId>
            <artifactId>ant-jsch</artifactId>
            <version>1.9.4</version>
        </dependency>
    </dependencies>

</plugin>

【讨论】:

    猜你喜欢
    • 2012-11-12
    • 2013-03-09
    • 2012-10-14
    • 2012-12-03
    • 2011-04-27
    • 1970-01-01
    • 2010-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多