В какой секции файла build gradle указываются зависимости приложения

Обновлено: 07.07.2024

Этот урок освещает создание вами простого Java-приложения с использованием Gradle.

Что вы создадите

Вы создадите простое приложение и соберете его с помощью Gradle.

Что вам потребуется

  • Примерно 15 минут свободного времени
  • Любимый текстовый редактор или IDE и выше

Как проходить этот урок

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

Чтобы начать с нуля, перейдите в Настройка проекта.

Когда вы закончите, можете сравнить получившийся результат с образцом в gs-gradle/complete .

Настройка проекта

Для начала вам необходимо настроить Java-проект перед тем, как собрать его Gradle'ом. Т.к. урок посвящен Gradle, сделаем проект максимально простым, насколько это возможно.

Создание структуры каталогов

В выбранном вами каталоге проекта создайте следующую структуру каталогов; к примеру, командой mkdir -p src/main/java/hello для *nix систем:

Внутри src/main/java/hello директории вы можете создать любые Java-классы, какие вы хотите. Для простоты и согласованности с остальной частью урока, Spring рекомендует вам создать два класса: HelloWorld.java и Greeter.java .

Установка Gradle

Теперь, когда у вас есть проект, который вы можете собрать с Gradle, вам нужно установит сам Gradle.

Распакуйте архив и добавьте путь к каталогу bin в переменную окружения path.

Чтобы протестировать правильность установки Gradle, запустите в командной строке:

Теперь у вас есть установленный Gradle.

Что может делать Gradle

Теперь, когда Gradle установлен, посмотрим, что он может делать. Прежде, чем вы создадите build.gradle для проекта, выможете проверить, какие доступны задачи:

Вы должны увидеть список доступных задач. Если вы запустите Gradle в каталоге, в котором нет ещё файла build.gradle, то увидите несколько самых элементарных задач:

Не смотря на то, что эти задачи доступны, они не представляют большого значения без конфигурации для сборки проекта. С build.gradle файлом, некоторые задачи будут более полезны. Список задач будет увеличиваться при добавлении плагинов в build.gradle , таким образом вы будете время от времени запускать tasks, чтобы проверить, какие задачи доступны.

Говоря о добавлении плагинов, в следующей части урока вы добавите плагин, который отвечает за базовую функциональность сборки Java-проектов.

Сборка Java кода

Начнем с простого, создадим очень простой build.gradle в корневой папке проекта(там, где src), который содержит только одну строчку:

Эта единственная строчка в конфигурации сборки приносит значительную пользу. Запустите gradle tasks снова и вы увидите новые задачи в списке, включая задачи для сборки проекта, создания JavaDoc и запуска тестов.

Вы будете изпользовать задачу gradle build достаточно часто. Эта задача компилирует, тестирует и упаковывает код в JAR-файл. Вы можете запустить её таким образом:

Через несколько секунд, "BUILD SUCCESSFUL" будет означать, что сборка прошла успешно.

  • classes. Скомпилированные .class файлы
  • reports. Отчеты в течении сборки(такие как отчеты о тестировании)
  • libs. Библиотеки для сборки проекта(обычно в виде JAR и/или WAR файлов)

Классы в каталоге с .class файлами генерируются во время сборки Java-кода. Соответственно, вы должны найти там HelloWorld.class и Greeter.class.

На данный момент проект не имеет зависимостей от библиотек, поэтому ничего нет в папке dependency_cache.

Каталог отчетов должен содержать отчет о выполнении тестов для проекта. Т.к. проект пока не содержит тестов, данный отчет будет нам неинтересен.

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

Объявление зависимостей

Простой "Hello World" пример полностью автономный и не зависит от каких-либо дополнительных библиотек. Однако, большинство приложений зависит от внешних библиотек, с реализацией распостраненного и/или сложного функционала.

К примеру, предположим, что в дополнение к "Hello World!" вы хотите, чтобы приложение печатало текущую дату и время. Вы могли бы использовать функциональность из стандартных(native) Java библиотек, но мы можем сделать это и другими интересными способами, например с помощью Joda Time библиотеки.

