在使用 spring-boot-maven-plugin 创建的嵌套可执行 jar 中启动 main class
Launching main class inside a nested executable jar created with spring-boot-maven-plugin
我有一个简单的 Spring 引导 class 像这样:
@SpringBootApplication
public class Starter {
public static void main(String... args) {
if ("foo".equals(args[0])) {
SpringApplication.run(Foo.class, args);
} else if ("bar".equals(args[0])) {
SpringApplication.run(Bar.class, args);
}
}
}
Foo.java 和 Bar.java 文件是作为依赖项嵌套在当前 jar 文件中的主要 class 文件,并且还使用 @SpringBootApplication 进行注释。 jar文件结构如下所示。
├───BOOT-INF
│ ├───classes
│ │ ├───com
│ │ │ └───app
│ │ │ └───starter
│ │ │ └───Starter.class
| | |
│ │ └───config
│ └───lib
| ├───tool1.jar
| | └───Foo.java
| └───tool2.jar
| └───Bar.java
├───META-INF
│ └───maven
│ └───com.app.starter
│ └───starter
└───org
└───springframework
└───boot
└───loader
├───archive
├───data
├───jar
└───util
虽然当我尝试启动 Starter.java 时这在 eclipse 中运行良好,但是当我尝试使用 maven 构建项目时出现异常:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project starter: Compilation failure: Compilation failure:
[ERROR] /C:/Projects/Starter/src/main/java/com/app/starter/Starter.java:[6,19] cannot find symbol
[ERROR] symbol: class Starter
这是 Starter POM 文件的摘录:
<project>
.....
<parent>
<groupId>com.app.myproject</groupId>
<artifactId>parent-tool</artifactId>
<version>1.0</version>
</parent>
<artifactId>starter</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.app.myproject</groupId>
<artifactId>foo-project</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.app.myproject</groupId>
<artifactId>bar-project</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
项目结构是这样的:
我有一个聚合器 POM 作为父项目,它也已将父项目声明为 spring-boot-starter。 Foo、Bar 和 Starter 项目都是父项目的子项目。
我想用 spring-boot-maven-plugin 嵌套所有依赖项来制作一个 fat jar。这样我就可以根据传递的参数从 starter main class 启动我想要的任何项目。 spring-boot 可以吗?我也试过用 classloader 调用 Foo 和 Bar 中的主要方法,但这种方法不起作用。可能是我做错了什么,因为我是 classloading 的新手。
URLClassLoader cl = URLClassLoader.newInstance(new URL[] {new URL("tool1.jar")});
Class myClass = cl.loadClass("com.app.Foo");
Method mainMethod = myClass.getMethod("main");
Object myClassObj = myClass.newInstance();
Object response = mainMethod.invoke(myClassObj);
有人可以建议用什么方法实现这个吗?非常感谢任何想法。
经过长时间的研究并在我的团队领导的帮助下,我终于找到了解决方案。它实际上是 spring-boot-maven 插件创建的可执行 jar 依赖的问题。我的初学者 class 无法在依赖列表中找到 Foo.java 或 Bar.java,因为这些 jar 也是可执行的 jar。最后,我在我的 foo-project 和 bar-project POM 文件中添加了这些行:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
这使得 foo-project 和 bar-project jar 成为通用的,一切都按预期工作。
希望这对使用 spring-boot-maven 插件的人有所帮助。
我有一个简单的 Spring 引导 class 像这样:
@SpringBootApplication
public class Starter {
public static void main(String... args) {
if ("foo".equals(args[0])) {
SpringApplication.run(Foo.class, args);
} else if ("bar".equals(args[0])) {
SpringApplication.run(Bar.class, args);
}
}
}
Foo.java 和 Bar.java 文件是作为依赖项嵌套在当前 jar 文件中的主要 class 文件,并且还使用 @SpringBootApplication 进行注释。 jar文件结构如下所示。
├───BOOT-INF │ ├───classes │ │ ├───com │ │ │ └───app │ │ │ └───starter │ │ │ └───Starter.class | | | │ │ └───config │ └───lib | ├───tool1.jar | | └───Foo.java | └───tool2.jar | └───Bar.java ├───META-INF │ └───maven │ └───com.app.starter │ └───starter └───org └───springframework └───boot └───loader ├───archive ├───data ├───jar └───util
虽然当我尝试启动 Starter.java 时这在 eclipse 中运行良好,但是当我尝试使用 maven 构建项目时出现异常:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project starter: Compilation failure: Compilation failure:
[ERROR] /C:/Projects/Starter/src/main/java/com/app/starter/Starter.java:[6,19] cannot find symbol
[ERROR] symbol: class Starter
这是 Starter POM 文件的摘录:
<project>
.....
<parent>
<groupId>com.app.myproject</groupId>
<artifactId>parent-tool</artifactId>
<version>1.0</version>
</parent>
<artifactId>starter</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.app.myproject</groupId>
<artifactId>foo-project</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.app.myproject</groupId>
<artifactId>bar-project</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
项目结构是这样的:
我有一个聚合器 POM 作为父项目,它也已将父项目声明为 spring-boot-starter。 Foo、Bar 和 Starter 项目都是父项目的子项目。
我想用 spring-boot-maven-plugin 嵌套所有依赖项来制作一个 fat jar。这样我就可以根据传递的参数从 starter main class 启动我想要的任何项目。 spring-boot 可以吗?我也试过用 classloader 调用 Foo 和 Bar 中的主要方法,但这种方法不起作用。可能是我做错了什么,因为我是 classloading 的新手。
URLClassLoader cl = URLClassLoader.newInstance(new URL[] {new URL("tool1.jar")});
Class myClass = cl.loadClass("com.app.Foo");
Method mainMethod = myClass.getMethod("main");
Object myClassObj = myClass.newInstance();
Object response = mainMethod.invoke(myClassObj);
有人可以建议用什么方法实现这个吗?非常感谢任何想法。
经过长时间的研究并在我的团队领导的帮助下,我终于找到了解决方案。它实际上是 spring-boot-maven 插件创建的可执行 jar 依赖的问题。我的初学者 class 无法在依赖列表中找到 Foo.java 或 Bar.java,因为这些 jar 也是可执行的 jar。最后,我在我的 foo-project 和 bar-project POM 文件中添加了这些行:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
这使得 foo-project 和 bar-project jar 成为通用的,一切都按预期工作。
希望这对使用 spring-boot-maven 插件的人有所帮助。