如何在Gradle中无需重新编译即可动态使用外部JDBC Jar包
问题描述
刚接触Gradle,现有一个用Gradle构建的Java项目,通过Application插件(底层依赖Java插件)生成fat jar。希望在不同部署环境中,无需重新编译就能使用对应数据库(Oracle、Postgres、DB2等)的JDBC Jar包。此前使用ANT时,只需将JDBC Jar包放入lib文件夹,应用即可直接识别使用,无需编译。
目前尝试两种方法均未成功:
- 添加依赖
runtimeOnly fileTree('lib') { include '*.jar' }:每次向lib文件夹添加新Jar包都需要重新编译。 - 在
sourceSets中设置runtimeClasspath:
sourceSets { main { java { runtimeClasspath = fileTree('lib') { include '*.jar' } } } }
该配置没有任何效果。
附上当前build.gradle配置:
plugins { id 'application' // implicitly applies java and distribution, see https://docs.gradle.org/7.4/userguide/application_plugin.html id 'com.github.johnrengelman.shadow' version '7.1.2' // For fat jars } repositories { mavenCentral() } dependencies { implementation 'org.apache.poi:poi:5.2.3' implementation 'org.apache.poi:poi-ooxml:5.2.3' // : // more implementation dependencies... // : // runtimeOnly fileTree('lib') { include '*.jar' } <- requires compilation } java { toolchain { languageVersion = JavaLanguageVersion.of(17) } } application { mainClass = 'my_pkg.ProcessAll' } shadowJar { archiveBaseName.set('MyApp') classifier = null } sourceSets { main { java { runtimeClasspath = fileTree('lib') { include '*.jar' } // <- doesn't work } } }
解决方案
要实现无需重新编译即可切换不同环境的JDBC驱动,核心是不要把驱动Jar包打包进fat jar,而是在运行时动态加载部署环境下的驱动文件。具体操作如下:
1. 清理无效配置
删除build.gradle中sourceSets下的runtimeClasspath配置,同时不要将lib目录的Jar包声明为Gradle依赖(否则修改lib目录会触发重新编译)。
2. 配置shadowJar排除驱动Jar包
确保生成的fat jar不包含任何JDBC驱动,修改shadowJar配置块:
shadowJar { archiveBaseName.set('MyApp') classifier = null // 排除项目根目录lib下的所有Jar包,不打包进fat jar exclude 'lib/*.jar' }
3. 运行时手动指定类路径
部署时,将对应环境的JDBC驱动Jar包放到项目的lib目录,然后用以下命令启动应用:
- Linux/macOS:
java -cp "MyApp.jar:lib/*" my_pkg.ProcessAll
- Windows:
java -cp "MyApp.jar;lib\*" my_pkg.ProcessAll
可选:用Application插件生成自动加载的启动脚本
如果希望用启动脚本简化操作,可配置application插件的JVM参数,让脚本自动加载lib目录的驱动:
application { mainClass = 'my_pkg.ProcessAll' // 设置JVM参数,让启动脚本自动加载APP_HOME下lib目录的Jar包 applicationDefaultJvmArgs = ["-cp", "\$APP_HOME/lib/*:\$APP_HOME/MyApp.jar"] }
执行gradle installDist生成部署包,将JDBC驱动放到build/install/MyApp/lib目录后,直接运行bin/MyApp(Linux/macOS)或bin/MyApp.bat(Windows)即可启动应用。
内容的提问来源于stack exchange,提问作者Rafs
相关产品推荐
相关产品推荐