Во первых, изменим HelloWorld.java , как показано ниже:

Здесь HelloWorld использует Joda Time LocalTime класс для получения и печати текущего времени.

Если бы вы запустили gradle build для сборки проекта сейчас, то получили бы ошибку сборки, потому что вы не объявили Joda Time компилируемую зависимость в сборке.

Во-вторых, вам необходимо добавить источники сторонних библиотек:

Блок repositories означает, что сборка должна разрешать зависимости из Maven Central репозитория. Gradle опирается в основном на многие соглашения и возможности, определенные в инструменте сборки Maven, включая использование Maven Central как источник библиотек зависимостей.

Теперь, когда мы готовы к приему сторонних библиотек, объявим их:

В блоке dependencies вы описываете единственную зависимость Joda Time. В частности, вы запрашиваете(читаем справа на лево) версию 2.2 библиотеки joda-time в joda-time группе.

Другое, что хотелось бы отметить, это необходимость указания ключевого слова compile , обозначающее доступность библиотеки во время компиляции(а если бы вы собирали WAR файл, то была бы включена /WEB-INF/libs папка в WAR). Также существуют другие заметные ключевые слова, среди которых:

  • providedCompile . Требуемые зависимости для компиляции кода, но которые будут доступны во время работы кода контейнера(например, Java Servlet API)
  • testCompile . Зависимости, используемые для компиляции и запуска тестов, но не требуемые для компиляции и запуска кода проекта

И наконец, назначим имя для нашего JAR артефакта.

jar блок определяет, как JAR файл будет назван. В данном случае мы получим gs-gradle-0.1.0.jar .

Теперь, если мы запустим gradle build , Gradle должен будет загрузить Joda Time зависимость из репозитория Maven Central и успешно собрать проект.

Сборка проекта с Gradle Wrapper

Gradle Wrapper является предпочтительным способом для начала Gradle сборки. Он содержит bat-скрипты для Windows и shell-скрипты для OS X и Linux. Эти скрипты позволяют вам запускать сборку с Gradle без необходимости установки самого Gradle в вашу систему. Чтобы это стало возможным, добавьте следующий блок в конец вашего build.gradle :

Запустите следующую команду для загрузки и инициализации wrapper-скриптов:

После того, как задачи отработают, вы заметите несколько новых файлов. Два скрипта в корневом каталоге, а jar-файл и properties-файл оболочки будут в папке gradle/wrapper .

Gradle Wrapper теперь доступен вам для сборки проекта. Добавьте его в вашу систему контроля версий и каждый, кто клонирует ваш проект, сможет его собрать точно таким же способом. Gradle Wrapper можно использовать наравне с установленным Gradle. Pfgecnbnt wrapper-скрипт для выполнения задичи сборки точно так же, как вы делали ранее:

Ранее, когда вы запускали wrapper с конкретной версией Gradle, он загружал и кешировал бинарники Gradle для соответствующей версии. Gradle Wrapper спроектирован таким образом, чтобы было возможно сохранить его в репозитории вашей VCS и любой, кто его клонирует, сможет собрать ваш проект без необходимости устанавливать и настраивать Gradle определенной версии.

На данном этапе у вас есть собранный ваш код. В результате вы увидете:

В сборке содержатся два класса Greeter и HelloWorld , как и ожидалось, а также JAR-файл. Окиньте беглым взглядом:

Это содержимое пакета файлов классов. Важно отметить, что даже, если вы и объявили joda-time как зависимость, библиотека не включена в пакет. И JAR-файл будет неспособен к выполнению.

Чтобы сделать этот код выполняемым, мы можем использовать плагин application . Добавьте его в ваш build.gradle файл.

Затем просто запустите ваше приложение!

