Лучшие практики для копирования файлов с Maven

194

У меня есть файлы конфигурации и различные документы, которые я хочу скопировать из среды dev в каталог dev-server с помощью Maven2. Как ни странно, Maven не кажется сильным в этой задаче.

Некоторые из вариантов:

  • Простое использование задачи копирования в Maven
<copy file="src/main/resources/config.properties" tofile="${project.server.config}/config.properties"/>
  • Используйте плагин Ant для выполнения копирования из Ant.

    • Создайте артефакт типа zip вместе с «основным» артефактом POM, который обычно имеет тип jar , затем распакуйте этот артефакт из репозитория в целевой каталог.

    • плагин maven-resources , как упомянуто ниже.

    • Плагин Maven Assembly - но для этого требуется много ручных определений, когда я хочу делать вещи просто и «условно».

    • Эта страница даже показывает, как создать плагин для копирования!

    • плагин maven-upload , как указано ниже.

    • maven-зависимый плагин с копией , как упомянуто ниже.


Все это кажется ненужным ad hoc: Maven должен превосходно выполнять эти стандартные задачи без суеты и беспокойства.

Любой совет?

Джошуа Фокс
источник
2
Maven построен на идее жизненного цикла с фазами, копирование случайных файлов на задачу удаленного сервера не очень подходит для этого. Всегда думайте о своем проекте в целом.
Андре
3
«Все это кажется излишне специальным: Maven должен превосходно выполнять эти стандартные задачи без суеты и беспокойства.» То, что вы делаете, не является стандартной задачей, как таковой. Если бы ваш артефакт был войной / ухом, то это было бы так же просто, как использовать грузовой плагин (cargo.codehaus.org/Maven2+plugin#Maven2plugin-get…). То, что вы описываете, звучит очень специфично для ваших развертываний, а не для стандартных развертываний контейнера Java-приложений. Maven на самом деле не предназначен для обработки операций развертывания на живых серверах - он больше ориентирован на создание операций / dev.
Кит
67
@ Андре: Я слышу этот аргумент снова и снова, но извините, это BS. Нет ничего плохого в том, чтобы думать о проекте в целом, но частью любой приличной системы сборки должна быть функциональность, которая позволяет мне напрямую решать задачу X, например копировать файлы, а Maven не может этого сделать. Есть причина, по которой в последнее время появилось так много проектов, в которых используется парадигма build-scripts-are-code (например, Gradle, SBT или Buildr).
Матиас
Я бы порекомендовал иметь pom.xml для создания артефактов и другой для развертывания данного артефакта.
Турбьерн Равн Андерсен
Все вышеизложенные предложения, похоже, не позволяют мне скопировать определенный файл из другого проекта / артефакта в проект maven. У меня есть несколько файлов в папке src / main / в артефакте, который становится jar, и я попытался использовать плагин maven для копирования зависимостей, однако я не нашел способа сказать, какие файлы я хочу скопировать, и я получил весь jar файл в файле сборки все время. Все остальные предложения, такие как ресурсы, похоже, не позволяют мне указывать артефакт, а не ресурсы внутри проекта
Александр Тенорио

Ответы:

120

Не уклоняйтесь от плагина Antrun. Просто потому, что некоторые люди склонны думать, что Муравей и Мавен находятся в оппозиции, это не так. Используйте задачу копирования, если вам необходимо выполнить одноразовую индивидуальную настройку:

<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 в качестве системы сборки для создания развертываемого артефакта, затем выполните эти настройки либо в отдельных модулях, либо в другом месте полностью. Если вы поделились немного больше со своей средой сборки, возможно, есть лучший способ - есть плагины для предоставления нескольких серверов. Не могли бы вы прикрепить сборку, которая распакована в корне сервера? Какой сервер вы используете?

Опять же, я уверен, что есть лучший способ.

Тим О'Брайен
источник
Является ли дескриптор задачи устаревшим?
Мэтт
3
@Matt Да, этот taskпараметр устарел ( плагин Antrun ). Вы должны использовать targetвместо этого (начиная с 1.5). К сожалению, есть примеры, которые смешивают это; например, targetпараметр и version<1,5.
CuH
Как это может быть принятым ответом? Определенно должен быть запрос на изменение к maven, чтобы сделать копию простой вещью.
Вольфганг
137
<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>
кей - SE это зло
источник
Спасибо @Peter, это было полезно. Теперь я использую цель копий ресурсов ресурсов плагина вместо antrun. Последний на самом деле намного проще и интуитивно понятен, но я не смог заставить его (версия 1.3) передать все пользовательские свойства Maven (определенные в разделе <properties>) в antrun, поэтому я переключился на плагин resources-plugin.
Корнел Массон
2
Раньше я думал, что это правильный ответ ... пока не понял, что плагин ресурсов не имеет конфигурации пропуска. Антрун это путь.
Майк Пост
Создать профиль пропуска не должно быть сложно. Я не использовал antrun, поэтому я не могу сказать, что легче / лучше
Вивек Чавда
41

Для копирования файла используйте:

        <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>  
Александр Дробышевский
источник
Фильтрация в Maven относится к интерполяции строк, поэтому я бы пропустил <filtering>предотвращение нежелательных изменений, например, файлов сценариев, которые используют ${...}переменные.
Герольд Брозер
20

Плагин зависимостей 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>

Зависимость: копия является documentend, и имеет более полезные цели , как распаковывать.

Шины
источник
3
Я не использовал Ant годами, и я не хочу начинать делать это для такой простой вещи. Так что спасибо за этот ответ.
Гюстав
18

Для простых задач копирования я могу порекомендовать 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 за то, что нашли это ограничение.)

