如何用Gradle构建含不同变量值的多版本Jar包
实现多客户端Jar包构建方案
你可以通过Gradle动态创建任务的方式,批量生成对应客户端的Jar包,同时完成属性替换或源码常量替换。以下是两种可行方案:
方案一:基于属性文件的替换(贴合你的初始思路)
这种方式通过expand替换资源文件中的占位符,主类读取属性文件获取客户端名称,无需修改Java源码结构。
1. 配置客户端列表
在build.gradle中定义客户端名称和对应的标识(用于Jar包命名):
def clients = [ [name: 'Client A', id: 'client-a'], [name: 'Client B', id: 'client-b'] ]
2. 添加客户端属性文件
在src/main/resources下创建client.properties,写入占位符:
client.name=${clientName}
3. 修改主类读取属性
在主类MainClass.java中静态加载属性文件:
package com.example; import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class MainClass { public static final String CLIENT; static { try (InputStream is = MainClass.class.getResourceAsStream("/client.properties")) { Properties props = new Properties(); props.load(is); CLIENT = props.getProperty("client.name"); } catch (IOException e) { throw new RuntimeException("Failed to load client config", e); } } // 其他业务代码... }
4. 动态创建Jar任务
在build.gradle中添加任务逻辑,为每个客户端生成独立Jar包:
// 遍历客户端列表,创建对应任务 clients.each { client -> // 注册Jar任务,命名为jarClientA、jarClientB等 def jarTask = tasks.register("jar${client.id.capitalize()}", Jar) { // 设置Jar包名称:project-client-a.jar、project-client-b.jar archiveBaseName.set("project-${client.id}") archiveVersion.set('') // 不需要版本号可保留此行,否则移除 // 包含编译后的主类字节码 from sourceSets.main.output.classesDirs // 处理资源文件,替换占位符 from sourceSets.main.resources { expand([clientName: client.name]) } // 依赖编译任务,确保先编译再打包 dependsOn compileJava } // 将Jar任务加入build任务的依赖,执行build时自动生成所有客户端Jar tasks.named('build').configure { dependsOn jarTask } }
方案二:直接替换源码常量(编译后固定值)
如果需要主类中的CLIENT变量是编译期常量(而非运行时读取),可以通过源码模板替换实现:
1. 准备源码模板
将主类文件移动到src/main/java-template/com/example/MainClass.java,把CLIENT变量改为占位符:
package com.example; public class MainClass { public static final String CLIENT = "${clientName}"; // 其他业务代码... }
2. 修改Gradle配置
在build.gradle中添加任务链:复制模板并替换占位符 → 编译源码 → 打包Jar:
def clients = [ [name: 'Client A', id: 'client-a'], [name: 'Client B', id: 'client-b'] ] clients.each { client -> // 任务1:复制模板并替换客户端名称 def prepareSource = tasks.register("prepareSourceFor${client.id.capitalize()}", Copy) { from 'src/main/java-template' into "$buildDir/tmp/sources/${client.id}" expand([clientName: client.name]) } // 任务2:编译替换后的源码 def compileClient = tasks.register("compile${client.id.capitalize()}Java", JavaCompile) { source = prepareSource.map { it.destinationDir } classpath = sourceSets.main.compileClasspath destinationDirectory.set(file("$buildDir/classes/java/${client.id}")) } // 任务3:打包Jar包 def jarClient = tasks.register("jar${client.id.capitalize()}", Jar) { archiveBaseName.set("project-${client.id}") archiveVersion.set('') from compileClient.map { it.destinationDirectory } from sourceSets.main.resources // 复制通用资源 dependsOn compileClient } tasks.named('build').configure { dependsOn jarClient } }
执行构建
运行./gradlew build(Windows用gradlew.bat build),生成的Jar包会位于build/libs目录下,每个Jar包对应一个客户端,且主类中的CLIENT值与配置一致。
内容的提问来源于stack exchange,提问作者Oa10712
相关产品推荐
相关产品推荐