Остановимся подробнее на упаковке зависимостей. К примеру, если бы мы собирали WAR-файл, общепризнанный формат, ассоциирующийся с упаковкой сторонних зависимостей, мы бы могли использовать WAR плагин. Если вы используете Spring Boot и хотите получить исполняемый JAR-файл, тогда вам пригодится spring-boot-gradle-plugin. На данном этапе, gradle недостаточно знает о выбранной вами системе. Но этого достаточно, чтобы приступить к работе с gradle.

В конечном счете, у вас должен получиться такой build.gradle файл:

Здесь присутствует много закомментированных открывающихся и закрывающихся вставок. Они позволяют разделить на части файл сборки для наглядного объяснения данного урока. Их необязательно использовать в вашем рабочем файле сборки.

Поздравляем! Вы создали простой, но эффективный файл сборки Gradle для сборки Java проектов.

Управление зависимостями – одна из наиболее важных функций в арсенале систем сборки. С приходом Gradle в качестве основной системы сборки Android-проектов в части управления зависимостями произошёл существенный сдвиг, закончилась эпоха ручного копирования JAR-файлов и долгих танцев с бубном вокруг сбоящих конфигураций проекта.


В статье рассматриваются основы управления зависимостями в Gradle, приводятся углублённые практические примеры, небольшие лайфхаки и ссылки на нужные места в документации.

Репозиторий

Объявление зависимостей


В приведённом выше примере вы видите сценарий сборки, в котором подключены две зависимости для различных конфигураций (compile и testCompile) компиляции проекта. JsonToken будет подключаться во время компиляции проекта и компиляции тестов проекта, jUnit только во время компиляции тестов проекта. Детальнее о конфигурациях компиляции — по ссылке.

Также можно увидеть, что jUnit-зависимость мы подключаем как динамическую(+), т.е. будет использоваться самая последняя из доступных версия 4.+, и нам не нужно будет следить за минорными обновлениями (рекомендую не использовать эту возможность в compile-типе компиляции приложения, т.к. могут появиться неожиданные, возможно, сложно локализуемые проблемы).

На примере с jUnit-зависимостью рассмотрим стандартный механизм Gradle по поиску необходимой зависимости:

Кэш

В Gradle реализована система кэширования, которая по умолчанию хранит зависимости в течение 24 часов, но это поведение можно переопределить.

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

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

– –offline – Gradle никогда не будет пытаться обратиться в сеть для проверки обновлений зависимостей.
– –refresh-dependencies – Gradle попытается обновить все зависимости. Удобно использовать при повреждении данных, находящихся в кэше. Верифицирует кэшированные данные и при отличии обновляет их.

Более детально про кэширование зависимостей можно прочитать в Gradle User Guide.

Виды зависимостей

Существует несколько видов зависимостей в Gradle. Наиболее часто используемыми являются:

– Внешние зависимости проекта — зависимости, загружаемые из внешних репозиториев;


– Проектные зависимости — зависимость от модуля (подпроекта) в рамках одного проекта;


– Файловые зависимости — зависимости, подключаемые как файлы (jar/aar архивы).


Также существуют зависимости клиентских модулей, зависимости Gradle API и локальные Groovy-зависимости. Они используются редко, поэтому в рамках данной статьи не будем их разбирать, но почитать документацию о них можно здесь.

Дерево зависимостей

Каждая внешняя или проектная зависимость может содержать собственные зависимости, которые необходимо учесть и загрузить. Таким образом, при выполнении компиляции происходит загрузка зависимостей для выбранной конфигурации и строится дерево зависимостей, человеческое представление которого можно увидеть, выполнив Gradle task ‘dependencies’ в Android Studio или команду gradle %module_name%:dependencies в консоли, находясь в корневой папке проекта. В ответ вы получите список деревьев зависимостей для каждой из доступных конфигураций.

Используя параметр configuration, указываем имя конфигурации, чтобы видеть дерево зависимостей только указанной конфигурации.

