Какой лучший способ поделиться файлами JAR между несколькими проектами?

Когда у вас есть несколько проектов, которые используют один и тот же набор JAR-библиотек, утомительно включать в каждый проект одни и те же JAR-файлы снова и снова. Если я работаю над 20 различными проектами, я бы предпочел, чтобы у меня не было 20 одинаковых наборов JAR-файлов. Каков наилучший способ сделать так, чтобы все эти проекты (и новые проекты) ссылались на один и тот же набор JAR?

У меня есть некоторые идеи, но у каждого из них есть свои недостатки:

  • Поместите все файлы JAR в папку и просмотрите каждый проект в этой папке.
  • Используя Eclipse, создайте "Пользовательскую библиотеку" и сделайте так, чтобы каждый проект ссылался на эту пользовательскую библиотеку.
  • Создайте "библиотечный" проект, который ссылается на каждый JAR, и каждый проект должен ссылаться на этот библиотечный проект.

7 ответов

Решение

Используйте Maven или Ivy для обработки этих общих банок. Если вы опасаетесь слишком сильно менять свои проекты, вы можете просто использовать Ivy для управления дополнительным путем к классам.


Оба имеют хорошие плагины Eclipse:

m2eclipse

http://img229.imageshack.us/img229/4848/mavendependencies.png

IvyDE

http://img76.imageshack.us/img76/3180/cpnode.jpg

который я использовал с хорошими результатами.

Вы заметите, что оба они ссылаются на jar вне рабочей области, поэтому дублирование удаляется.


Обновление (подсказано комментариями):

Моя причина рекомендовать этот подход состоит в том, что я твердо верю, что проще и яснее объявлять зависимости, чем включать их вручную. С этим связана небольшая единовременная стоимость - для Ivy меньше, чем для Maven - но в конечном итоге она окупается.

Другое, меньшее, преимущество - обработка транзитивных и конфликтующих зависимостей. Легко забыть, зачем вам нужен файл commons-logging-1.1.jar в classpath и нужно ли вам обновиться до 1.1.1. А также неинтересно вставлять все зависимости, необходимые, например, для комбинации Hibernate + Annotation + Spring. Фокус на программировании, а не на строительстве.

Believe it or not, your 'tedious' approach is probably the simplest, cleanest and least time-consuming approach there is.

Before jumping on the maven bandwagon you should consider what is really wrong with doing things the way you are currently doing them. You mentioned that it is tedious and that you have a lot of jar files lying around. I created the build process on a large multi-module project using Maven then spent the next 18 months battling with it constantly. Believe me it was tedious and there were a lot of jar files lying around.

Since going back to Ant and committing jars to source control alongside the projects that use them it has been a much smoother ride.

I store a bunch of jar files in a single directory on my machine and then when I create a new project or need to add a new jar to an existing project it only takes about 30 seconds:

  • Copy the jar from JAR_REPO to project lib dir.
  • Add jar to build.properties
  • Add jar to classpath in build.xml
  • Add jar to build path in Eclipse.

Over the course of a project, that 30 seconds is insignificant, but it means I have a project that can be checked out of source control and just works without requiring any custom Eclipse configuration or Maven installations or user-specific setup.

This approach has saved me and my project team a huge amount of time, mainly because it is simple, reliable and easy to understand.


Update: Clarification prompted by comments

@Robert Munteanu: Thanks for the feedback and updated comments. This might sound a bit argumentative but I'm afraid I can't agree with you that Maven is simpler and clearer, or that it will save you time in the long run.

From your posting:
"I strongly believe that it's simpler and clearer to declare dependencies rather then manually include them. There is a small one-time cost associated with this - smaller for Ivy than for Maven - but in the long run it does pay off."

Maven может быть проще скачать файл JAR для вас, чем загружать его самостоятельно, но это единственное преимущество. В противном случае Maven не проще, не понятнее, и его сложности и ограничения обойдутся вам в долгосрочной перспективе.

ясность

Ниже приведены два объявления зависимостей. Я считаю, что Муравей намного яснее, чем Мавен.

Муравей Стиль:

<path id="compile.classpath">  
    <pathelement location="${log4j.jar}" />
    <pathelement location="${spring.jar}" />
</path>  

Maven Style:

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>${log4j.version}</version>
    <scope>compile</scope>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring</artifactId>
    <version>${spring.version}</version>
    <scope>compile</scope>
</dependency>

Простота

С версией Ant вы можете навести курсор на свойство ${log4j.jar}, и оно покажет вам абсолютный путь к файлу jar. Вы можете искать использование compile.classpath. Там не так много, что вам нужно знать.

