【问题标题】:Spring Boot 2 with Gradle - Building/Compiling different editions (Basic, Pro, Ultimate) from a single codebaseSpring Boot 2 with Gradle - 从单个代码库构建/编译不同版本(Basic、Pro、Ultimate)
【发布时间】:2021-05-06 11:41:11
【问题描述】:

项目详情

我有一个使用 Gradle 作为构建工具的 spring boot 2 项目。我使用 Java 8 作为 Java 版本。用于模板引擎的 Thymeleaf。

我的目标

我想构建不同的版本,例如基本版、专业版和终极版。例如,假设 Base 版本有 5 个功能。 Pro 版本具有 Base 版本的所有功能,另外还有 5 个功能。 Ultimate 版拥有 Pro 版的所有功能,另外还有 5 个功能。

我想到的解决方案和互联网搜索的解决方案

  1. 为不同的版本保留不同的分支。但这里的问题是如何实际管理代码库、修补修复和引入新功能等。我也搜索过这种方法,但都说不要使用它,因为这不是一个好的选择。
  2. 使用 Gradle 构建多个版本。 我知道在 Android 中有一个功能可以构建多种风格的应用程序,例如用于开发、QA 和生产。 Spring boot 是否有任何可用于制作版本的功能。
  3. 使用某种配置。我们可以有一个基于它的配置文件,我们可以根据版本打开/关闭功能。但这很容易被黑客入侵。所以不敢用。
  4. 使用许可。这与第 3 点相同,但略有不同。
  5. 通过一些 Gradle 配置使用 java 的模块功能(显然,我必须升级我的 java 版本)。在构建时,我们可以包含基于的模块

那么如何创建不同的版本?在这种情况下,制作不同版本的最佳解决方案是什么?每个版本都与之前的版本有一些共同的特点?

请考虑我想要一个单一的代码库。因此,由于它们共享一些共同的代码/功能,因此进行错误修复会很容易。

【问题讨论】:

    标签: java spring spring-boot gradle build-tools


    【解决方案1】:

    您可以使用依赖项和 Java 的 SPI 来做一些事情......

    你可以在一些核心模块中定义一个提供者接口(这里我称之为“:core”)

    package com.example;
    
    interface FlavorProvider {
    
        String getFlavor();
    
    }
    

    然后在basic 模块中定义它的实现:

    package com.example;
    
    public class BasicFlavorProvider implements FlavorProvider {
    
        @Override
        public String getFlavor() {
            return "BASIC!";
        }
    
    }
    

    以及包含com.example.BasicFlavorProvider行的文件resources/META-INF/services/com.example.FlavorProvider

    另一个在 pro 模块中

    package com.example;
    
    public class ProFlavorProvider implements FlavorProvider {
    
        @Override
        public String getFlavor() {
            return "PRO!";
        }
    }
    

    连同包含com.example.ProFlavorProvider行的文件resources/META-INF/services/com.example.FlavorProvider

    然后在您的应用程序中,可选择将任一模块作为依赖项包含在项目属性中:

        implementation(project(":core"))
        if (project.hasProperty("pro")) {
            implementation(project(":pro"))
        } else {
            implementation(project(":basic"))
        }
    

    在你的主课中你可以这样做:

    package com.example;
    
    import java.util.ServiceLoader;
    
    public class Main {
    
        private final ServiceLoader<FlavorProvider> provider = ServiceLoader.load(FlavorProvider.class);
    
        public static void main(String[] args) {
            new Main().run();
        }
    
        private void run() {
            provider.forEach(p -> System.out.println(p.getFlavor()));
        }
    }
    

    然后:

    ➜ ./gradlew app:run
    
    > Task :app:run
    BASIC!
    

    还有:

    ➜ ./gradlew app:run -Ppro
    
    > Task :app:run
    PRO!
    

    YMMV,这并没有考虑到 Spring ?

    【讨论】:

    • 我对这个解决方案有两个顾虑。 1. 这个解决方案实际上将所有源代码都包含在最终构建中。虽然我可以使用混淆。但这仍然很容易破解吗?因为只有更改字符串才能解锁专业版。 2. 如果此解决方案在最终版本中包含所有功能,那么我是否必须根据版本使用切换(显示/隐藏)功能?
    • 1.基本应用程序没有捆绑 pro jar。 2. 我想这由 1 回答。可能有很多其他方法可以做同样的事情,而且你可能无论如何都需要混淆。和许可。
    • 现在我很清楚了,感谢@tim_yates。我已经在寻找带有 Spring boot 的 Java SPI 集成示例。但到目前为止,我无法获得任何有用的资源。如果你有任何请与我分享。我只是关心如何将 Base(您的示例中的核心)版本包含到更高版本(此处为专业版)?控制器和 URL 端点将如何工作。上下文将如何工作。再次感谢您的支持。
    • stackoverflow.com/questions/25751988/… 似乎是一个类似的问题
    猜你喜欢
    • 1970-01-01
    • 2013-02-19
    • 1970-01-01
    • 2020-11-09
    • 1970-01-01
    • 2021-02-19
    • 1970-01-01
    • 1970-01-01
    • 2018-10-19
    相关资源
    最近更新 更多