Возьмем специально подготовленные исходники репозитория, расположенного на github и попробуем получить дерево зависимостей для конкретной конфигурации (в данный момент проект находится в состоянии 0, т.е. в качестве build.gradle используется build.gradle.0):


Проанализировав дерево зависимостей, можно увидеть, что модуль app использует в качестве зависимостей две внешних зависимости (appcompat и guava), а также две проектных зависимости (first и second), которые в свою очередь используют библиотеку jsontoken версий 1.0 и 1.1 как внешнюю зависимость. Совершенно очевидно, что проект не может содержать две версии одной библиотеки в Classpath, да и нет в этом необходимости. На этом этапе Gradle включает модуль разрешения конфликтов.

Разрешение конфликтов

Gradle DSL содержит компонент, используемый для разрешения конфликтов зависимостей. Если посмотреть на зависимости библиотеки jsontoken на приведённом выше дереве зависимостей, то мы увидим их только раз. Для модуля second зависимости библиотеки jsontoken не указаны, а вывод самой зависимости содержит дополнительно ‘–> 1.1’, что говорит о том, что версия библиотеки 1.0 не используется, а автоматически была заменена на версию 1.1 с помощью Gradle-модуля разрешения конфликтов.

Для объяснения каким образом была разрешена конфликтная ситуация, также можно воспользоваться Gradle-таском dependencyInsight, например:


Стоит обратить внимание, что версия 1.1 выбирается в результате conflict resolution, также возможен выбор в результате других правил (например: selected by force или selected by rule). В статье будут приведены примеры использования правил, влияющих на стратегию разрешения зависимостей, и выполнив таск dependencyInsight вы сможете увидеть причину выбора конкретной версии библиотеки на каждом из приведённых ниже этапов. Для этого при переходе на каждый этап вы можете самостоятельно выполнить таск dependencyInsight.

При необходимости есть возможность переопределить логику работы Gradle-модуля разрешения конфликтов, например, указав Gradle падать при выявлении конфликтов во время конфигурирования проекта. (состояние 1)

После чего даже при попытке построить дерево зависимостей Gradle таски будут прерываться по причине наличия конфликта в зависимостях приложения.


У задачи есть четыре варианта решения:

Первый вариант – удалить строки, переопределяющие стратегию разрешения конфликтов.

Второй вариант – добавить в стратегию разрешения конфликтов правило обязательного использования библиотеки jsonToken, с указанием конкретной версии (состояние 2):

При применении этого варианта решения дерево зависимостей будет выглядеть следующим образом:


Третий вариант — добавить библиотеку jsonToken явно в качестве зависимости для проекта app и присвоить зависимости параметр force, который явно укажет, какую из версий библиотеки стоит использовать. (состояние 3)

А дерево зависимостей станет выглядеть следующим образом:


Четвёртый вариант – исключить у одной из проектных зависимостей jsontoken из собственных зависимостей с помощью параметра exclude. (состояние 4)

И дерево зависимостей станет выглядеть следующим образом:


Стоит отметить, что exclude не обязательно передавать оба параметра одновременно, можно использовать только один.

Но несмотря на правильный вывод дерева зависимостей, при попытке собрать приложение Gradle вернёт ошибку:


Добиться успешной сборки проекта можно тремя вариантами:

Первый — удалить guava из зависимостей модуля app. Если используется только та часть Guava, которая содержится в Google Collections, то предложенное решение будет неплохим.

Второй — исключить Google Collections из модуля first. Добиться этого мы можем используя описанное ранее исключение или правила конфигураций. Рассмотрим оба варианта, сначала используя исключения (состояние 5)

Пример использования правил конфигураций (состояние 6):

Дерево зависимостей для обеих реализаций исключения Google Collections будет идентично.


Третий вариант — использовать функционал подмены модулей (состояние 7):

Дерево зависимостей будет выглядеть следующим образом:


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

Также важно заметить, что последний из озвученных вариантов является самым гибким, ведь при удалении guava из списка зависимостей Gradle, Google Collections сохранится в проекте, и функционал, от него зависящий, сможет продолжить выполнение. А дерево зависимостей будет выглядеть следующим образом:


