zoukankan      html  css  js  c++  java
  • 开启Spring Initializr个性化之旅

    Every good Spring Boot project usually starts at https://start.spring.io/

    Josh Long

    202006201751FnpKSR11

    背景介绍,自己的项目或者公司的项目一般需要维护很多定制化的模块时,都是上传到maven私服中方便使用,但存在一个问题,每次需要相关的package需要去翻文档或者看bom,不能在建项目的时间直接引入,参考了start.spring.io,尝试搭建自己的spring initializr服务,同时整合自己的一些package,提供个性化服务,快速开发。

    目标

    基本框架

    18077Y13ii51

    • Spring Initializr 提供核心REST API,可以整合到UI或者IDE(如Intellij IDEA),直接生成项目
    • https://start.spring.io 提供web界面,强依赖于 Spring Initializr,显示数据来源于 Spring Properties,定制化主要是使用 Spring Initializr 提供的SPI
    • 除此之外,Spring.io 提供 Spring Boot metadata endpoint,Spring Initializr 会使用metadata作为外部数据源,以确保生成的Spring Boot版本是最新的

    个性化

    https://start.spring.io/ 虽然已经提供了非常优秀的Spring Boot Start,但在某些场景下,仍然需要做一些定制化,比如:

    1. 由于网络限制,需要搭建一个自己的实例
    2. 定制化自己的UI界面
    3. 提供一些自己的配置或依赖,如公司内部的starter

    Spring Initializr 是一个使用Spring Boot搭建的模块化应用,所以还是很容易扩展的

    版本

    由于官方Spring Initializr以及提供了bom,所以我们直接基于最新的bom版本搭建即可。

    <dependencyManagement>
        <dependencies>
          <dependency>
            <groupId>io.spring.initializr</groupId>
            <artifactId>initializr-bom</artifactId>
            <version>0.8.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
          </dependency>
        </dependencies>
      </dependencyManagement>
    

    搭建流程

    准备

    两个组件

    initializr 是必须的,ui界面是可选的。

    个性化

    定制配置文件

    可以基于 InitializrProperties 定义 application.yml,产出核心依赖。Spring Initializr 也允许我们使用 InitializrMetadataProvider 定义metadata,因此,我们可以创建一个 CustomInitializrProperties 类 来读取不同配置文件的配置项。

    @Configuration
    @EnableConfigurationProperties(CustomInitializrProperties.class)
    public class CustomInitializrConfiguration {
    
      @Bean
      public DefaultInitializrMetadataProvider customInitializrMetadataProvider(InitializrProperties initializrProperties,
          CustomInitializrProperties customInitializrProperties,
          InitializrMetadataUpdateStrategy initializrMetadataUpdateStrategy) {
        InitializrMetadata meta = InitializrMetadataBuilder.fromInitializrProperties(customInitializrProperties.getInitializr())
            .withInitializrProperties(initializrProperties, true).build();
        return new DefaultInitializrMetadataProvider(meta, initializrMetadataUpdateStrategy);
      }
    }
    
    
    @Data
    @ConfigurationProperties("custom")
    public class CustomInitializrProperties {
      @NestedConfigurationProperty
      InitializrProperties initializr = new InitializrProperties();
    }
    

    配置是通过 StartApplication 来加载的,但由于应用并没有使用组件扫描,我们需要在配置文件里进行自定义设置:

    custom:
      initializr:
        dependencies:
          - name: Custom Dependencies
            content:
              - name: Custom dependency
                id: custom-dependency
                groupId: your.domain
                artifactId: custom-artifact
                starter: false
                description: My first custom dependency for the Spring Initializr
    

    通过这种自定义的依赖配置,我们就可以控制配置项的合并和显示顺序。

    Initializr扩展

    通过配置文件自定义依赖,并不是总能满足我们的需求,有时候我们还需要自定义一些代码片段,这个时候就需要使用 Spring Initializr 提供的一些扩展钩子:

    • BuildCustomizer:定义Maven/Gradle构建过程,如增加maven build插件
    • ProjectContributor:定义一些个性化的项目目录或者文件
    • MainSourceCodeCustomizer, MainCompilationUnitCustomizer, MainApplicationTypeCustomizer, TestSourceCodeCustomizer, TestApplicationTypeCustomizer:项目的源码生成或修改,而不局限于项目语言
    • GitIgnoreCustomizer:定义gitignore文件
    • HelpDocumentCustomizer:定义 HELP.md文件
    • ProjectDescriptionCustomizer:通常用于适应项目描述,例如自动解决框架版本和语言级别的无效组合。

    举例,如果我们需要在生成项目中增加maven插件,则需要使用一种所谓的“伪”依赖( pseudo dependency)。首先我们需要定义一个像这样的依赖:

    custom:
      initializr:
        dependencies:
          - name: Custom Dependencies
            content:
              - name: Custom Maven Plugin
                id: custom-maven-plugin
                groupId: your.domain
                artifactId: custom-maven-plugin
                version: 1.0.0
                starter: false
                description: Configures custom Maven plugin integration for project scans
    

    接着,我们定义两个 BuildCustomizer:一个用来增加maven依赖插件,一个用来移除插件。

    @ProjectGenerationConfiguration
    @ConditionalOnRequestedDependency("custom-maven-plugin")
    public class CustomMavenPluginConfiguration {
    
      @Bean
      public BuildCustomizer<MavenBuild> customPluginConfigurer() {
        return (MavenBuild build) -> {
          build.dependencies().ids().filter(it -> it.equals("custom-maven-plugin"))
              .findFirst()
              .map(r -> build.dependencies().get(r)).map(r -> {
            build.plugins().add(r.getGroupId(), r.getArtifactId(),
                (plugin) -> plugin.execution("my-execution",
                    (first) -> first.goal("scan").configuration((conf) -> {conf.add("failOnSeverity", "MAJOR");})
                ));
            return build;
          }).orElse(build);
        };
      }
    
    
      @Bean
      public BuildCustomizer<MavenBuild> customPluginDependencyRemoval() {
        return build -> build.dependencies().remove("custom-maven-plugin");
      }
    }
    

    注意使用注解,Spring Initializr 自身并不会使用这些自动化配置,而是在生成项目时使用的,但需要spring.factories注册这些配置

    io.spring.initializr.generator.project.ProjectGenerationConfiguration=
      io.spring.start.site.extension.StartProjectGenerationConfiguration, 
      io.spring.start.site.CustomMavenPluginConfiguration
    

    最终产生的pom类似这样:

    <plugin>
        <groupId>your.domain</groupId>
        <artifactId>custom-maven-plugin</artifactId>
        <version>1.0.0</version>
        <executions>
            <execution>
                <id>my-execution</id>
                <goals>
                    <goal>scan</goal>
                </goals>
                <configuration>
                    <failOnSeverity>MAJOR</failOnSeverity>
                </configuration>
            </execution>
        </executions>
    </plugin>
    

    结语

    抛砖引玉,这篇文章只是简单介绍了Spring Initializr的一些定制化方法,更多更好的扩展方式还需要你去发现。

    本文由 歧途老农 创作,采用 CC BY 4.0 CN 协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。

  • 相关阅读:
    053573
    053572
    053571
    053570
    053569
    053568
    Android:你好,androidX!再见,android.support
    最新Androidx Fragment的前世今生系列(一)之Fragment的简单使用
    Android开发中如何匹配layout资源(layoutsw480dp layoutsw600dpland layoutsw720dpport)
    Android:Fragment最全面介绍 & 使用方法解析
  • 原文地址:https://www.cnblogs.com/whereis/p/13253480.html
Copyright © 2011-2022 走看看