【问题标题】:Gradle setup to handle two deployment types with the same code base but different dependenciesGradle 设置以处理具有相同代码库但依赖项不同的两种部署类型
【发布时间】:2020-01-17 10:57:44
【问题描述】:

我正在开发一个新的 Web 应用程序项目,该项目必须在分布式环境中运行,以及一个很好的旧“将所有内容放入 war 文件并在 tomcat 上运行”环境。 两个版本的代码完全相同,只有一个小的 if/else 子句来处理不同的调用类型。

但是,我现在正在为 gradle 设置而苦苦挣扎。我有两个服务,我们称之为“DAO”和“Connector”作为例子。 DAO 使用连接器从数据源中检索数据。 在分布式模式下,DAO 必须依赖于 Connector:api,因为 DAO 应该只知道所说的 API,因为实现在其他地方运行。 在捆绑模式下,DAO 必须依赖于 Connector:bundle,因为所有内容都必须进入一个单独的 war-file。

我们生成的所有 jars 都使用 maven-publish 插件发布在我们的内部 nexus 3 服务器上。我们目前使用的是 gradle 版本 4.10.3,DAO 项目是更大的多项目设置的一部分,由紧密耦合的模块组成,而连接器是供另一个应用程序使用的共享服务。

为了完成这些事情,我尝试了许多想法。他们中的大多数都是完全错误的,所以我不会在这里讨论它们。我现在最终得到的是一个多发布设置。

  publishing {
    publications {
      dist(MavenPublication) {
        alias false
        from components.java
        afterEvaluate {
          artifact apiJar
        }
      }
      bundle(MavenPublication) {
        alias true
        from components.java
        afterEvaluate {
          artifactId "${artifactId}-bundle"
        }
      }
    }
    repositories {...}
}

此设置现在生成 2 组 pom 和 jar 文件。一个用于 connector-api.jar,一个用于 connector-bundle.jar

在 DAO 依赖设置中,我现在必须使用 if 块来决定设置什么依赖:

gradle.taskGraph.whenReady { graph ->
    if (graph.hasTask(generatePomFileForBundlePublication)){
      dependencies {
        implementation "com.example:Connector-bundle:1.0.0"
      }
    }
    else {
      dependencies {
        implementation "com.example:Connector:1.0.0:api"
      }
    }
  }
}

但是,这会导致我在开发时不再有可用的库。所以我改为无条件添加api依赖。

这确实有点用,但现在生成的 pom 文件内部总是有 api 依赖项,当我构建捆绑版本时,它同时具有两个依赖项。

完成了这么长的解释后,这是我的问题:
有没有更好的方法来代替这个......拼凑? 如果没有,我至少可以处理依赖重复问题吗?当我构建捆绑版本时,我不希望拥有 api 包。它充其量是冗余的,最坏的情况是它增加了更多的冗余依赖项。我不能像上面说的那样有条件地添加它,因为我失去了针对API进行开发的能力,并且我不想一直手动添加和删除它。

感谢任何帮助,因为我完全没有想法。

PS:别名的使用是为了处理maven-publish插件在多项目环境下使用multi-publishing的问题(见https://github.com/gradle/gradle/issues/1061

【问题讨论】:

    标签: java gradle dependencies pom.xml


    【解决方案1】:

    好的,在摒弃了我所有的先入之见并创建了一个 gradle 原型之后,我找到了一个可行的解决方案。这就是我所做的:

    首先我向 gradle.properties 添加了一个新属性mode=dist
    这使我能够通过 if(mode == "dist")else 块拆分我的依赖项。例如:

    dependencies {
      if (mode == "dist"){
        implementation "com.example:Connector:1.0.0:api" 
      } else {
        implementation "com.example:Connector-bundle:1.0.0"
      }
    }
    

    由于这个设置,默认情况下 gradle 现在就像我处于分发模式一样,这意味着我总是加载 API 库,而不是完整的东西。

    接下来我创建了一个自定义任务 publishBundle,在其中设置 mode = "lib" 并执行整个构建和发布过程。举个例子:

    task publishBundle {
      mode = "lib"
      dependsOn "build"
      dependsOn "publishBundlePublicationToNexusRepository"
    }
    

    最后一次调整必须在发布配置中进行。在这里我也必须添加正确的模式值:

      publishing {
        publications {
          dist(MavenPublication) {
            mode = "dist"
            alias false
            from components.java
            afterEvaluate {
              artifact apiJar
            }
          }
          bundle(MavenPublication) {
            mode = "lib"
            alias true
            from components.java
            afterEvaluate {
              artifactId "${artifactId}-bundle"
            }
          }
        }
        repositories {...}
      }
    

    这样,正常的构建和发布过程将遵循分布式方法,而 publishBundle 任务创建和发布包。在我们的存储库中,我们现在有两个连接器项目:connector 和 connector-bundle,这意味着我们可以根据我们所处的模式处理不同的依赖关系。

    它仍然感觉像是拼凑而成,但我可以想象我的要求太……特别了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-27
      • 2023-03-08
      • 1970-01-01
      • 2014-03-31
      • 2017-05-20
      • 2015-11-03
      • 2015-04-11
      相关资源
      最近更新 更多