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

如何用Gradle创建仅含自研模块的可发布Shaded Jar?

问题背景

我们需要从多模块Spring Boot项目的数据层(very-neat-bigdata模块)发布一个可供客户(大概率是Spring项目)使用的库,核心需求如下:

  1. 自研模块(very-neat-bigdata、very-neat-util、very-neat-other)需做Shade处理,打包到发布的jar中;
  2. 第三方依赖(如Spring、HBase、Guava等)不做Shade,但要出现在发布的pom.xml中,且不强制客户使用我们指定的版本;
  3. 无需客户逐个排除依赖,依赖版本由客户项目自行控制。

现有项目结构

very-neat-project
  very-neat-web
    -> spring-web 1.5.4
  very-neat-bigdata            <- 目标模块
    -> spring-context 1.5.4
    -> hbase
    -> very-neat-util
      -> guava 26
    -> very-neat-other
      -> common.util 1.5.6
    -> ...其他大量依赖...

客户引入后的期望结构

customer-project
  customer-web
    -> spring-web 1.6.8
    -> spring-context 1.6.8
    -> very-neat-bigdata-shaded <- 我们提供的库
    -> guava 28
    -> hbase
    -> common.util 1.5.4
    -> ..其他大量依赖..

Gradle实现方案

通过Gradle的Shadow插件可以满足需求,具体配置步骤如下:

1. 引入Shadow插件

在very-neat-bigdata模块的build.gradle中添加插件依赖:

plugins {
    id 'java'
    id 'maven-publish'
    id 'com.github.johnrengelman.shadow' version '7.1.2'
}

2. 自定义依赖配置

创建专门用于Shade自研模块的配置,隔离自研与第三方依赖:

configurations {
    // 继承implementation配置,用于标记需要Shade的自研依赖
    shadowImplementation.extendsFrom implementation
}

3. 配置依赖关系

将自研模块放入shadowImplementation(会被打包到jar),第三方依赖放入implementation(作为传递依赖出现在pom):

dependencies {
    // 自研模块:将被Shade到最终发布的jar中
    shadowImplementation project(':very-neat-util')
    shadowImplementation project(':very-neat-other')

    // 第三方依赖:不Shade,作为传递依赖暴露给客户,版本由客户控制
    implementation 'org.springframework:spring-context'
    implementation 'org.apache.hbase:hbase-client'
    // 其他第三方依赖...
}

4. 配置ShadowJar任务

指定要打包的自研代码包,排除第三方类,同时设置发布jar的名称:

shadowJar {
    // 包含自研模块的包路径(根据实际包名调整)
    include 'com/veryneat/bigdata/**'
    include 'com/veryneat/util/**'
    include 'com/veryneat/other/**'

    // 排除第三方依赖的类,避免打包进Shaded jar
    exclude 'com/google/**'
    exclude 'org/apache/hbase/**'
    exclude 'org/springframework/**'
    // 其他第三方包路径...

    // 设置最终jar名称为 very-neat-bigdata-shaded
    archiveBaseName.set('very-neat-bigdata-shaded')
    archiveClassifier.set('') // 移除默认的"shadow"后缀
}

5. 配置发布任务

确保发布的构件是Shaded jar,同时生成的pom.xml正确包含第三方依赖:

publishing {
    publications {
        maven(MavenPublication) {
            from components.java
            // 指定使用ShadowJar生成的jar作为发布构件
            artifact shadowJar {
                classifier = ''
            }
            // 优化pom依赖:让第三方依赖版本可被客户覆盖
            pom {
                dependencies {
                    configurations.implementation.allDependencies.each { dep ->
                        if (dep.group && dep.name) {
                            dependency {
                                groupId dep.group
                                artifactId dep.name
                                // 使用版本范围或留空(Maven需版本,建议用范围如"[1.5.4,)")
                                version dep.version ?: '[1.0,)'
                                scope 'compile'
                            }
                        }
                    }
                }
            }
        }
    }
    // 配置发布仓库(如公司私服)
    repositories {
        maven {
            url = uri('https://your-company-maven-repo.com')
            credentials {
                username = project.findProperty('repoUser') ?: System.getenv('REPO_USER')
                password = project.findProperty('repoPass') ?: System.getenv('REPO_PASS')
            }
        }
    }
}

最佳实践建议

  1. 依赖管理优先:如果是Spring生态模块,建议继承Spring Boot的dependencyManagement,不引入starter,让客户的Spring Boot版本自动覆盖依赖版本,减少冲突。
  2. 严格隔离自研与第三方依赖:通过Shadow插件的自定义配置明确区分两类依赖,避免误打包第三方类导致类加载冲突。
  3. 不Shade核心框架:Spring、Guava这类核心库绝对不要Shade,依赖调解机制会自动处理版本优先级,强制Shade反而容易引发兼容性问题。
  4. 提供清晰的集成文档:告知客户哪些第三方依赖会自动引入,以及如何通过dependencyManagement覆盖版本,降低集成成本。
  5. 多版本兼容性测试:在不同版本的Spring、第三方依赖环境下测试Shaded模块,确保兼容性。

内容的提问来源于stack exchange,提问作者Daniel Hári

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 19:40:33