Every good Spring Boot project usually starts at https://start.spring.io/
背景介紹翁授,自己的項(xiàng)目或者公司的項(xiàng)目一般需要維護(hù)很多定制化的模塊時(shí)死相,都是上傳到maven私服中方便使用,但存在一個(gè)問題聘芜,每次需要相關(guān)的package需要去翻文檔或者看bom,不能在建項(xiàng)目的時(shí)間直接引入夯缺,參考了start.spring.io拉宗,嘗試搭建自己的spring initializr服務(wù)锻弓,同時(shí)整合自己的一些package,提供個(gè)性化服務(wù)蔫骂,快速開發(fā)么翰。
目標(biāo)
基本框架
- Spring Initializr 提供核心REST API,可以整合到UI或者IDE(如Intellij IDEA)辽旋,直接生成項(xiàng)目
- https://start.spring.io 提供web界面浩嫌,強(qiáng)依賴于 Spring Initializr,顯示數(shù)據(jù)來源于 Spring Properties补胚,定制化主要是使用 Spring Initializr 提供的SPI
- 除此之外码耐,Spring.io 提供 Spring Boot metadata endpoint,Spring Initializr 會(huì)使用metadata作為外部數(shù)據(jù)源溶其,以確保生成的Spring Boot版本是最新的
個(gè)性化
https://start.spring.io/ 雖然已經(jīng)提供了非常優(yōu)秀的Spring Boot Start骚腥,但在某些場景下,仍然需要做一些定制化瓶逃,比如:
- 由于網(wǎng)絡(luò)限制束铭,需要搭建一個(gè)自己的實(shí)例
- 定制化自己的UI界面
- 提供一些自己的配置或依賴,如公司內(nèi)部的starter
Spring Initializr 是一個(gè)使用Spring Boot搭建的模塊化應(yīng)用厢绝,所以還是很容易擴(kuò)展的
版本
由于官方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>
搭建流程
準(zhǔn)備
兩個(gè)組件
initializr 是必須的昔汉,ui界面是可選的懈万。
個(gè)性化
定制配置文件
可以基于 InitializrProperties 定義 application.yml,產(chǎn)出核心依賴挤庇。Spring Initializr 也允許我們使用 InitializrMetadataProvider 定義metadata钞速,因此,我們可以創(chuàng)建一個(gè) CustomInitializrProperties 類 來讀取不同配置文件的配置項(xiàng)嫡秕。
@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 來加載的渴语,但由于應(yīng)用并沒有使用組件掃描,我們需要在配置文件里進(jìn)行自定義設(shè)置:
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
通過這種自定義的依賴配置昆咽,我們就可以控制配置項(xiàng)的合并和顯示順序驾凶。
Initializr擴(kuò)展
通過配置文件自定義依賴牙甫,并不是總能滿足我們的需求,有時(shí)候我們還需要自定義一些代碼片段调违,這個(gè)時(shí)候就需要使用 Spring Initializr 提供的一些擴(kuò)展鉤子:
- BuildCustomizer:定義Maven/Gradle構(gòu)建過程窟哺,如增加maven build插件
- ProjectContributor:定義一些個(gè)性化的項(xiàng)目目錄或者文件
- MainSourceCodeCustomizer, MainCompilationUnitCustomizer, MainApplicationTypeCustomizer, TestSourceCodeCustomizer, TestApplicationTypeCustomizer:項(xiàng)目的源碼生成或修改,而不局限于項(xiàng)目語言
- GitIgnoreCustomizer:定義gitignore文件
- HelpDocumentCustomizer:定義 HELP.md文件
- ProjectDescriptionCustomizer:通常用于適應(yīng)項(xiàng)目描述技肩,例如自動(dòng)解決框架版本和語言級(jí)別的無效組合且轨。
舉例,如果我們需要在生成項(xiàng)目中增加maven插件虚婿,則需要使用一種所謂的“偽”依賴( pseudo dependency)旋奢。首先我們需要定義一個(gè)像這樣的依賴:
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
接著,我們定義兩個(gè) BuildCustomizer:一個(gè)用來增加maven依賴插件然痊,一個(gè)用來移除插件至朗。
@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 自身并不會(huì)使用這些自動(dòng)化配置剧浸,而是在生成項(xiàng)目時(shí)使用的蛙埂,但需要spring.factories
注冊(cè)這些配置
io.spring.initializr.generator.project.ProjectGenerationConfiguration=\
io.spring.start.site.extension.StartProjectGenerationConfiguration, \
io.spring.start.site.CustomMavenPluginConfiguration
最終產(chǎn)生的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>
結(jié)語
拋磚引玉击罪,這篇文章只是簡單介紹了Spring Initializr的一些定制化方法恳蹲,更多更好的擴(kuò)展方式還需要你去發(fā)現(xiàn)滑沧。
本文由 歧途老農(nóng) 創(chuàng)作,采用 CC BY 4.0 CN 協(xié)議 進(jìn)行許可袋马。 可自由轉(zhuǎn)載初澎、引用,但需署名作者且注明文章出處虑凛。