Могу ли я добавить файлы jar в maven 2 buildpath без их установки?
Maven2 сводит меня с ума во время фазы эксперимента / быстрого и грязного макета разработки.
у меня есть pom.xml
файл, который определяет зависимости для структуры веб-приложения, которую я хочу использовать, и я могу быстро сгенерировать начальные проекты из этого файла. Тем не менее, иногда я хочу сделать ссылку на стороннюю библиотеку, которая еще не имеет pom.xml
файл, а не создавать pom.xml
вручную запустите сторонний lib и установите его, а также добавьте зависимость к моему pom.xml
Я просто хотел бы сказать Maven: "В дополнение к моим определенным зависимостям, включите любые jar-файлы, которые находятся в /lib
тоже."
Кажется, это должно быть просто, но если это так, я что-то упускаю.
Любые указатели о том, как это сделать, с благодарностью. Если не считать этого, если есть простой способ указать Maven на /lib
каталог и легко создать pom.xml
со всеми вложенными jar-файлами, сопоставленными с одной зависимостью, которую я мог бы затем назвать / установить и ссылаться на нее одним махом;
23 ответа
Проблемы популярных подходов
Большинство ответов, которые вы найдете в Интернете, предложат вам либо установить зависимость для вашего локального репозитория, либо указать "системную" область в pom
и распространите зависимость с источником вашего проекта. Но оба эти решения на самом деле несовершенны.
Почему вы не должны применять подход "Install to Local Repo"
Когда вы устанавливаете зависимость в свой локальный репозиторий, он остается там. С вашим артефактом распространения все будет хорошо, если у него есть доступ к этому хранилищу. Проблема в том, что в большинстве случаев этот репозиторий будет находиться на вашем локальном компьютере, поэтому не будет никакого способа разрешить эту зависимость на любом другом компьютере. Очевидно, что зависимость вашего артефакта от конкретной машины - это не способ справиться с ситуацией. В противном случае эта зависимость должна быть установлена локально на каждой машине, работающей с этим проектом, что не лучше.
Почему вы не должны применять подход "Scope System"
Банки, от которых зависит подход System Scope, не устанавливаются ни в какое хранилище и не присоединяются к целевым пакетам. Вот почему ваш дистрибутив не сможет решить эту зависимость при использовании. Именно это, я считаю, и стало причиной того, что использование системного объема даже не рекомендуется. В любом случае, вы не хотите полагаться на устаревшую функцию.
Статическое решение для репозитория в проекте
После помещения этого в ваш pom
:
<repository>
<id>repo</id>
<releases>
<enabled>true</enabled>
<checksumPolicy>ignore</checksumPolicy>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<url>file://${project.basedir}/repo</url>
</repository>
для каждого артефакта с идентификатором группы формы x.y.z
Maven будет включать следующее местоположение в директорию вашего проекта при поиске артефактов:
repo/
| - x/
| | - y/
| | | - z/
| | | | - ${artifactId}/
| | | | | - ${version}/
| | | | | | - ${artifactId}-${version}.jar
Подробнее об этом вы можете прочитать в этом блоге.
Используйте Maven для установки в репозиторий проекта
Вместо того, чтобы создавать эту структуру вручную, я рекомендую использовать плагин Maven для установки ваших jar-файлов в качестве артефактов. Итак, чтобы установить артефакт в репозиторий в проекте под repo
папка выполнить:
mvn install:install-file -DlocalRepositoryPath=repo -DcreateChecksum=true -Dpackaging=jar -Dfile=[your-jar] -DgroupId=[...] -DartifactId=[...] -Dversion=[...]
Если вы выберете этот подход, вы сможете упростить декларацию хранилища в pom
чтобы:
<repository>
<id>repo</id>
<url>file://${project.basedir}/repo</url>
</repository>
Вспомогательный скрипт
Поскольку выполнение команды установки для каждой библиотеки является раздражающим и определенно подверженным ошибкам, я создал служебный скрипт, который автоматически устанавливает все файлы jar из lib
папка в хранилище проекта, автоматически разрешая все метаданные (groupId, artifactId и т. д.) из имен файлов. Сценарий также распечатывает зависимости xml для вас, чтобы скопировать и вставить в ваш pom
,
Включите зависимости в ваш целевой пакет
Когда вы создадите свой репозиторий в проекте, вы решите проблему распределения зависимостей проекта с его источником, но с тех пор целевой артефакт вашего проекта будет зависеть от неопубликованных jar-файлов, поэтому при установке у этого хранилища будут неразрешимые зависимости.
Чтобы преодолеть эту проблему, я предлагаю включить эти зависимости в ваш целевой пакет. Это вы можете сделать либо с плагином сборки, либо лучше с плагином OneJar. Официальную документацию по OneJar легко понять.
Только для выброшенного кода
установить область видимости == и просто создать идентификатор группы, идентификатор артефакта и версию
<dependency>
<groupId>org.swinglabs</groupId>
<artifactId>swingx</artifactId>
<version>0.9.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/swingx-0.9.3.jar</systemPath>
</dependency>
Примечание: системные зависимости не копируются в полученный jar / war
(см. Как включить системные зависимости в войну, построенную с использованием maven)
Вы можете создать локальный репозиторий на вашем проекте
Например, если у вас есть libs
папка в структуре проекта
В
libs
Папка, вы должны создать структуру каталогов, как:/groupId/artifactId/version/artifactId-version.jar
В вашем pom.xml вы должны зарегистрировать репозиторий
<repository> <id>ProjectRepo</id> <name>ProjectRepo</name> <url>file://${project.basedir}/libs</url> </repository>
и добавить зависимость как обычно
<dependency> <groupId>groupId</groupId> <artifactId>artifactId</artifactId> <version>version</version> </dependency>
Это все.
Для подробной информации: Как добавить внешние библиотеки в Maven
Примечание. При использовании области действия системы ( как упомянуто на этой странице) Maven нужны абсолютные пути.
Если ваши файлы находятся в корне вашего проекта, вам нужно добавить префикс значений systemPath к ${basedir}.
Это то, что я сделал, он также работает с проблемой пакета и работает с проверенным кодом.
Я создал новую папку в проекте, в моем случае я использовал repo
, но не стесняйтесь использовать src/repo
В моем POM у меня была зависимость, которой нет ни в одном публичном репозитории maven
<dependency>
<groupId>com.dovetail</groupId>
<artifactId>zoslog4j</artifactId>
<version>1.0.1</version>
<scope>runtime</scope>
</dependency>
Затем я создал следующие каталоги repo/com/dovetail/zoslog4j/1.0.1
и скопировал файл JAR в эту папку.
Я создал следующий файл POM для представления загруженного файла (этот шаг не является обязательным, но он удаляет ПРЕДУПРЕЖДЕНИЕ) и помогает следующему парню выяснить, где я получил файл для начала.
<?xml version="1.0" encoding="UTF-8" ?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dovetail</groupId>
<artifactId>zoslog4j</artifactId>
<packaging>jar</packaging>
<version>1.0.1</version>
<name>z/OS Log4J Appenders</name>
<url>http://dovetail.com/downloads/misc/index.html</url>
<description>Apache Log4j Appender for z/OS Logstreams, files, etc.</description>
</project>
Два дополнительных файла, которые я создаю, - это контрольные суммы SHA1 для POM и JAR, чтобы удалить предупреждения о пропущенной контрольной сумме.
shasum -b < repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.jar \
> repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.jar.sha1
shasum -b < repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.pom \
> repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.pom.sha1
Наконец, я добавляю следующий фрагмент в мой pom.xml, который позволяет мне ссылаться на локальный репозиторий
<repositories>
<repository>
<id>project</id>
<url>file:///${basedir}/repo</url>
</repository>
</repositories>
Вот как мы добавляем или устанавливаем локальную банку
<dependency>
<groupId>org.example</groupId>
<artifactId>iamajar</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/iamajar.jar</systemPath>
</dependency>
я дал некоторые значения по умолчанию groupId и artifactId, потому что они являются обязательными:)
Вы действительно должны установить фреймворк через репозиторий и заранее определить ваши зависимости. Использование системной области является распространенной ошибкой, которую используют люди, потому что они "не заботятся об управлении зависимостями". Проблема в том, что, делая это, вы получаете извращенную сборку maven, которая не будет отображать maven в нормальном состоянии. Тебе лучше следовать такому подходу.
Плагин установки Maven использует командную строку для установки jar в локальный репозиторий, POM является необязательным, но вам нужно будет указать GroupId, ArtifactId, Version и Packaging (все содержимое POM).
С помощью <scope>system</scope>
Это ужасная идея по причинам, объясненным другими, установка файла вручную в локальный репозиторий делает сборку невоспроизводимой и использует <url>file://${project.basedir}/repo</url>
это тоже не очень хорошая идея, потому что (1) это может быть file
URL (например, если проект извлечен в каталоге с необычными символами), (2) результат будет неприменим, если POM этого проекта используется в качестве зависимости от чужого проекта.
Если вы не хотите загружать артефакт в общедоступный репозиторий, предложение Симеона о вспомогательном модуле делает эту работу. Но теперь есть более легкий путь...
Рекомендация
Используйте https://github.com/stephenc/non-maven-jar-maven-plugin. Делает именно то, что вы просили, без каких-либо недостатков других подходов.
Я нашел другой способ сделать это, см. Здесь из сообщения Heroku
Подводя итог (извините за некоторые скопировать и вставить)
- Создать
repo
каталог под вашей корневой папкой:
yourproject +- pom.xml +- источник +- репо
- Запустите это, чтобы установить jar в локальный каталог репо
mvn deploy:deploy-file -Durl=file:///path/to/yourproject/repo/ -Dfile=mylib-1.0.jar -DgroupId=com.example -DartifactId=mylib -Dpackaging=jar -Dversion=1.0
- Добавьте это ваше
pom.xml
:
<repositories> <!--other repositories if any--> <repository> <id>project.local</id> <name>project</name> <url>file:${project.basedir}/repo</url> </repository> </repositories> <dependency> <groupId>com.example</groupId> <artifactId>mylib</artifactId> <version>1.0</version> </dependency>
То, что мне кажется самым простым, - это просто настроить плагин maven-compiler-plugin, чтобы он включал ваши пользовательские файлы jar. Этот пример загрузит любые файлы jar в каталог lib.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<includes>
<include>lib/*.jar</include>
</includes>
</configuration>
</plugin>
После продолжительного обсуждения с ребятами из CloudBees правильной упаковки таких JAR-файлов они сделали интересное хорошее предложение для решения:
Создание поддельного проекта Maven, который присоединяет ранее существовавший JAR-файл в качестве основного артефакта и запускается в принадлежащую POM install: выполнение install-file. Вот пример такого рода POM:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>image-util-id</id>
<phase>install</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${basedir}/file-you-want-to-include.jar</file>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<packaging>jar</packaging>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Но для его реализации необходимо изменить существующую структуру проекта. Во-первых, вы должны иметь в виду, что для каждого такого вида JAR должен быть создан отдельный поддельный проект Maven (модуль). И должен быть создан родительский проект Maven, включающий все подмодули, а именно: все оболочки JAR и существующий основной проект. Структура может быть:
корневой проект (содержит родительский POM-файл, включающий все подмодули с модулем XML) (упаковка POM)
JAR 1 обертка Maven, детский проект (упаковка POM)
JAR 2 обертка Maven, детский проект (упаковка POM)
основной существующий детский проект Maven (WAR, JAR, EAR .... упаковка)
Когда родительский процесс выполняется через mvn:install или mvn:package принудительно, и субмодули будут выполнены. Это может рассматриваться как минус, так как структура проекта должна быть изменена, но в конце предлагает нестатическое решение.
Чтобы установить сторонний jar, которого нет в репозитории maven, используйте maven-install-plugin.
Ниже приведены шаги:
- Скачать JAR-файл вручную с источника (веб-сайт)
- Создайте папку и поместите в нее свой файл jar
- Запустите приведенную ниже команду, чтобы установить сторонний jar в локальный репозиторий maven.
mvn install:install-file -Dfile= -DgroupId= -DartifactId= -Dversion= -Dpackaging=
Ниже приведен пример, который я использовал для simonsite log4j
mvn install: install-file -Dfile = / Пользователи /athanka/git/MyProject/repo/log4j-Rolling-Appender.jar -DgroupId=uk.org.simonsite -DartifactId=log4j-Rolling-Appender -Dversion=20150607-2059 -Dpackaging= баночка
В pom.xml включите зависимость как показано ниже
<dependency> <groupId>uk.org.simonsite</groupId> <artifactId>log4j-rolling-appender</artifactId> <version>20150607-2059</version> </dependency>
Запустите команду mvn clean install, чтобы создать упаковку
Ниже ссылка ссылка:
https://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html
Если вы хотите быстрое и грязное решение, вы можете сделать следующее (хотя я не рекомендую это ни для чего, кроме тестовых проектов, maven долго будет жаловаться, что это не правильно).
Добавьте запись о зависимости для каждого необходимого вам jar-файла, желательно с помощью perl-скрипта или чего-то подобного, и скопируйте / вставьте его в ваш pom-файл.
#! /usr/bin/perl
foreach my $n (@ARGV) {
$n=~s@.*/@@;
print "<dependency>
<groupId>local.dummy</groupId>
<artifactId>$n</artifactId>
<version>0.0.1</version>
<scope>system</scope>
<systemPath>\${project.basedir}/lib/$n</systemPath>
</dependency>
";
Быстрое и грязное пакетное решение (на основе ответа Алекса):
libs.bat
@ECHO OFF
FOR %%I IN (*.jar) DO (
echo ^<dependency^>
echo ^<groupId^>local.dummy^</groupId^>
echo ^<artifactId^>%%I^</artifactId^>
echo ^<version^>0.0.1^</version^>
echo ^<scope^>system^</scope^>
echo ^<systemPath^>${project.basedir}/lib/%%I^</systemPath^>
echo ^</dependency^>
)
Выполните это так: libs.bat > libs.txt
, Тогда открой libs.txt
и скопируйте его содержимое как зависимости.
В моем случае мне нужны были только библиотеки для компиляции моего кода, и это решение было лучшим для этой цели.
Проблема с systemPath
заключается в том, что файлы jar зависимостей не будут распределяться по вашим артефактам как переходные зависимости. Попробуйте то, что я написал здесь: лучше ли Mavenize файлы вашего проекта JAR или поместить их в WEB-INF/lib?
Затем объявите зависимости как обычно.
И, пожалуйста, прочитайте примечание нижнего колонтитула.
Даже если это не совсем подходит к вашей проблеме, я опущу это здесь. Мои требования были:
- Банки, которые не могут быть найдены в онлайн-хранилище maven, должны быть в SVN.
- Если один разработчик добавляет другую библиотеку, другим разработчикам не следует беспокоиться об их ручной установке.
- Среда IDE (в моем случае NetBeans) должна найти источники и javadoc для автозаполнения и помощи.
Давайте сначала поговорим о (3): просто держать банки в папке и как-то объединять их в финальную банку здесь не сработает, поскольку среда IDE не поймет этого. Это означает, что все библиотеки должны быть установлены правильно. Однако я не хочу, чтобы все устанавливали его с помощью "mvn install-file".
В моем проекте мне понадобился мета-виджет. Вот так:
- Создайте новый проект Maven (назовите его "shared-libs" или что-то в этом роде).
- Скачайте metawidget и распакуйте zip в src / main / lib.
- Папка doc / api содержит Javadocs. Создайте ZIP-архив содержимого (doc / api / api.zip).
- Модифицируйте пом как это
- Постройте проект, и библиотека будет установлена.
- Добавьте библиотеку в качестве зависимости к вашему проекту или (если вы добавили зависимость в проекте shared-libs) добавьте shared-libs в качестве зависимости, чтобы получить все библиотеки одновременно.
Каждый раз, когда у вас есть новая библиотека, просто добавьте новое исполнение и скажите всем, что вам нужно построить проект заново (вы можете улучшить этот процесс с помощью иерархий проектов).
Странное решение, которое я нашел:
используя Eclipse
- создать простой (не maven) проект Java
- добавить основной класс
- добавить все банки в путь к классам
- экспорт Runnable JAR (это важно, потому что здесь нет другого способа сделать это)
- выберите Извлечь необходимые библиотеки в сгенерированный JAR
- решить вопросы лицензии
- tadammm... установите сгенерированную банку на свой m2repo
- добавьте эту единственную зависимость к другим вашим проектам.
ура, Балинт
Для тех, кто не нашел здесь хорошего ответа, это то, что мы делаем, чтобы получить банку со всеми необходимыми зависимостями. В этом ответе ( /questions/13896682/mogu-li-ya-dobavit-fajlyi-jar-v-maven-2-buildpath-bez-ih-ustanovki/13896699#13896699) упоминается использование подключаемого модуля Maven Assembly, но на самом деле не приводится пример ответа. И если вы не прочитали весь путь до конца ответа (он довольно длинный), вы можете пропустить его. Добавление ниже к вашему pom.xml сгенерирует target/${PROJECT_NAME}-${VERSION}-jar-with-dependencies.jar
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<!-- get all project dependencies -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- MainClass in mainfest make a executable jar -->
<archive>
<manifest>
<mainClass>my.package.mainclass</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Я сослался на некоторый код на python в комментарии к ответу @alex lehmann's, поэтому выкладываю его здесь.
def AddJars(jarList):
s1 = ''
for elem in jarList:
s1+= """
<dependency>
<groupId>local.dummy</groupId>
<artifactId>%s</artifactId>
<version>0.0.1</version>
<scope>system</scope>
<systemPath>${project.basedir}/manual_jars/%s</systemPath>
</dependency>\n"""%(elem, elem)
return s1
В нашем проекте работает то, что написал Архимед Траяно, но в нашем файле.m2/settings.xml было что-то вроде этого:
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://url_to_our_repository</url>
</mirror>
и * следует изменить на центральный. Так что, если его ответ не работает для вас, вы должны проверить свои settings.xml
Это не ответ на вопрос о том, как добавить их в POM, и, может быть, не составит труда, но просто добавит lib dir к вашей работе с classpath? Я знаю, что это то, что я делаю, когда мне нужна внешняя банка, которую я не хочу добавлять в свои репозитории Maven.
Надеюсь это поможет.
Решение для подхода scope='system' в Java:
public static void main(String[] args) {
String filepath = "/Users/Downloads/lib/";
try (Stream<Path> walk = Files.walk(Paths.get(filepath))) {
List<String> result = walk.filter(Files::isRegularFile)
.map(x -> x.toString()).collect(Collectors.toList());
String indentation = " ";
for (String s : result) {
System.out.println(indentation + indentation + "<dependency>");
System.out.println(indentation + indentation + indentation + "<groupId>"
+ s.replace(filepath, "").replace(".jar", "")
+ "</groupId>");
System.out.println(indentation + indentation + indentation + "<artifactId>"
+ s.replace(filepath, "").replace(".jar", "")
+ "</artifactId>");
System.out.println(indentation + indentation + indentation + "<version>"
+ s.replace(filepath, "").replace(".jar", "")
+ "</version>");
System.out.println(indentation + indentation + indentation + "<scope>system</scope>");
System.out.println(indentation + indentation + indentation + "<systemPath>" + s + "</systemPath>");
System.out.println(indentation + indentation + "</dependency>");
}
} catch (IOException e) {
e.printStackTrace();
}
}
Я просто хотел быстрый и грязный обходной путь... Я не мог запустить скрипт от Никиты Волкова: синтаксическая ошибка + требуется строгий формат для имен банок.
Я создал этот Perl-скрипт, который работает с любым форматом для имен файлов jar, и он генерирует зависимости в xml, чтобы его можно было копировать и вставлять непосредственно в pom.
Если вы хотите использовать его, убедитесь, что вы понимаете, что делает скрипт, вам может потребоваться изменить lib
папка и значение для groupId
или же artifactId
...
#!/usr/bin/perl
use strict;
use warnings;
open(my $fh, '>', 'dependencies.xml') or die "Could not open file 'dependencies.xml' $!";
foreach my $file (glob("lib/*.jar")) {
print "$file\n";
my $groupId = "my.mess";
my $artifactId = "";
my $version = "0.1-SNAPSHOT";
if ($file =~ /\/([^\/]*?)(-([0-9v\._]*))?\.jar$/) {
$artifactId = $1;
if (defined($3)) {
$version = $3;
}
`mvn install:install-file -Dfile=$file -DgroupId=$groupId -DartifactId=$artifactId -Dversion=$version -Dpackaging=jar`;
print $fh "<dependency>\n\t<groupId>$groupId</groupId>\n\t<artifactId>$artifactId</artifactId>\n\t<version>$version</version>\n</dependency>\n";
print " => $groupId:$artifactId:$version\n";
} else {
print "##### BEUH...\n";
}
}
close $fh;