Ответ 1
Вы можете достичь этого с помощью Gradle плагина приложения
как экспортировать исполняемую банку в gradle, и эта банка может запускаться, поскольку она включает в себя справочные библиотеки.
build.gradle
apply plugin: 'java'
manifest.mainAttributes("Main-Class" : "com.botwave.analysis.LogAnalyzer")
repositories {
mavenCentral()
}
dependencies {
compile (
'commons-codec:commons-codec:1.6',
'commons-logging:commons-logging:1.1.1',
'org.apache.httpcomponents:httpclient:4.2.1',
'org.apache.httpcomponents:httpclient:4.2.1',
'org.apache.httpcomponents:httpcore:4.2.1',
'org.apache.httpcomponents:httpmime:4.2.1',
'ch.qos.logback:logback-classic:1.0.6',
'ch.qos.logback:logback-core:1.0.6',
'org.slf4j:slf4j-api:1.6.0',
'junit:junit:4.+'
)
}
после запуска i: gradle build
он создает папку сборки, и я запускаю jar в файле build/libs/XXX.jar:
java -jar build/libs/XXX.jar
вот исполнение:
Exception in thread "main" java.lang.NoClassDefFoundError: ch/qos/logback/core/joran/spi/JoranException
как я могу запустить его с помощью библиотек ссылок?
Вы можете достичь этого с помощью Gradle плагина приложения
Надеюсь, это поможет кому-то (поскольку, к сожалению, я потратил некоторое время на поиск решения). Вот решение, которое работало для меня для создания исполняемого JAR. Я внедряю Jetty в основной метод, Jetty 9, чтобы быть конкретным и использовать Gradle 2.1.
Включите следующий код в свой файл build.gradle(если подпроект является "основным" проектом, из которого необходимо построить банку, а затем добавьте его в подпроект, который должен начинаться как этот проект (':') { вставьте код где-то здесь, после зависимостей.}.
Кроме того, вам нужно добавить плагин java для этого: apply plugin: 'java'.
Моя задача jar выглядит следующим образом:
apply plugin: 'java'
jar {
archiveName = "yourjar.jar"
from {
configurations.runtime.collect {
it.isDirectory() ? it : zipTree(it)
}
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes 'Main-Class': 'your.package.name.Mainclassname'
}
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
}
И затем вы можете выполнить свой yourjar.jar через командную строку:
java -jar yourjar.jar
Для этого необходимо исключить DSA META-INF/.RSA, META-INF/.SF и META-INF/*. В противном случае возникает исключение SecurityException.
Проблема, похоже, связана с встроенным Jetty, поскольку Jetty переместился в Eclipse и теперь подписывает их JAR, который, как я прочитал, становится проблематичным, когда другие, без знака JAR хотят загрузить подписанные. Пожалуйста, не стесняйтесь воспитывать меня, если я ошибаюсь в этом, это то, что я читаю.
JAR, от которых зависит проект, определяются в зависимостях следующим образом:
dependencies {
// add the subprojects / modules that this depends on
compile project(':subproject-1')
compile project(':subproject-2')
compile group: 'org.eclipse.jetty', name: 'jetty-server', version: '9.2.6.v20141205'
compile group: 'org.eclipse.jetty', name: 'jetty-servlet', version: '9.2.6.v20141205'
compile group: 'org.eclipse.jetty', name: 'jetty-http', version: '9.2.6.v20141205'
}
EDIT: прежде чем вместо
configurations.runtime.collect{...}
Я имел
configurations.runtime.asFileTree.files.collect{...}
Это вызвало странное поведение в более крупном проекте в чистой сборке. При запуске jar после выполнения Gradle чистой сборки в первый раз (после ручной очистки каталога сборки) он выкинет NoClassDefFoundException (в нашем проекте со многими подпроектами), но запустил jar после выполнения Gradle clean build a второй раз (без опустошения каталога сборки вручную), по какой-то причине он имел все зависимости. Этого не произошло, если asFileTree.files был исключен.
Также я должен отметить, что все компиляционные зависимости включены во время выполнения, однако не все время исполнения включено в компиляцию. Поэтому, если вы просто используете компиляцию
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
Затем обязательно помните, что если возникает NoClassDefFoundException, некоторый класс не найден во время выполнения, что означает, что вы также должны включить это:
configurations.runtime.collect {
it.isDirectory() ? it : zipTree(it)
}
Добавьте в свой build.gradle
следующее:
apply plugin: 'application'
mainClassName = 'org.example.app.MainClass'
jar {
manifest {
attributes 'Main-Class': mainClassName,
'Class-Path': configurations.runtime.files.collect {"$it.name"}.join(' ')
}
}
gradle installDist
java -jar build/install/<appname>/lib/<appname>.jar
Я рекомендую добавить версию приложения к вашему build.gradle
, но это не требуется. Если вы это сделаете, имя встроенного баннера будет <appname>-<version>.jar
.
Примечание. Я использую gradle 2.5
Чтобы создать автономную исполняемую банку, которую можно просто запустить с помощью:
java -jar appname.jar
вам понадобится:
Как показывают некоторые другие ответы, вы можете использовать сторонний плагин для достижения этого, например shadow или one-jar.
Я попробовал тень, но мне не понравилось, что все мои зависимости и их ресурсы были выгружены в встроенную банку вместе с моим кодом приложения. Я также предпочитаю минимизировать использование внешних плагинов.
Другим вариантом было бы использовать gradle плагин приложения, как указано выше. Запуск gradle build
будет создавать банку для вас и красиво связывать ее со всеми вашими зависимостями в файле zip/tar. Вы также можете запустить gradle installDist
, чтобы пропустить zipping.
Однако, поскольку @jeremyjjbrown написал в комментарии там, плагин не создает сам исполняемый банку. Он создает банку и script, который создает путь к классам и выполняет команду для запуска основного класса вашего приложения. Вы не сможете запустить java -jar appname.jar
.
Чтобы получить лучшее из обоих миров, выполните описанные выше шаги, которые создают вашу банку вместе со всеми вашими зависимостями в виде отдельных банок и добавьте правильные значения в ваш MANIEST.
Я проверил довольно некоторые ссылки для решения, наконец, сделал следующие шаги, чтобы заставить его работать. Я использую Gradle 2.9.
Внесите следующие изменения в файл сборки: gradle:
1. Указать плагин:
apply plugin: 'eu.appsatori.fatjar'
2. Предоставьте Buildscript:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "eu.appsatori:gradle-fatjar-plugin:0.3"
}
}
3. Предоставить основной класс:
fatJar {
classifier 'fat'
manifest {
attributes 'Main-Class': 'my.project.core.MyMainClass'
}
exclude 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.SF'
}
4. Создайте жир:
./gradlew clean fatjar
5. Запустите fatjar из /build/libs/:
java -jar MyFatJar.jar
Все эти ответы либо ошибочны, либо устарели.
ОП просит о том, что известно как "жирная банка". Это сложная банка, которая содержит все зависимости, чтобы она не требовала внешних зависимостей для запуска (за исключением JRE, конечно!).
Ответ на момент написания - это плагин Gradle Shadow Jar, хорошо понятный в Руководство пользователя и примеры теневого плагина.
Потому что я невежественный человек, но я все же немного боролся. Более конкретно, я использовал Gradle в течение нескольких месяцев, как это "окно волшебных трюков". Половина времени я действительно не знаю, что он делает слишком хорошо, или как он это делает (не в большой степени заинтересован в том, чтобы попасть в Groovy язык в настоящее время). Просто знайте, что он работает, чтобы выполнить тестирование и запуск файлов, которые я хочу сделать.
Сделайте так:
поместите все эти строки где-нибудь в файл build.gradle(я положил их вверху):
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.4'
}
}
apply plugin: 'com.github.johnrengelman.shadow'
shadowJar {
baseName = 'shadow'
classifier = null
version = null
}
jar {
manifest {
attributes 'Class-Path': '/libs/a.jar'
attributes 'Main-Class': 'core.MyClassContainingMainMethod'
}
}
PS не беспокойтесь о каких-либо других строках "репозиториев", "зависимостей" или "плагинов" в другом месте вашего файла сборки, а do оставить строки таким образом внутри этого блока "buildscript" (I не знаю, зачем вам это нужно).
PPS Руководство пользователя и примеры плагинов плагинов хорошо написано, но не говорит вам для включения строки
attributes 'Main-Class': 'core.MyClassContainingMainMethod'
где я поставил его выше. Возможно, потому, что автор предполагает, что вы менее невежественны, чем я, и вы, вероятно, так и есть. У меня нет подсказки, почему нам говорят, чтобы этот странный атрибут Class-Path был включен, но если он не сломался, не исправляйте его.
Когда вы переходите
> gradle shadowjar
Gradle, мы надеемся, создадим жирный исполняемый jar под /build/libs (имя по умолчанию "shadow.jar" ), которое вы можете запустить, выполнив это:
> java -jar shadow.jar