<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
因業務需要, 公司內需要使用 SpringBoot Starter 構建 SDK. 不同的是使用了更為靈活的 Kotlin 語言, 構建指令碼也換成了 Kotlin Script.
.kts
)本文主要分幾個步驟:
不會太詳細, 但會把主要的內容和要注意的點記錄下來.
SpringBoot Starter 實現的原理網路上已經有很多, 就不細說了, 我總結了一下核心的運作邏輯, 就是下面我畫的這張圖:
所以要寫一個 starter, 無論用什麼語言本質上都是一樣的.
以下步驟可能與部分網路教學不太一樣, 主要是根據上面的圖方向來分析說明的, 是一個按照邏輯需求來定義的順序:
resources
下新建 META-INF
資料夾, 寫個 spring.factories
檔案 (檔案內容見後文), 用於指定一個設定類.application.properties
或者 application.yml
裡能使用的設定屬性application.properties
的時候提示一些資訊實際寫程式碼時順序按需即可.
比如, 我想實現一個郵件告警的 SDK.
這個 SDK 有一個類 AlarmByEmails
, 整合此 SDK 的專案通過如下的 application.properties 設定後, 可通過 AlarmByEmails
的某個方法呼叫 xxx@163.com 傳送郵件給 yyy@163.com.
(考慮到後續 starter 測試用 yml 方式有所不便, 所以 starter 中測試使用 properties 檔案)
simple.alarm.email.host=smtp.163.com # 郵件協定伺服器 simple.alarm.email.senderEmail=xxx@163.com # 傳送方郵箱 simple.alarm.email.senderPassword=xxx # 傳送方郵箱的授權碼, 非密碼 simple.alarm.email.receiverEmail=yyy@163.com # 接收方郵箱
怎麼實現呢?
看個總體目錄結構(已刪減無關檔案):
├── build.gradle.kts ├── settings.gradle.kts └── src └── main ├── kotlin │ └── com │ └── looko │ └── simplealarmspringbootstarter │ ├── autoconfigure │ │ ├── SimpleAlarmAutoConfiguration.kt │ │ └── properties │ │ └── EmailProperties.kt │ └── component │ └── AlarmByEmails.kt └── resources ├── META-INF │ └── spring.factories └── test.properties
基於 Kotlin 和 Gradle 新建 Spring Boot 專案, 名稱最好按照 Starter 建立的約定俗成規範 xxx-spring-boot-starter
, 刪除啟動類, 然後在 build.gradle.kts
的依賴中新增:
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
這裡的屬性就定義了組態檔的寫法.
@ConfigurationProperties(prefix = "simple.alarm.email") data class EmailProperties( var host? = null, var senderEmail? = null, var senderPassword? = null, var receiverEmail? = null )
注意:
屬性宣告好了, 該到用的時候了.
class AlarmByEmail( private val host, private val senderEmail, private val senderPassword, private val receiverEmail ) { fun sendMessage(content: String): Boolean { // 發郵件的實現 } }
此處使用了構造器注入的方式, 也可以使用 setter 方式.
這是關鍵, 上面設定上的屬性和業務 Bean 都有了, 如何把它倆關聯起來並註冊成 Spring Bean 呢?
@Configuration @ConditionalOnClass(SimpleAlarmAutoConfiguration::class) @EnableConfigurationProperties(value = [EmailProperties::class]) class SimpleAlarmAutoConfiguration { @Bean fun alarmByEmail(properties: EmailProperties): AlarmByEmail { return AlarmByEmail( properties.host, properties.senderEmail, properties.senderPassword, properties.receiverEmail ) } }
就是如此簡單.
@Configuration + @Bean 老組合了, 將一個類註冊為 Spring Bean.
@ConditionalOnClass, 是基於 @Conditional 的條件註解, 是 Spring4 提供的一種註解, 它的作用是按照設定的條件進行判斷, 把滿足判斷條件的 Bean 註冊到 Spring 容器. 相關注解如下:
條件註解 | 作用 |
---|---|
@ConditionalOnBean | 當上下文存在某個物件時才會範例化 Bean |
@ConditionalOnClass | 某個 Class 位於 classpath 路徑上才會範例化 Bean |
@ConditionalOnExpression | 當 SpEL 表示式值為 true 的時候才會範例化 Bean |
@ConditionalOnMissingBean | 當上下文不存在某個物件時才會範例化 Bean |
@ConditionalOnMissingClass | 某個 Class 不在 classpath 路徑上才會範例化 Bean |
@ConditionalOnNotWebApplication | 非 web 應用才會範例化 Bean |
@ConditionalOnWebApplication | web 應用才會範例化 Bean |
@ConditionalOnProperty | 當指定的屬性有指定的值時才會範例化 Bean |
@ConditionalOnJava | 當 JVM 版本為指定的版本範圍時才會範例化 Bean |
@ConditionalOnResource | 當 classpath 路徑下有指定的資源時才會範例化 Bean |
@ConditionalOnJndi | 在 JNDI 存在時才會範例化 Bean |
@ConditionalOnSingleCandidate | 當指定的 Bean 在容器中只有一個, 或者有多個但是指定了首選的 Bean 時, 才會範例化 Bean |
@EnableConfigurationProperties , 用於獲取設定宣告類, 原理不贅述.
這個檔案是上面寫好的自動設定的入口, 有了它 Spring 才能讀到上面寫好的內容:
org.springframework.boot.autoconfigure.EnableAutoConfiguration= com.looko.simplealarmspringbootstarter.autoconfigure.SimpleAlarmAutoConfiguration
可不寫, 用來作為寫屬性時的提示.
spring-configuration-metadata.json
:
{ "properties": [ { "name": "simple.alarm.email.host", "type": "java.lang.String", "description": "郵件伺服器地址." }, { "name": "simple.alarm.email.senderEmail", "type": "java.lang.String", "description": "傳送者郵箱." }, { "name": "simple.alarm.email.senderPassword", "type": "java.lang.String", "description": "傳送者授權碼." }, { "name": "simple.alarm.email.receiverEmail", "type": "java.lang.String", "description": "接收者郵箱." }, ] }
如果我想通過設定配多個傳送者的郵箱, 每個郵箱又可以設定, 該如何實現呢?
比如, 使用 xxx@163.com 傳送郵件給 yyy@163.com, 而使用 yyy@163.com 則可以同時發郵件給 zzz@163.com 和 xxx@163.com.
設定的寫法:
simple.alarm.email.configs[0].host=smtp.163.com simple.alarm.email.configs[0].senderEmail=xxx@163.com simple.alarm.email.configs[0].senderPassword=xxx simple.alarm.email.configs[0].receivers[0]=yyy@163.com simple.alarm.email.configs[1].host=smtp.163.com simple.alarm.email.configs[1].senderEmail=yyy@163.com simple.alarm.email.configs[1].senderPassword=yyy simple.alarm.email.configs[1].receivers[0]=zzz@163.com simple.alarm.email.configs[1].receivers[0]=xxx@163.com
將郵箱按傳送者分成了一個個的 configs 陣列, 每個 configs 下面儲存了傳送的設定, 同時接收者也設定成了陣列,
這樣就完美符合需求了.
那麼 properties 等類怎麼寫呢?
EmailProperties
:
@ConfigurationProperties(prefix = "simple.alarm.email") data class EmailProperties( var configs: Array<EmailConfigEntity> = arrayOf() )
這是抽出來的 EmailConfigEntity
, 注意用 var:
data class EmailConfigEntity( var host: String? = null, var senderEmail: String? = null, var senderPassword: String? = null, var receivers: Array<String> = arrayOf() )
因為引數抽出來了, 所以 AlarmByEmail
的入參也要相應調整:
class AlarmByEmail( private val configs: Array<EmailConfigEntity> ) { fun sendMessage(content: String): Boolean { // 發郵件的實現 } }
SimpleAlarmAutoConfiguration
相應調整:
@Configuration @ConditionalOnClass(SimpleAlarmAutoConfiguration::class) @EnableConfigurationProperties(value = [EmailProperties::class]) class SimpleAlarmAutoConfiguration { @Bean fun alarmByEmail(properties: EmailProperties): AlarmByEmail { return AlarmByEmail( properties.configs ) } }
這樣就全部完成了.
測試是必要的.
單獨的 Spring-boot-starter
並不是一個完整的應用 大多數時候都是作為一個實際應用的一部分存在 如果是通過另一個專案參照並啟動專案的話, 會在 Debug 時造成不必要的麻煩 所以需要建立能夠獨立執行的 Test
testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-test-autoconfigure")
resourses
路徑下的 test.properties
:
simple.alarm.email.configs[0].host=smtp.163.com simple.alarm.email.configs[0].senderEmail=xxx@163.com simple.alarm.email.configs[0].senderPassword=xxx simple.alarm.email.configs[0].receivers[0]=yyy@163.com simple.alarm.email.configs[1].host=smtp.163.com simple.alarm.email.configs[1].senderEmail=yyy@163.com simple.alarm.email.configs[1].senderPassword=yyy simple.alarm.email.configs[1].receivers[0]=zzz@163.com simple.alarm.email.configs[1].receivers[0]=xxx@163.com
如下, 通過註解指定自動設定類和組態檔
@SpringBootTest(classes = [SimpleAlarmAutoConfiguration::class]) @TestPropertySource("classpath:test.properties") class SimpleAlarmSpringBootStarterApplicationTests { @Test fun contextLoads() { } @Autowired lateinit var alarmByEmail: AlarmByEmail @Test fun testAlarmByEmail() { assert(alarmByEmail.sendMessage("Message Content")) } }
使用 maven-publish
外掛.
在 build.gradle.kts
中, 主要用法如下 :
// ... plugins { // ... `maven-publish` } // ... val sourcesJar by tasks.registering(Jar::class) { archiveClassifier.set("sources") from(sourceSets.main.get().allSource) } publishing { publications { register("alarm", MavenPublication::class) { groupId = "com.looko" artifactId = "simple-alarm-spring-boot-starter" version = "0.0.1-SNAPSHOT" from(components["java"]) artifact(sourcesJar.get()) } } repositories { maven { mavenLocal() } } } // ...
在 IDEA 介面 double-ctrl 撥出 run 視窗, 找到 gradle publishToMavenLocal
回車就能打包到 .m2
目錄下了.
或者在右側 gradle 視窗中也能找到相應的 gradle task.
如果打到倉庫的包裡含有 plain
字尾, 不被 maven 識別的話, 可以在 build.gradle.kts
中新增如下設定解決:
tasks.getByName<Jar>("jar") { archiveClassifier.set("") }
testImplementation("com.looko:simple-alarm-spring-boot-starter:0.0.1-SNAPSHOT")
application.properties
simple.alarm.email.configs[0].host=smtp.163.com simple.alarm.email.configs[0].senderEmail=xxx@163.com simple.alarm.email.configs[0].senderPassword=xxx simple.alarm.email.configs[0].receivers[0]=yyy@163.com simple.alarm.email.configs[1].host=smtp.163.com simple.alarm.email.configs[1].senderEmail=yyy@163.com simple.alarm.email.configs[1].senderPassword=yyy simple.alarm.email.configs[1].receivers[0]=zzz@163.com simple.alarm.email.configs[1].receivers[0]=xxx@163.com
或者 application.yml
simple: alarm: email: configs: - host: smtp.163.com senderEmail: xxx@163.com senderPassword: xxx receivers: - yyy@163.com - host: smtp.163.com senderEmail: yyy@163.com senderPassword: yyy receivers: - zzz@163.com - xxx@163.com
程式碼
根據實際業務整合, 具體程式碼略.
範例程式碼:
以上就是KotlinScript 構建 SpringBootStarter保姆級教學的詳細內容,更多關於KotlinScript 構建 SpringBootStarter的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45