javascript
SpringBoot之自定义starter
目錄
一、什么是SpringBoot starter機制
二、為什么要自定義starter
三、什么時候需要創建自定義starter
四、自動加載核心注解說明
五、自定義starter的開發流程
案例一:為短信發送功能創建一個starter
案例二:AOP方式統一服務日志
?一、什么是SpringBoot starter機制
SpringBoot中的starter是一種非常重要的機制(自動化配置),能夠拋棄以前繁雜的配置,將其統一集成進starter,應用者只需要在maven中引入starter依賴,SpringBoot就能自動掃描到要加載的信息并啟動相應的默認配置。
starter讓我們擺脫了各種依賴庫的處理,需要配置各種信息的困擾。SpringBoot會自動通過classpath路徑下的類發現需要的Bean,并注冊進IOC容器。SpringBoot提供了針對日常企業應用研發各種場景的spring-boot-starter依賴模塊。
所有這些依賴模塊都遵循著約定成俗的默認配置,并允許我們調整這些配置,即遵循“約定大于配置”的理念。
二、為什么要自定義starter
在我們的日常開發工作中,經常會有一些獨立于業務之外的配置模塊,我們經常將其放到一個特定的包下,然后如果另一個工程需要復用這塊功能的時候,需要將代碼硬拷貝到另一個工程,重新集成一遍,麻煩至極。
如果我們將這些可獨立于業務代碼之外的功配置模塊封裝成一個個starter,復用的時候只需要將其在pom中引用依賴即可,SpringBoot為我們完成自動裝配,簡直不要太爽
三、什么時候需要創建自定義starter
在我們的日常開發工作中,可能會需要開發一個通用模塊,以供其它工程復用。SpringBoot就為我們提供這樣的功能機制,我們可以把我們的通用模塊封裝成一個個starter,這樣其它工程復用的時候只需要在pom中引用依賴即可,由SpringBoot為我們完成自動裝配。
常見場景:
? ?1.通用模塊-短信發送模塊
? ?2.基于AOP技術實現日志切面
? ?3.分布式雪花ID,Long-->string,解決精度問題
? ? ?jackson2/fastjson
? ?4.微服務項目的數據庫連接池配置
? ?5.微服務項目的每個模塊都要訪問redis數據庫,每個模塊都要配置redisTemplate
? ? ?也可以通過starter解決
四、自動加載核心注解說明
starter 組件開發,核心是自動注解類的注解順序,即根據條件進行注解
?關于自動加載核心注解,詳情可見:https://blog.csdn.net/qq_19782697/article/details/100727302
五、自定義starter的開發流程
那么前面對自定義 starter 機制簡單介紹了一下,接下來就進入正題!
自定義starter的開發流程:
? ?1.創建Starter項目(spring-initl 2.1.14)
? ?2.定義Starter需要的配置類(Properties)
? ?3.編寫Starter項目的業務功能
? ?4.編寫自動配置類
? ?5.編寫spring.factories文件加載自動配置類
? ?6.打包安裝
? ?7.其它項目引用
案例一:為短信發送功能創建一個starter
1.創建Starter項目
?
?starter項目和SpringBoot工程結構沒有什么區別,下面就把一些特殊的要求羅列一下
? ? ?1.1.命名規范
? ? ? ?SpringBoot官方命名方式
? ? ? ?格式:spring-boot-starter-{模塊名}
? ? ? ?舉例:spring-boot-starter-web
? ? ? ?自定義命名方式
? ? ? ?格式:{模塊名}-spring-boot-starter
? ? ? ?舉例:mystarter-spring-boot-starter
? ? ?1.2.必須引入的依賴
如果我們剛剛創建項目時選擇了Spring Configuration Processor,在pom.xml文件中就會有上面的依賴
2.編寫相關屬性類(XxxProperties):SmsProperties.java
--@ConfigurationProperties注解基本用法
? ? ? ?前綴定義了哪些外部屬性將綁定到類的字段上
? ? ? ?根據 Spring Boot 寬松的綁定規則,類的屬性名稱必須與外部屬性的名稱匹配
? ? ? ?我們可以簡單地用一個值初始化一個字段來定義一個默認值
? ? ? ?類本身可以是包私有的
? ? ? ?類的字段必須有公共 setter 方法 ??
? ? ?注意:SmsProperties代碼寫完后會報如下錯誤,這是正常的,因為
? ? ? ? ?還有配置類AutoConfig和一個注解@EnableConfigurationProperties沒有加
? ? ? ? ?(Not registered via @EnableConfigurationProperties or marked as Spring component)
3.編寫Starter項目的業務功能?
ISmsService和SmsServiceImpl相關代碼如下:
4.編寫自動配置類AutoConfig?
? ? 4.1. @Configuration:
? ? ? ?定義一個配置類
? ? 4.2. @EnableConfigurationProperties:
? ? ? ?@EnableConfigurationProperties注解的作用是@ConfigurationProperties注解生效。
? ? ? ?如果只配置@ConfigurationProperties注解,在IOC容器中是獲取不到properties配置文? ? ? ? ? ?件轉化的bean的?
5.編寫spring.factories文件加載自動配置類
? ? ?5.1.在resources下新建META-INF文件夾,然后創建spring.factories文件
? ? ?5.2.在該文件中加入如下配置,該配置指定上步驟中定義的配置類為自動裝配的配置
注1:其中AutoConfig是starter配置文件的類限定名,多個之間逗號分割,還可以\進行轉義即相當于去掉后面換行和空格符號,如下所示
?# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration,\com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration6.打包安裝
打包時需要注意一下,SpringBoot項目打包的JAR是可執行JAR,它的類放在BOOT-INF目錄下,如果直接作為其他項目的依賴,會找不到類。可以通過修改pom文件來解決,代碼如下:
<plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><classifier>exec</classifier></configuration> </plugin>打包前,先查看我們maven倉庫的位置,并設置到自己本地倉庫位置中去,再打包。過程如下:
成功后,我們可以發現我們本地倉庫就會有剛剛我們打包完的項目:
到這里為止,我們的整個自定義starter的準備工作就做完了,如下是我的整個自定義starter文件的結構:
7.在其他項目中的應用?
7.1.首先在其他項目的pom.xml中引入相關依賴:
?7.2.在application.yml文件中添加配置
?為了展示效果,我們寫一個測試類,看能否看到我們想要的效果,測試代碼如下:
package com.zking.springboot02.service.impl;import com.zking.springboot02.Springboot02Application; import com.zking.springboot02.model.Book; import com.zking.springboot02.service.IBookService; import com.zking.springboot02.utils.PageBean; import com.zking.zzcloudspringbootstarter.sms.ISmsService; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.redis.core.RedisTemplate;import javax.annotation.Resource; import java.util.List;@SpringBootTest(classes = Springboot02Application.class) class SmsServiceImplTest {@Resourceprivate ISmsService smsService;@BeforeEachvoid setUp() {}@AfterEachvoid tearDown() {}@Testvoid testRedis() {smsService.send("15575488448","pengying","1","小彭不會禿頭加油干!");} }控制臺效果如下:
?如果控制臺有如上效果,說明我們整個自定義starter的過程就成功了!
案例二:AOP方式統一服務日志
原先實現統一日志都是放到每個工程中以AOP方式實現,現在有了starter方式,就可以將公司的日志規范集中到這里來統一管理。
這里我們使用之前創建好的項目進行案例二的編寫,步驟與上同理:
1.導入aop相關依賴
<!--aop相關依賴--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency>2.編寫相關屬性類(XxxProperties):WebLogProperties.java
package com.zking.zzcloudspringbootstarter.sms;import org.springframework.boot.context.properties.ConfigurationProperties;import java.io.Serializable;@ConfigurationProperties("zzcloud.weblog") public class WebLogProperties implements Serializable {public Boolean enabled; //Boolean封裝類,默認為nullpublic Boolean getEnabled() {return enabled;}public void setEnabled(Boolean enabled) {this.enabled = enabled;} }3.編寫Starter項目的業務功能?
package com.zking.zzcloudspringbootstarter.weblog;import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest; import java.util.Arrays;@Aspect @Component @Slf4j public class WebLogAspect {//@Pointcut("execution(public * com.zking..controller.*.*(..))")@Pointcut("execution(* *..*Controller.*(..))")public void webLog(){}@Before("webLog()")public void doBefore(JoinPoint joinPoint) throws Throwable {// 接收到請求,記錄請求內容ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();// 記錄下請求內容log.info("開始服務:{}", request.getRequestURL().toString());log.info("客戶端IP :{}" , request.getRemoteAddr());log.info("參數值 :{}", Arrays.toString(joinPoint.getArgs()));}@AfterReturning(returning = "ret", pointcut = "webLog()")public void doAfterReturning(Object ret) throws Throwable {// 處理完請求,返回內容log.info("返回值 : {}" , ret);} }4.編寫自動配置類AutoConfig?
4.1.@ConditionalOnProperty(prefix = "zzcloud.weblog",value = "enabled", matchIfMissing = true):
matchIfMissing屬性:默認情況下matchIfMissing為false,也就是說如果未進行屬性配置,則自動配置不生效。如果matchIfMissing為true,則表示如果沒有對應的屬性配置,則自動配置默認生效
4.2.@ConditionalOnMissingBean:
在@bean定義上,它的作用就是在容器加載它作用的bean時,檢查容器中是否存在目標類型(ConditionalOnMissingBean注解的value值)的bean了,如果存在這跳過原始bean的BeanDefinition加載動作。
5.編寫spring.factories文件加載自動配置類
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.zking.zzcloudspringbootstarter.config.SmsAutoConfig,\com.zking.zzcloudspringbootstarter.config.WebLogAutoConfig6.打包,操作同上
7.在其他項目中引用
7.1.導入依賴,由于這里我們使用的是之前的那個項目,這里就不需要重復導入依賴了
7.2.在application.yml文件中添加配置
?測試如下:這里我用該項目里的方法進行測試
?如果我不使用日志,效果如下:
反之如果我使用日志,就會拿到我請求的路徑、我的客戶端以及我的參數值,效果如下:
?如果由以上效果,說明我的案例二:AOP方式統一服務日志就成功了!
今天的學習記錄就到這了,拜拜!
說明:學習記錄,若有錯誤,歡迎指正,若有疑問,歡迎評論? ??
總結
以上是生活随笔為你收集整理的SpringBoot之自定义starter的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图片滤镜调色设计
- 下一篇: bin和obj文件夹