Java 带Gradle的Spring Boot 2-从单个代码库构建/编译不同版本(Basic、Pro、Ultimate)

Java 带Gradle的Spring Boot 2-从单个代码库构建/编译不同版本(Basic、Pro、Ultimate),java,spring,spring-boot,gradle,build-tools,Java,Spring,Spring Boot,Gradle,Build Tools,项目详细信息 我有一个SpringBoot2项目,使用Gradle作为构建工具。我使用Java8作为Java版本。用于模板引擎的模板 我的目标 我想建立不同的版本,如基础版,专业版和最终版。例如,假设基本版本有5个特性。专业版具有基础版的所有功能,另外还有5个功能。终极版拥有专业版的所有功能,另外还有5个功能 我想到的解决方案和互联网搜索解决方案 为不同的版本保留不同的分支。但这里的问题是如何实际管理代码库、修补补丁和引入新功能等。我也搜索过这种方法,但所有人都说不要使用这种方法,因为这不是一个

项目详细信息

我有一个SpringBoot2项目,使用Gradle作为构建工具。我使用Java8作为Java版本。用于模板引擎的模板

我的目标

我想建立不同的版本,如基础版,专业版和最终版。例如,假设基本版本有5个特性。专业版具有基础版的所有功能,另外还有5个功能。终极版拥有专业版的所有功能,另外还有5个功能

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

  • 为不同的版本保留不同的分支。但这里的问题是如何实际管理代码库、修补补丁和引入新功能等。我也搜索过这种方法,但所有人都说不要使用这种方法,因为这不是一个好的选择
  • 使用Gradle构建多个版本。我知道Android中有一个功能可以构建多种风格的应用程序,比如开发、QA和生产。Spring boot有什么特性可以用来制作版本吗
  • 使用某种配置。我们可以有一个配置文件,我们可以根据版本切换开/关功能。但这很容易被黑客入侵。所以我不敢用它
  • 使用许可证。这与第3点相同,但略有不同
  • 使用java的模块特性(显然,我必须升级我的java版本)和一些Gradle配置。在构建时,我们可以基于
  • 那么如何创建不同的版本呢?在这种情况下,制作不同版本的最佳解决方案是什么?在这种情况下,每个版本都与以前的版本共享一些共同的功能


    请考虑我想要一个单一的代码库。因此,修复bug会很容易,因为它们共享一些常见的代码/功能。

    下面是一些您可以使用依赖项和Java的SPI

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

    然后在
    basic
    模块中定义此功能的实现:

    package com.example;
    
    public class BasicFlavorProvider implements FlavorProvider {
    
        @Override
        public String getFlavor() {
            return "BASIC!";
        }
    
    }
    
    以及一个文件
    resources/META-INF/services/com.example.FlavorProvider
    ,其中包含
    com.example.BasicFlavorProvider

    另一个在
    pro
    模块中

    package com.example;
    
    public class ProFlavorProvider implements FlavorProvider {
    
        @Override
        public String getFlavor() {
            return "PRO!";
        }
    }
    
    以及一个文件
    resources/META-INF/services/com.example.FlavorProvider
    ,其中包含
    com.example.ProFlavorProvider

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

        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()));
        }
    }
    
    以及:


    YMMV,这没有考虑到Spring,我对这个解决方案有两个问题。1.这个解决方案实际上将所有源代码都包含在最终构建中。虽然我可以使用模糊处理。但这还是很容易破解的吗?因为只有更改字符串才能解锁pro版本。2.如果此解决方案在最终版本中包含了所有功能,那么我必须根据版本1使用切换(显示/隐藏)功能。基本应用程序没有捆绑pro jar。2.我想答案是1。做同样的事情可能有很多其他的方法,而且你可能无论如何都需要混淆。还有许可证。现在我很清楚了,谢谢@tim_yates。我已经在搜索带有SpringBoot的JavaSPI集成示例。但是我到现在还没有得到任何有用的资源。如果你有什么,请与我分享。我只是关心如何将基本版(在您的示例中是核心版)包含到高级版(这里是pro版)中?控制器和URL端点将如何工作。上下文将如何工作。再次感谢您的支持。似乎是一个类似的问题
    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!