Gradle 和 Spring-bootRun 找不到我的 class
Gradle and Spring-bootRun can not find my class
有两个项目:
- 经典(有主要class)
- 高级
我想让 Advanced 拥有 Classic
的所有 classes。但正如我 运行 Advanced/gradle bootRun
所有 Advanced
classes 似乎都丢失了。
Advanced/src/main/java/foo/Bar.java:
package foo;
public class Bar{
//empty
}
Classic/src/main/java/foo/Classic.java:
package foo;
public class Classic {
public static void main(){
try {
Class.forName("foo.Bar");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
异常:
java.lang.ClassNotFoundException: foo.Bar
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:340)
at foo.Classic.main(Classic.java:14)
java.lang.ClassNotFoundException: foo.Bar
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:144)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:340)
at foo.Classic.main(Classic.java:14)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
我的 Advanced/build 里有这个。gradle:
...
dependencies{
...
implementation project(':classic')
...
}
...
来自评论的重要信息:
Jacob G.
我在其中一个聊天室与 OP 交谈了一会儿,我发现了一些事情。当尝试使用 Gradle 构建 Advanced 项目时,它报告了 50 多个关于找不到包的编译错误:,指的是 Classic 项目中的包。此外,Classic 和 Advanced 不共享根项目,所以我觉得尝试依赖 project(':classic') 是徒劳的。 OP 声明只能提交到 Advanced,因此可能根本无法解决该问题。对于任何好奇的人,OP 也没有使用 IDE.
尊重声明
我对问题进行了编辑,添加了一个限制。这是一个非常重要的编辑,我只能在 Advanced 中提交更改。因为我没有 gradle 方面的经验,所以我没有意识到这些附加信息的重要性。晚限深表歉意,礼遇倍感欣慰,望谅解
我也有和你一样的项目结构,所以通过进行下面提到的更改它对我来说效果很好:
- build.gradle 文件中的条目
compile project(':Classic')
- 进入 settings.gradle
include ':Classic'
project(':Classic').projectDir = new File(settingsDir, '../../libs/Classic')
我希望这对你也有用,是的,不要忘记在进行这些更改后重建你的成绩项目。
据我从问题中可以理解,我们正在处理一个多项目场景。在这种情况下,multi project builds documentation 告诉我们必须在包含两个项目的文件夹中有一个 settings.gradle:
然后可以 运行 两个项目都没有 cd
将目录更改到特定文件夹,但直接从多项目根目录通过命令:gradle advanced:bootRun
根据 20200610 编辑问题 确认规范:只能对 Advanced
项目 提交.
我们仍然可以获得解决方案,但在这种情况下(实际上不是 gradle 多项目)
不需要在Advanced
的父目录级别有settings.gradle
;它满足无法在 Advanced
之外提交的要求
Classic
项目是如何构建的并不重要,我们不关心它,因为我们不能提交它
我们不能在 Advanced/build.gradle
中使用 implementation project(':classic')
作为依赖项,因为这仅适用于 真实 gradle 多项目场景;在这里我们必须使用 文件依赖项 或另一个可用于用户开发环境的 type of dependecy。
在这种情况下,可以通过 cd Advanced
然后从 Advanced 目录 运行 th 命令来 运行 Advanced 项目: gradle bootRun
为什么有效?
..为了更好地理解它是如何工作的,让我们检查一下
SystemClassLoader
的当前路径通过在Advanced/src/main/java/com/example/springboot/Application.java
中添加这行代码
ClassLoader cl = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader)cl).getURLs();
for(URL url: urls){
System.out.println(url.getFile());
}
输出是:
<multi-project-root>/Advanced/build/classes/java/main/
<multi-project-root>/Advanced/build/resources/main/
<multi-project-root>/Classic/build/libs/Classic-0.0.1-SNAPSHOT.jar
~/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring
... [suppressed many othe spring devtools and gradle related caches ]
这允许高级版和经典版 类 找到彼此
概念证明的源代码
你需要的是Gradle的composite build. See my POC project。
高级项目包括this line
的经典项目
advanced/App.java调用classic.App.main, And the classic.App class可以从高级项目加载foo.Bar。无需提交经典项目。
在高级文件夹中执行"gradlew run"
看看它是如何工作的。
有两个项目:
- 经典(有主要class)
- 高级
我想让 Advanced 拥有 Classic
的所有 classes。但正如我 运行 Advanced/gradle bootRun
所有 Advanced
classes 似乎都丢失了。
Advanced/src/main/java/foo/Bar.java:
package foo;
public class Bar{
//empty
}
Classic/src/main/java/foo/Classic.java:
package foo;
public class Classic {
public static void main(){
try {
Class.forName("foo.Bar");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
异常:
java.lang.ClassNotFoundException: foo.Bar
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:340)
at foo.Classic.main(Classic.java:14)
java.lang.ClassNotFoundException: foo.Bar
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:144)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:340)
at foo.Classic.main(Classic.java:14)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
我的 Advanced/build 里有这个。gradle:
...
dependencies{
...
implementation project(':classic')
...
}
...
来自评论的重要信息:
Jacob G.
我在其中一个聊天室与 OP 交谈了一会儿,我发现了一些事情。当尝试使用 Gradle 构建 Advanced 项目时,它报告了 50 多个关于找不到包的编译错误:,指的是 Classic 项目中的包。此外,Classic 和 Advanced 不共享根项目,所以我觉得尝试依赖 project(':classic') 是徒劳的。 OP 声明只能提交到 Advanced,因此可能根本无法解决该问题。对于任何好奇的人,OP 也没有使用 IDE.
尊重声明
我对问题进行了编辑,添加了一个限制。这是一个非常重要的编辑,我只能在 Advanced 中提交更改。因为我没有 gradle 方面的经验,所以我没有意识到这些附加信息的重要性。晚限深表歉意,礼遇倍感欣慰,望谅解
我也有和你一样的项目结构,所以通过进行下面提到的更改它对我来说效果很好:
- build.gradle 文件中的条目
compile project(':Classic')
- 进入 settings.gradle
include ':Classic' project(':Classic').projectDir = new File(settingsDir, '../../libs/Classic')
我希望这对你也有用,是的,不要忘记在进行这些更改后重建你的成绩项目。
据我从问题中可以理解,我们正在处理一个多项目场景。在这种情况下,multi project builds documentation 告诉我们必须在包含两个项目的文件夹中有一个 settings.gradle:
然后可以 运行 两个项目都没有 cd
将目录更改到特定文件夹,但直接从多项目根目录通过命令:gradle advanced:bootRun
根据 20200610 编辑问题 确认规范:只能对 Advanced
项目 提交.
我们仍然可以获得解决方案,但在这种情况下(实际上不是 gradle 多项目)
不需要在
Advanced
的父目录级别有settings.gradle
;它满足无法在Advanced
之外提交的要求
Classic
项目是如何构建的并不重要,我们不关心它,因为我们不能提交它我们不能在
Advanced/build.gradle
中使用implementation project(':classic')
作为依赖项,因为这仅适用于 真实 gradle 多项目场景;在这里我们必须使用 文件依赖项 或另一个可用于用户开发环境的 type of dependecy。
在这种情况下,可以通过 cd Advanced
然后从 Advanced 目录 运行 th 命令来 运行 Advanced 项目: gradle bootRun
为什么有效?
..为了更好地理解它是如何工作的,让我们检查一下
SystemClassLoader
的当前路径通过在Advanced/src/main/java/com/example/springboot/Application.java
ClassLoader cl = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader)cl).getURLs();
for(URL url: urls){
System.out.println(url.getFile());
}
输出是:
<multi-project-root>/Advanced/build/classes/java/main/
<multi-project-root>/Advanced/build/resources/main/
<multi-project-root>/Classic/build/libs/Classic-0.0.1-SNAPSHOT.jar
~/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring
... [suppressed many othe spring devtools and gradle related caches ]
这允许高级版和经典版 类 找到彼此
概念证明的源代码
你需要的是Gradle的composite build. See my POC project。 高级项目包括this line
的经典项目advanced/App.java调用classic.App.main, And the classic.App class可以从高级项目加载foo.Bar。无需提交经典项目。
在高级文件夹中执行"gradlew run"
看看它是如何工作的。