После каждого из вариантов мы достигнем успеха в виде собранного и запущенного приложения.

Но давайте рассмотрим другую ситуацию (состояние 8), у нас одна единственная сильно урезанная (для уменьшения размеров скриншотов) динамическая зависимость wiremock. Мы её используем сугубо в целях обучения, представьте вместо неё библиотеку, которую поставляет ваш коллега, он может выпустить новую версию в любой момент, и вам непременно необходимо использовать самую последнюю версию:

Дерево зависимостей выглядит следующим образом:


Как вы можете увидеть, Gradle загружает последнюю доступную версию wiremock, которая является beta. Ситуация нормальная для debug сборок, но если мы собираемся предоставить сборку пользователям, то нам определённо необходимо использовать release-версию, чтобы быть уверенными в качестве приложения. Но при этом в связи с постоянной необходимостью использовать последнюю версию и частыми релизами нет возможности отказаться от динамического указания версии wiremock. Решением этой задачи будет написание собственных правил стратегии выбора версий зависимости:

Стоит отменить, что данное правило применится ко всем зависимостям, а не только к wiremock.
После чего, запустив задачу отображения дерева зависимостей в информационном режиме, мы увидим, как отбрасываются beta-версии библиотеки, и причину, по которой они были отброшены. В конечном итоге будет выбрана стабильная версия 1.58:


Но при тестировании было обнаружено, что в версии 1.58 присутствует критичный баг, и сборка не может быть выпущена в таком состоянии. Решить эту задачу можно, написав ещё одно правило выбора версии зависимости:

После чего версия wiremock 1.58 будет также отброшена, и начнёт использоваться версия 1.57, а дерево зависимостей будет выглядеть следующим образом:


Заключение

Несмотря на то, что статья получилась достаточно объемной, тема Dependency Management в Gradle содержит много не озвученной в рамках этой статьи информации. Глубже погрузиться в этот мир лучше всего получится с помощью официального User Guide в паре с документацией по Gradle DSL, в изучение которых придется инвестировать немало времени.

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

В данном разделе описывается структура и основные элементы скрипта build.gradle .

В секции buildscript задается следующее:

Версия платформы, на которой основан данный проект.

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

Зависимости, используемые системой сборки, включая плагин CUBA для Gradle.

После секции buildscript объявляются несколько переменных, используемых далее в скрипте.

Логика сборки, специфичная для CUBA, сосредоточена в Gradle плагине cuba . Он подключается в корне скрипта и в секциях configure каждого модуля:

Параметры плагина cuba задаются в секции cuba :

Рассмотрим доступные параметры:

artifact - задает группу и версию собираемых артефактов проекта. Имена артефактов формируются на основе имен модулей, заданных в settings.gradle .

group - группа артефактов.

version - версия артефактов.

isSnapshot - если установлено в true , то в именах артефактов будет присутствовать суффикс SNAPSHOT .

Версию артефактов можно переопределить в командной строке, например:

tomcat - задает параметры сервера Tomcat, который используется для быстрого развертывания.

dir - расположение каталога установки Tomcat.

port - порт сервера; по умолчанию 8080.

debugPort - порт для подключения Java отладчика; по умолчанию 8787.

shutdownPort - порт для передачи команды SHUTDOWN ; по умолчанию 8005.

ajpPort - порт AJP connector; по умолчанию 8009.

ide - задает некоторые параметры для Studio и IDE.

vcs - тип используемой в проекте VCS. В данный момент поддерживаются только Git и svn .

copyright - текст Copyright Notice, вставляемый в начало файлов исходных текстов.

classComment - текст комментария, который будет расположен над объявлением класса в исходных текстах Java.

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

url - URL репозитория. По умолчанию используется репозиторий Haulmont.

user - имя пользователя репозитория.

password - пароль пользователя репозитория.

Параметры репозитория выгрузки артефактов можно передать в командной строке с помощью следующих аргументов:

