如何通过命令行运行Spring Boot可执行Jar中的非主类?
首先得明确为什么你的命令会失败:Spring Boot的可执行Jar采用了嵌套归档结构——应用类都被打包在BOOT-INF/classes/目录下,依赖Jar在BOOT-INF/lib/里,而标准Java的类加载器无法识别这种嵌套在Jar内部的类路径结构,所以直接用java -cp找不到你的工具类。
下面给你几个可行的解决方案,按推荐程度排序:
方案一:打包时生成两个Jar(推荐)
修改你的Gradle配置,在生成默认的Spring Boot可执行Jar之外,额外生成一个普通的、未嵌套的Jar,专门用来运行工具类。这样既能保留原有的可执行Jar,又能方便地直接调用工具类:
// 定义一个任务,生成包含所有应用类的普通Jar task plainJar(type: Jar) { baseName = 'client-stp-grid-publisher-plain' // 直接打包源码编译后的输出文件 from sourceSets.main.output } // 让build任务自动触发这个plainJar的构建 build.dependsOn(plainJar)
执行gradle build后,你会在build/libs目录下得到两个Jar:
client-stp-grid-publisher-SNAPSHOT.jar:原来的Spring Boot可执行Jarclient-stp-grid-publisher-plain.jar:普通Jar,包含所有应用类
之后直接用这个普通Jar运行工具类即可:
java -cp client-stp-grid-publisher-plain.jar com.client.stp.util.JMXClientUtils
如果工具类依赖第三方Jar,你需要把依赖也加入类路径,或者可以修改plainJar任务,把依赖也打包进去(做成fatJar,但体积会更大):
task plainFatJar(type: Jar) { baseName = 'client-stp-grid-publisher-plain-fat' from sourceSets.main.output // 打包所有依赖 from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } }
方案二:临时解压后运行
如果不想修改打包配置,可以临时把可执行Jar里的类和依赖解压出来,再指定类路径运行:
# 创建临时目录并解压必要的内容 unzip client-stp-grid-publisher-SNAPSHOT.jar BOOT-INF/classes/* BOOT-INF/lib/* -d temp-stp-dir # 运行工具类(Linux/macOS用冒号分隔类路径,Windows用分号) java -cp "temp-stp-dir/BOOT-INF/classes:temp-stp-dir/BOOT-INF/lib/*" com.client.stp.util.JMXClientUtils
这种方式适合临时测试,每次运行都需要解压,比较繁琐。
方案三:用Spring Boot的PropertiesLauncher指定主类(不推荐,除非工具类无Spring依赖)
Spring Boot提供了PropertiesLauncher,可以通过参数指定要运行的主类。这种方式不需要修改打包配置,但会通过Spring Boot的类加载器来启动,虽然不会初始化Spring应用上下文,但还是会加载Spring Boot相关类:
首先确保你的MANIFEST.MF里的Main-Class是org.springframework.boot.loader.PropertiesLauncher(如果不是,可以修改Gradle的jar任务配置):
jar { baseName = 'client-stp-grid-publisher' manifest { attributes( 'Main-Class': 'org.springframework.boot.loader.PropertiesLauncher' ) } }
然后运行时指定要执行的工具类:
java -Dloader.main=com.client.stp.util.JMXClientUtils -jar client-stp-grid-publisher-SNAPSHOT.jar
如果你的工具类完全不依赖Spring环境,这个方法可以用,但如果想彻底脱离Spring Boot的类加载环境,还是前两个方案更合适。
内容的提问来源于stack exchange,提问作者Shashi Shankar