morten.c
источник
2
Хотя мне нравится этот плагин, поразительно, что он не может копировать каталоги.
james.garriss
3
@ james.garriss Я не знал об этом ограничении, но, к сожалению, вы правы. Я отредактирую это в своем ответе, чтобы, возможно, сэкономить некоторым людям время, чтобы найти это самостоятельно.
morten.c
7

Приведенное выше решение для ant проще всего настроить, но мне повезло с помощью maven-upload-plugin от Atlassian. Мне не удалось найти хорошую документацию, вот как я ее использую:

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

<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 с этим плагином находится здесь: https://maven.atlassian.com/public/

Я рекомендую скачать исходники и просмотреть документацию внутри, чтобы увидеть все функции, которые предоставляет плагин.

`

Кайл Ренфро
источник
5

Что ж, maven не должен хорошо выполнять тонкие гранулярные задачи, это не язык сценариев, такой как bash или ant, он скорее декларативный - вы говорите - мне нужна война или ухо, и вы это понимаете. Однако, если вам нужно настроить внешний вид войны или ушей, у вас есть проблема. Это просто не процедурный, как муравей, а декларативный. У этого есть некоторые плюсы в начале, и может быть много минусов в конце.

Я предполагаю, что первоначальная концепция заключалась в том, чтобы иметь прекрасные плагины, которые «просто работают», но реальность другая, если вы делаете нестандартные вещи.

Однако, если вы приложите достаточно усилий к своим poms и нескольким пользовательским плагинам, вы получите гораздо лучшую среду сборки, как, например, с ant (конечно, это зависит от вашего проекта, но оно становится все более и более актуальным для больших проектов).

siddhadev
источник
4

У меня был очень хороший опыт работы с copy-maven-plugin . Он имеет гораздо более удобный и лаконичный синтаксис по сравнению с плагином maven-resources-plugin.

azerole
источник
8
К сожалению, copy-maven-plugin не совместим с maven 3.1.x
Хакан
2
Проблема отслеживания совместимости с maven 3.1 есть: github.com/evgeny-goldin/maven-plugins/issues/10
koppor
Забудьте об этом плагине ... Ищите его вилки
Kukeltje
4

Общий способ копирования произвольных файлов - использование транспортной абстракции Maven Wagon . Он может обрабатывать различные пункты назначения с помощью протоколов , таких как file, HTTP, FTP, SCPили WebDAV.

Есть несколько плагинов, которые предоставляют средства для копирования файлов с помощью Wagon. Наиболее заметными являются:

  • Из-из-табакерки Maven Plugin Deploy

    Есть 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

    Используйте upload-singleцель :

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

    Использование Wagon Maven Pluginдля копирования является простым и, кажется, наиболее универсальным.


В приведенных выше примерах <url>может быть любой поддерживаемый протокол. Смотрите список существующих провайдеров вагонов . Например

  • локальное копирование файла: 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настройки . repositoryId/ serverIdпередаваемый плагинам должен соответствовать серверу, указанному в настройках.

ᄂ ᄀ
источник
3

Я могу только предположить, что ваше свойство $ {project.server.config} определено пользователем и находится вне стандартного макета каталога.

Если так, то я бы использовал задачу копирования.

Уэйли
источник
Допустим, я позаботился о том, чтобы поместить файлы в стандартную структуру каталогов. Может ли Maven скопировать их в цель как есть, а не в zip / jar?
Джошуа Фокс
2

Другой способ - объединить эти вещи в артефакт, используя плагин сборки. Затем вы можете использовать плагин зависимости, чтобы распаковать эти файлы, куда вы хотите. В плагине зависимостей также есть цели копирования для копирования артефактов.

Брайан Фокс
источник
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

Бретт Даттон
источник
-1

Подводя итог некоторым из прекрасных ответов выше: Maven предназначен для создания модулей и копирования результатов в репозиторий Maven. Любое копирование модулей в каталог развертывания / установки-ввода должно выполняться вне контекста основных функций Maven, например, с помощью команды копирования Ant / Maven .

Джошуа Фокс
источник
Ant относится к основной функциональности Maven и Wagon (хотя плагин вокруг него не является официальным плагином ядра Maven).
Герольд Брозер