Секции configure описывают конфигурацию модулей. Наиболее важная часть конфигурации - описание зависимостей, например:

Есть возможность добавлять зависимости через конфигурацию server для модулей core, web и portal (модули, имеющие задачу с типом CubaDeployment ). Это имеет смысл в некоторых случаях, например, когда для варианта развёртывания с помощью UberJar обращение к зависимости происходит до старта приложения, а сама зависимость нужна для всех вариантов развёртывания в конкретном модуле. Тогда объявление отдельно на уровне модуля (что нужно, например, для случая развертывания опции WAR) и через конфигурацию uberJar на уровне проекта вызовет ненужное дублирование зависимости для UberJar. Такие зависимости при выполнении задач deploy , buildWar и buildUberJar будут помещаться в серверные библиотеки.

Блок entitiesEnhancing позволяет описать конфигурацию bytecode enhancement (weaving) классов сущностей. Его нужно объявить как минимум в модуле global, однако можно включить его в конфигурацию каждого модуля по-отдельности.

Секции main и test здесь - это наборы исходников проекта и тестов, а необязательный параметр persistenceConfig позволяет явно указать набор файлов persistence.xml. Если не установлено, задача будет обрабатывать все персистентные сущности, перечисленные в файлах *persistence.xml , найденных в CLASSPATH.

Нестандартные зависимости модулей можно задавать в Studio в экране Project properties > Advanced. См. также контекстную помощь Studio.

В случае транзитивных зависимостей и конфликта версий будет использована стандартная стратегия разрешения версий Maven. Согласно этой стратегии, релизные версии имеют приоритет над snapshot-версиями, а более точный числовой квалификатор имеет приоритет над более общим. При прочих равных, строковые квалификаторы приоритизируются в алфавитном порядке. Пример:

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

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

Дополнительное чтение:

  • Начало работы с Gradle: Введение поможет вам установить Gradle, описывает основные концепции сборки Gradle и описывает, как вы можете добавить функциональность в свою сборку с помощью плагинов Gradle.
  • Начало работы с Gradle: наш первый Java-проект описывает, как вы можете создать проект Java с помощью Gradle и упаковать свое приложение в исполняемый файл JAR.

Введение в управление хранилищем

Репозитории по сути являются контейнерами зависимостей, и каждый проект может использовать ноль или более репозиториев.

Gradle поддерживает следующие форматы репозитория:

Давайте выясним, как мы можем настроить каждый тип репозитория в нашей сборке.

Добавление репозитория плюща в нашу сборку

Мы можем добавить репозиторий Ivy в нашу сборку, используя его URL-адрес или расположение в локальной файловой системе.

Если мы хотим добавить репозиторий Ivy, используя его URL-адрес, мы должны добавить следующий фрагмент кода в файл build.gradle :

Если мы хотим добавить репозиторий Ivy, используя его местоположение в файловой системе, нам нужно добавить следующий фрагмент кода в файл build.gradle :

Если вы хотите получить больше информации о настройке репозиториев Ivy, вам следует проверить следующие ресурсы:

Давайте продолжим и узнаем, как мы можем добавить репозитории Maven в нашу сборку.

Добавление репозиториев Maven в нашу сборку

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

Если мы хотим добавить репозиторий Maven, используя его URL, мы должны добавить следующий фрагмент кода в файл build.gradle :

Если мы хотим добавить репозиторий Maven, используя его местоположение в файловой системе, мы должны добавить следующий фрагмент кода в файл build.gradle :

У Gradle есть три «псевдонима», которые мы можем использовать, когда добавляем репозитории Maven в нашу сборку. Эти псевдонимы:

  • Псевдоним mavenCentral () означает, что зависимости извлекаются из центрального хранилища Maven 2 .
  • Псевдоним jcenter () означает, что зависимости извлекаются из репозитория JCenter Maven Bintray .
  • Псевдоним mavenLocal () означает, что зависимости извлекаются из локального репозитория Maven.

