Кращі практики копіювання файлів за допомогою Maven


194

У мене є конфігураційні файли та різні документи, які я хочу скопіювати з середовища розробників у каталог dev-серверів за допомогою Maven2. Як не дивно, Мевен не здається сильним у цьому завданні.

Деякі варіанти:

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

    • Побудуйте артефакт zip типу , поряд із "головним" артефактом POM, який зазвичай є тип jar , а потім розпакуйте цей артефакт із сховища в цільовий каталог.

    • додаток maven-ресурси , як зазначено нижче.

    • Плагін Maven Assembly - але це, мабуть, вимагає безлічі ручних визначень, коли я хочу робити речі просто та "умовно".

    • На цій сторінці навіть показано, як створити плагін для копіювання!

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

    • плагін maven-залежність із копією , як зазначено нижче.


Все це здається непотрібним: Maven повинен досконало виконувати ці стандартні завдання без суєти і не турбуватися.

Будь-яка порада?


2
Мейвен будується навколо ідеї життєвого циклу з фазами, копіювання випадкових файлів у завдання віддаленого сервера насправді не вписується в це. Завжди думайте про свій проект в цілому.
Андре

3
"Все це здається не потрібним спеціальним завданням: Мейвен повинен досконало виконувати ці стандартні завдання без суєти і не турбуватися". Те, що ви робите, не є звичайним завданням, як правило. Якщо ваш артефакт був війною / вухом, то це було б так само просто, як використання плагіну вантажу (cargo.codehaus.org/Maven2+plugin#Maven2plugin-get…). Те, що ви описуєте, звучить дуже специфічно для того, як ви робите розгортання, а не стандартні розгортання контейнерів Java-додатків. Maven насправді не спрямований на обробку часу розгортання активних серверів - він більше орієнтований на створення / розробку.
кит

67
@ Андре: Я чую цей аргумент знову і знову, але вибачте, це BS. Нічого поганого в розгляді проекту в цілому, але частина будь-якої пристойної системи складання повинна бути функціональністю, яка дозволяє мені виконувати завдання X прямим шляхом, наприклад, копіювати файли, і Maven не може цього зробити. Є причина, чому останнім часом з’явилося так багато проектів, які охоплюють парадигму build-script-are-code (як Gradle, SBT або Buildr).
Маттіас

Я б рекомендував мати pom.xml для створення артефактів та інший для розгортання заданого артефакту.
Thorbjørn Ravn Andersen

Усі наведені вище пропозиції все ще не дозволяють мені скопіювати певний файл з іншого проекту / артефакту в проект Maven. У мене є кілька файлів під src / main / папкою в артефакт, який стає jar, і я спробував використовувати плагін Maven-copy copy, але я не знайшов способу сказати, які файли я хочу скопіювати, і я отримаю всю банку Файл у складальному файлі постійно. Усі інші пропозиції тут, як ресурси, схоже, не дозволяють мені вказати артефакт, а не ресурси всередині проекту
Олександр Томоріо

Відповіді:


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 Plugin ). Ви повинні використовувати 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>

Дякую @Peter, це було корисно. Зараз я використовую ціль ресурсів-плагінів копіювання ресурсів замість antrun. Останнє насправді визначити набагато простіше та інтуїтивніше, але я не міг змусити його (версія 1.3) передати всі власні властивості Maven (визначені в розділі <властивості>) на запуск, тому я перейшов на ресурс-плагін.
Корнел Массон

2
Раніше я вважав, що це правильна відповідь ... поки я не зрозумів, що плагін ресурсів не має конфігурації пропуску. Антрун - це шлях.
Майк Пост

Створити пропускний профіль не повинно бути складно. Ніколи не використовував мурашник, тому не можу сказати, що простіше / краще
Вівек Чавда,

40

Щоб скопіювати файл, використовуйте:

        <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
Я не використовував Мурашку роками, і не хочу починати робити це для такої простої речі. Тож дякую за цю відповідь.
Густав

18

Для простих завдань щодо копіювання я можу порекомендувати копіювати-перейменувати-maven-плагін . Це просто і просто у використанні:

<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, що знайшли це обмеження.)


2
Хоча цей плагін мені подобається, він вражає, що він не може копіювати каталоги.
james.garriss

3
@ james.garriss Я не знав цього обмеження, але, на жаль, ти маєш рацію. Я відредагую це у своїй відповіді, щоб, можливо, заощадити деяким людям час на пошук цього самих.
morten.c

7

Розроблене вище рішення для мурашок найлегше налаштувати, але мені пощастило використовувати плагін maven-upload від 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, це саме те, що я назвав свої змінні. У мене є профіль для розробника, тестування та прямого ефіру. Отже, щоб завантажити своє вухо до 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>
       ...

Примітки: Atpossian maven repo, який має цей плагін, знаходиться тут: https://maven.atlassian.com/public/

Рекомендую завантажити джерела та переглянути документацію всередині, щоб побачити всі функції, які надає плагін.

`


5

Що ж, Maven не повинен бути хорошим у виконанні тонких детальних завдань, це не мова сценаріїв, як баш або мураш, це доволі декларативно - ви кажете - мені потрібна війна чи вухо, і ви її отримуєте. Однак якщо вам потрібно налаштувати, як повинна виглядати війна чи вухо всередині, у вас є проблеми. Це просто не процедурно, як мураха, а декларативний. Це має деякі плюси на початку, і в кінці кінця може бути багато мінусів.

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

Якщо ви докладете достатньо зусиль для своїх помічників і декількох користувацьких плагінів, ви отримаєте набагато кращу середу побудови, як, наприклад, мураха (це залежить від вашого проекту, звичайно, але це стає все більше і більше для більших проектів).


4

Я мав дуже гарний досвід роботи з програмою copy-maven-plugin . Він має набагато більш зручний і стислий синтаксис порівняно з maven-ресурси-плагіном.


8
На жаль, copy-maven-plugin не сумісний з maven 3.1.x
Хакан

2
Проблема з відстеженням сумісності з maven 3.1 є: github.com/evgeny-goldin/maven-plugins/isissue/10
koppor

Забудьте про цей плагін ... Шукайте його вилки
Kukeltje

4

Узагальненим способом копіювання довільних файлів є використання транспортної абстракції Maven Wagon . Він може обробляти різні пункти призначення з допомогою протоколів , таких як file, HTTP, FTP, SCPабо WebDAV.

Є кілька плагінів, які надають засоби для копіювання файлів за допомогою використання Wagon. Найпомітніші:

  • Нестандартний плагін Maven 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 copy .


Ant належить до основних функціональних можливостей Maven, а також Wagon (хоча плагін навколо нього не є офіційним плагін Maven).
ГерольдБрозер повертає Моніку
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.