You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修正Java Gradle插件使其实现原Kotlin Maven发布逻辑?

问题:Java Gradle插件无法推送源码Jar和二进制Jar至S3 Maven仓库,如何修正?

我之前在每个build.gradle.kts中复制粘贴一段Kotlin代码,用于将Java构件发布到指定S3 Maven仓库,该代码会生成sources Jar并配置相关凭证。目前我已编写对应的Java Gradle插件,插件可正常编译,但运行时无法推送源码Jar和二进制Jar至仓库,请问如何修正该插件使其与原Kotlin代码功能一致?

原Kotlin代码

System.getenv("JRS_S3_URI")?.let { 
    val sourcesJar by tasks.creating(Jar::class) { 
        classifier = "sources" 
        from(java.sourceSets["main"].allSource) 
    } 
    publishing { 
        repositories { 
            maven { 
                url = uri(it) 
                credentials(AwsCredentials::class.java) { 
                    accessKey = System.getenv("JRS_ACCESSKEYID") 
                    secretKey = System.getenv("JRS_SECRETACCESSKEY") 
                } 
            } 
        } 
        publications { 
            "mavenJava"(MavenPublication::class) { 
                from(components["java"]) 
                artifact(sourcesJar) 
            } 
        } 
    } 
}

当前Java Gradle插件代码

public class Maven extends SourceSetConfiguredPlugin { 
    public Maven( XenoExtension extension ) { 
        super( extension ); 
    } 
    @Override 
    public void apply( Project project ) { 
        if ( System.getenv( "JRS_S3_URI" ) != null ) { 
            project.getPluginManager().apply( MavenPublishPlugin.class ); 
            TaskContainer tasks = project.getTasks(); 
            Jar sourceSet = tasks.create( "sources", Jar.class, task -> { 
                getSourceSets().stream() 
                    .map( SourceSet::getAllSource ) 
                    .map( sds -> project.copySpec().from( sds ) ) 
                    .forEach( copySpec -> task.include( copySpec.getIncludes() ) ); 
            } ); 
            tasks.withType( PublishToMavenRepository.class, task -> { 
                task.getRepository().setUrl( URI.create( System.getenv( "JRS_S3_URI" ) ) ); 
                task.getRepository().credentials( AwsCredentials.class, creds -> { 
                    creds.setAccessKey( System.getenv( "JRS_ACCESSKEYID" ) ); 
                    creds.setSecretKey( System.getenv( "JRS_SECRETACCESSKEY" ) ); 
                } ); 
                MavenPublication publication = task.getPublication(); 
                publication.artifact( project.getComponents() ); 
                publication.artifact( sourceSet ); 
            } ); 
        } 
    } 
}

问题分析与修正方案

你的Java插件和原Kotlin代码的核心差异在于配置时机、源码Jar构建逻辑、Publication与仓库的配置方式,下面是具体的修正点和完整的修复代码:

1. 核心问题点

  • 源码Jar构建错误:原Kotlin代码明确指定了classifier = "sources"并直接关联main源码集的所有源码,而你的Java代码没有设置classifier,且错误地用include代替from来关联源码。
  • Publishing扩展配置时机错误:原Kotlin代码直接配置publishing扩展(仓库和Publication),而你是在PublishToMavenRepository任务层面修改,这会导致配置不生效或重复覆盖。
  • Publication配置错误:你调用publication.artifact(project.getComponents())是错误的,project.getComponents()返回的是组件容器,应该关联java组件来自动包含二进制Jar。

2. 修正后的Java插件代码

import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.MavenPublishPlugin;
import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.publish.maven.MavenPublication;
import org.gradle.api.tasks.bundling.Jar;
import org.gradle.api.tasks.TaskContainer;
import org.gradle.api.provider.Provider;
import software.amazon.awssdk.auth.credentials.AwsCredentials;

public class Maven extends SourceSetConfiguredPlugin {

    public Maven(XenoExtension extension) {
        super(extension);
    }

    @Override
    public void apply(Project project) {
        String s3Uri = System.getenv("JRS_S3_URI");
        if (s3Uri != null) {
            // 应用必要的插件
            project.getPluginManager().apply(MavenPublishPlugin.class);
            project.getPluginManager().apply(JavaPlugin.class);

            TaskContainer tasks = project.getTasks();

            // 1. 正确创建sources Jar任务,和原Kotlin逻辑对齐
            Provider<Jar> sourcesJarProvider = tasks.register("sourcesJar", Jar.class, task -> {
                task.setClassifier("sources"); // 设置源码Jar的classifier标识
                // 关联main源码集的所有源码文件
                task.from(project.getExtensions().getByType(org.gradle.api.plugins.JavaPluginExtension.class)
                        .getSourceSets().getByName("main").getAllSource());
            });

            // 2. 获取Publishing扩展,全局配置仓库和Publication
            PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);

            // 配置S3 Maven仓库
            publishing.getRepositories().maven(repo -> {
                repo.setUrl(project.getUri(s3Uri));
                // 配置AWS凭证信息
                repo.getCredentials(AwsCredentials.class, creds -> {
                    creds.setAccessKey(System.getenv("JRS_ACCESSKEYID"));
                    creds.setSecretKey(System.getenv("JRS_SECRETACCESSKEY"));
                });
            });

            // 配置Maven Publication,关联Java组件和sources Jar
            publishing.getPublications().create("mavenJava", MavenPublication.class, publication -> {
                // 关联Java组件,自动包含编译后的二进制Jar
                publication.from(project.getComponents().getByName("java"));
                // 添加sources Jar作为额外构件
                publication.artifact(sourcesJarProvider);
            });
        }
    }
}

3. 关键修正说明

  • 源码Jar任务:使用tasks.register(Gradle推荐的懒加载任务创建方式)创建sourcesJar,明确设置classifier = "sources",并正确关联main源码集的allSource,和原Kotlin逻辑完全一致。
  • Publishing扩展配置:直接操作PublishingExtension来配置仓库和Publication,确保配置在Gradle生命周期的正确时机生效,避免任务层面配置的不确定性。
  • Publication关联:通过publication.from(project.getComponents().getByName("java"))关联Java组件,自动包含编译后的二进制Jar,再添加sourcesJar作为额外构件,保证发布内容完整。
  • 凭证配置:在仓库层面统一配置AWS凭证,确保所有发布任务都使用相同的凭证信息,避免重复配置。

这样修改后,你的Java插件就会和原Kotlin代码实现完全一致的功能,能够正确生成并推送源码Jar和二进制Jar到指定的S3 Maven仓库。

内容的提问来源于stack exchange,提问作者xenoterracide

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:27:56