Если мы хотим добавить центральный репозиторий Maven 2 в нашу сборку, мы должны добавить следующий фрагмент в наш файл build.gradle :

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

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

Добавление хранилищ плоских каталогов в нашу сборку

Если мы хотим использовать репозитории плоских каталогов, мы должны добавить следующий фрагмент кода в наш файл build.gradle :

Это означает, что зависимости ищутся из каталога lib . Также, если мы хотим, мы можем использовать несколько каталогов, добавив следующий фрагмент в файл build.gradle :

Если вы хотите получить больше информации о хранилищах плоских каталогов, вы должны проверить следующие ресурсы:

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

Введение в управление зависимостями

После того, как мы настроили репозитории нашего проекта, мы можем объявить его зависимости. Если мы хотим объявить новую зависимость, мы должны выполнить следующие шаги:

  1. Укажите конфигурацию зависимости.
  2. Объявите необходимую зависимость.

Давайте внимательнее посмотрим на эти шаги.

Группировка зависимостей в конфигурации

В Gradle зависимости группируются в именованный набор зависимостей. Эти группы называются конфигурациями, и мы используем их для объявления внешних зависимостей нашего проекта.

  • Зависимости, добавленные в конфигурацию компиляции , требуются при компиляции нашего исходного кода нашего проекта.
  • Конфигурация времени выполнения содержит зависимости, которые требуются во время выполнения. Эта конфигурация содержит зависимости, добавленные в конфигурацию компиляции .
  • Конфигурация testCompile содержит зависимости, необходимые для компиляции тестов нашего проекта. Эта конфигурация содержит скомпилированные классы нашего проекта и зависимости, добавленные в конфигурацию компиляции .
  • Конфигурация testRuntime содержит зависимости, которые требуются при запуске наших тестов. Эта конфигурация содержит зависимости, добавленные в конфигурации compile , runtime и testCompile .
  • Конфигурация архива содержит артефакты (например, файлы Jar), ​​созданные нашим проектом.
  • Группа конфигурации по умолчанию содержит зависимости, которые требуются во время выполнения.

Давайте продолжим и выясним, как мы можем объявить зависимости нашего проекта Gradle.

Объявление зависимостей проекта

Наиболее распространенные зависимости называются внешними зависимостями, которые находятся во внешнем репозитории. Внешняя зависимость определяется с помощью следующих атрибутов:

  • Атрибут group идентифицирует группу зависимости (пользователи Maven знают этот атрибут как groupId ).
  • Атрибут name идентифицирует имя зависимости (пользователи Maven знают этот атрибут как artifactId ).
  • Атрибут version указывает версию внешней зависимости (пользователи Maven знают этот атрибут как версию ).

Эти атрибуты обязательны при использовании репозиториев Maven. Если вы используете другие репозитории, некоторые атрибуты могут быть необязательными.

Давайте предположим, что мы должны объявить следующую зависимость:

  • Группа зависимости — ‘foo’.
  • Название зависимости — ‘foo’.
  • Версия зависимости — 0.1.
  • Зависимость требуется при компиляции нашего проекта.

Мы можем объявить эту зависимость, добавив следующий код в файл build.gradle :

Мы также можем объявить зависимости нашего проекта, используя ярлык, следующий синтаксису: [группа]: [имя]: [версия] . Если мы хотим использовать форму ярлыка, мы должны добавить следующий фрагмент кода в файл build.gradle :

Мы также можем добавить несколько зависимостей к одной и той же конфигурации. Если мы хотим использовать «нормальный» синтаксис при объявлении наших зависимостей, мы должны добавить следующий фрагмент кода в файл build.gradle :

С другой стороны, если мы хотим использовать форму ярлыка, соответствующая часть файла build.gradle выглядит следующим образом:

Естественно, можно объявить зависимости, которые принадлежат разным конфигурациям. Например, если мы хотим объявить зависимости, которые принадлежат конфигурациям compile и testCompile , мы должны добавить следующий фрагмент кода в файл build.gradle :