Нет сомнений в том, что Maven более сложен, чем подход, который я предлагаю. Когда вы начинаете с Maven, это лишь некоторые из вопросов, на которые нужно ответить.

  • Что означает groupId?
  • Что означает artifactId?
  • Откуда берется банка?
  • Где сейчас банка?
  • Что предусмотрено сфера? Кто это обеспечивает?
  • Как этот файл JAR оказался в моем файле WAR?
  • Почему эта зависимость не имеет элемента версии?
  • Я не понимаю это сообщение об ошибке. Что на земле это значит?
  • Откуда на Земле взялся этот файл? Я не заявлял об этом.
  • Почему у меня есть 2 версии одного и того же файла JAR на моем classpath?
  • Почему проект больше не строится? Ничего не изменилось с тех пор, как я в последний раз его построил.
  • Как добавить стороннюю банку, которой нет в репозитории Maven?
  • Скажите мне еще раз, откуда я взял этот плагин Eclipse.

Переходные зависимости

"Другим, меньшим, преимуществом является обработка переходных и конфликтующих зависимостей".

По моему опыту, переходные зависимости - больше проблем, чем они того стоят. В итоге вы получаете несколько версий одного и того же файла JAR, и вы получаете дополнительные файлы JAR, которые вам не нужны. Я закончил тем, что объявил почти все с предоставленной областью, чтобы избежать хлопот.

Долгосрочная выплата

"Фокус на программировании, а не на строительстве".

Согласен. С тех пор, как я вернулся к Ant и перевел мои jar-файлы в систему контроля версий, я смог потратить гораздо меньше времени на решение проблем сборки.

Вот те вещи, на которые я трачу меньше времени:

  • Чтение плохой документации Maven.
  • Чтение еще более бедной документации Codehaus Mojo.
  • Настройка общих внутренних репозиториев.
  • Обучение членов команды.
  • Написание плагинов Maven для заполнения пробелов.
  • Попытка обойти неисправные плагины (выпуск, сборка).
  • Установка плагинов Eclipse для Maven.
  • Жду, когда плагин вернет мне контроль над Eclipse.

В любом случае, извините за долгую публикацию. Может быть, теперь, когда я снял это с моей груди, я смогу завершить свой долгий и мучительный опыт с Maven.:)

Это зависит от ваших потребностей, но есть несколько жизнеспособных вариантов. Моя работа использует внешнюю папку, и все проекты ссылаются на эту папку, что облегчает жизнь сборкам вне затмения. Пользовательская библиотека - немного более приятный способ сделать что-то, если вы не возражаете против небольшой зависимости затмения. Я не вижу особой пользы для библиотечного проекта сам по себе, но если у вас есть какой-то универсальный проект типа 'util', который уже загружены всеми другими проектами, вы можете просто поместить все внешние jar в этот проект.

Один из подходов состоит в том, чтобы поместить все ваши jar-файлы в одном месте на вашем компьютере, в вашем eclipse ide, определить переменную среды, скажем, LIB_LOCATION, которая указывает на этот каталог, и ваши проекты используют jars относительно этой переменной. Таким образом, вы получаете простоту использования, отсутствие нескольких jar-файлов, переносимых между машинами, если переменная определена правильно. Я пробовал Maven для группы проектов приличного размера, и мне кажется, что я должен бороться по крайней мере столько же, сколько раньше. Ошибки и проводное поведение в плагинах, m2eclipse и q4eclipse.

Мы определились с более утомительным методом, но который позволяет нам все устроить, но, вероятно, будет хорошо работать только для небольшого числа разработчиков.

Каждый набор JAR-файлов настроен как проект Eclipse, названный соответствующим образом после набора JAR, добавленный в путь сборки, исходные JAR-файлы и Javadoc-файлы JAR, правильно настроенные для каждого JAR-файла в пути сборки, и каждый проект включает в себя те проекты библиотек, которые необходимы для этот проект. Результирующее многопроектное рабочее пространство затем экспортируется в виде файла ProjectSet.psf, который затем может быть прочитан в необработанном Eclipse, снова перенося все рабочее пространство. Затем у нас есть все вышеупомянутые проекты в CVS, включая файлы jar.

Это сработало очень хорошо или нам.

Если вы работаете в более крупной организации, обработка зависимостей в Maven может работать хорошо для вас. У вас обязательно должен быть локальный кеш артефактов, чтобы весь мир не остановился, если ваше интернет-соединение потеряно.

Также обратите внимание, что новый Eclipse 3.5, выходящий этим летом, будет иметь "Create Runnable Jar", который может вывести необходимые jar рядом с сгенерированным runnable jar и правильно настроить строку Class-PAth в Manifest. Я ожидаю, что это сэкономит много времени - проверьте это.

Я бы рекомендовал "библиотечный" проектный подход.

Но даже лучше - отдельный проект lib для каждого внешнего jar-файла - это позволяет отслеживать задержки между сторонними jar-файлами и знать, что нужно изменить при обновлении зависимости.

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

Вы можете отредактировать "Установленные JRE", включив в них свой JAR-файл ("Добавить внешние JAR-файлы"), добавить файл в каталог jdk\jre\lib\ext\ или указать переменную среды CLASSPATH, содержащую путь к ней.

Другие вопросы по тегам