由 Gradle 构建的 JAR 找不到 Gson



问题已经解决,请阅读最后一节

"背景">


我制作ToDoApp只是为了一个附带项目,作为学习Gradle的借口。最初的构建运行良好,JAR也按预期运行[a]。但该版本没有外部依赖关系;它是独立的。

我被鼓励在项目中添加持久性,并决定使用GSON库(2.6.2版)来处理JSON。我使用IntelliJ IDEA(2016.1.2)来编写代码。

现在,我通过IntelliJ中的Maven Repository选项添加了gson-2.6.2工件(在项目结构中)。在编写代码时,当IntelliJ提示时,我将库添加到项目的类路径中。当我在IDE中运行该代码时,该代码可以编译并正常工作。下面是一个运行示例:

========ToDo App========

The following commands are recognised:
► help
Display this help message.
► add <name>
Add a new Todo task with the given name and also displays its corresponding ID.
► get <id>
Displays the task with the given id.
► mark <id>
Toggles the given task as completed or incomplete.
► print
Displays all tasks in order of their creation.
► update <id> <new text>
Updates the item with the given id to store the new text.
► del <id>
Deletes the task with the given id.
► exit
Exit the program.

The tasks are :
>> add Get the Gradle build to work. 
New item added with id = 1
>> add Push the stable system to GitHub and wait for Travis to give the green signal.
New item added with id = 2
>> add Proceed
New item added with id = 3
>> print
The tasks are :
•  Get the Gradle build to work.  [ID: 1 Completed: false]
•  Push the stable system to GitHub and wait for Travis to give the green signal. [ID: 2 Completed: false]
•  Proceed [ID: 3 Completed: false]
>> exit

它运行良好。JSON数据按照我的预期保存:

{"currentId":3,"toDos":{"1":{"id":1,"name":" Get the Gradle build to work. ","completed":false},"2":{"id":2,"name":" Push the stable system to GitHub and wait for Travis to give the green signal.","completed":false},"3":{"id":3,"name":" Proceed","completed":false}}}

当我重新运行代码时,数据会被正确地读回。我对我的代码很满意。

"情况">


这是我的build.gradle:

group 'ml.cristatus'
version = '0.2'
apply plugin: 'java'
sourceCompatibility = 1.7
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.code.gson:gson:2.6.2'
}
jar {
manifest {
attributes 'Main-Class': 'ml.cristatus.todo.ToDoApp'
}
}

当我在Ubuntu16.04终端上运行gradle build时,JAR文件会生成以下输出:

:compileJava
warning: [options] bootstrap class path not set in conjunction with -source 1.7
1 warning
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build
BUILD SUCCESSFUL
Total time: 7.036 secs
This build could be faster, please consider using the Gradle Daemon: https://docs.gradle.org/2.13/userguide/gradle_daemon.html

所以我设法把它编译了。但当我尝试使用java -jar build/libs/ToDoApp-0.2.jar运行它时,代码不起作用:

========ToDo App========

Exception in thread "main" java.lang.NoClassDefFoundError: com/google/gson/Gson
at ml.cristatus.todo.repository.ToDoRepositoryWithJSON.<init>(ToDoRepositoryWithJSON.java:25)
at ml.cristatus.todo.ToDoApp.REPL(ToDoApp.java:38)
at ml.cristatus.todo.ToDoApp.main(ToDoApp.java:17)
Caused by: java.lang.ClassNotFoundException: com.google.gson.Gson
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 3 more

我可能犯了一些新手的错误,但我似乎无法理解。我做错了什么值得注意的是,代码编译后却找不到gson工件。我猜这和类路径有关吧?我不知道。我不确定。

请在这方面帮助我。

解决方案

我刚刚在jar {}块中添加了这一行:

from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }

由本教程提供


[a]这是0.1版本的二进制文件。

您必须将带有gson jar的jar文件添加到类路径中。当您启动应用程序时("java-jarbuild/libs/ToDoApp-0.2.jar">)。有多种方法可以实现它。

一种可能的方法是:

将task添加到您的gradle中,它将依赖项(在您的案例中为gson.jar)复制到"lib"目录中。当您启动应用程序时,将其添加到类路径中。例如,通过这种方式"java-cp build/lib/gson.jar-jar build/libs/ToDoApp-0.2.jar">

也许对你更好的是:

将依赖项添加到清单中。在这个答案中讨论了如何在gradle中复制依赖关系库JAR它应该对你有用。

下一个选项是:

创建一个"uberjar"意味着将所有依赖项添加到一个大jar文件中。就我个人而言,我不喜欢它。但对你来说,它会起作用的。这里讨论了如何在gradle中创建uberjar:使用Gradle构建uberjar

最新更新