Опять же, можно использовать ярлык формы. Если мы хотим объявить те же зависимости с помощью формы ярлыка, соответствующая часть файла build.gradle выглядит следующим образом:

Вы можете получить больше информации об объявлении ваших зависимостей, прочитав раздел 50.4 Как объявить ваши зависимости в Руководстве пользователя Gradle .

Теперь мы изучили основы управления зависимостями. Давайте перейдем к реализации нашего примера приложения.

Создание примера приложения

Требования нашего примера приложения описаны в следующем:

Давайте выясним, как мы можем выполнить эти требования.

Конфигурирование репозиториев нашей сборки

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

attributes 'Main-Class' : 'net.petrikainulainen.gradle.HelloWorld'

Давайте двигаться дальше и объявим зависимости нашего примера приложения.

Объявление зависимостей нашего примера приложения

Мы должны объявить две зависимости в файле build.gradle :

После того, как мы объявили эти зависимости, файл build.gradle выглядит следующим образом (соответствующая часть выделена):

attributes 'Main-Class' : 'net.petrikainulainen.gradle.HelloWorld'

Давайте двигаться дальше и напишем некоторый код.

Написание кода

Чтобы выполнить требования нашего примера приложения, «мы должны его чрезмерно спроектировать». Мы можем создать пример приложения, выполнив следующие действия:

Давайте пройдемся по этим шагам один за другим.

Сначала мы должны создать класс MessageService в каталоге src / main / java / net / petrikainulainen / gradle и реализовать его. После того, как мы это сделаем, его исходный код будет выглядеть следующим образом:

Во-вторых , мы создали MessageServiceTest в каталоге src / main / test / net / petrikainulainen / gradle и записали модульный тест в метод getMessage () класса MessageService . Исходный код класса MessageServiceTest выглядит следующим образом:

assertEquals( "Hello World!" , messageService.getMessage()); private static final Logger LOGGER = Logger.getLogger(HelloWorld. class );

В-четвертых , мы должны настроить Log4j с помощью log4j.properties, который находится в каталоге src / main / resources . Файл log4j.properties выглядит следующим образом:

log4j.appender.Stdout.layout=org.apache.log4j.PatternLayout log4j.appender.Stdout.layout.conversionPattern=%-5p - %-26.26c <1>- %m\n

Вот и все. Давайте выясним, как мы можем запустить тесты нашего примера приложения.

Запуск юнит-тестов

Мы можем запустить наш модульный тест с помощью следующей команды:

Когда наш тест пройден, мы видим следующий вывод:

Однако, если наш модульный тест не пройден, мы увидим следующий результат (интересный раздел выделен):

net.petrikainulainen.gradle.MessageServiceTest > getMessage_ShouldReturnMessageFAILED > There were failing tests. See the report at: file : ///Users/loke/Projects/Java/Blog/gradle-examples/dependency-management/build/reports/tests/index .html Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

Как мы видим, если наши модульные тесты не пройдены, описываются:

  • какие тесты не удалось.
  • сколько тестов было выполнено и сколько тестов не удалось.
  • расположение отчета о тестировании, в котором содержится дополнительная информация о неудачных (и пройденных) тестах.

Когда мы запускаем наши модульные тесты, Gradle создает отчеты о тестировании в следующих каталогах:

  • Каталог build / test-results содержит необработанные данные каждого запуска теста.
  • Каталог build / reports / tests содержит HTML-отчет, который описывает результаты наших тестов.

Отчет о тестировании HTML является очень полезным инструментом, потому что он описывает причину, по которой наш тест не прошел Например, если наш модульный тест ожидает, что метод getMessage () класса MessageService возвращает строку «Hello Worl1d!», Отчет о тестировании HTML этого теста будет выглядеть следующим образом:

testfailure

Давайте продолжим и выясним, как мы можем упаковать и запустить наш пример приложения.

Читайте также: