SpringBoot如何手寫一個(gè)starter并使用這個(gè)starter詳解
1、stater工程的命名
starter 是一個(gè)開箱即用的組件,減少不必要的重復(fù)代碼,重復(fù)配置。例如,在mavne項(xiàng)目進(jìn)行配置的時(shí)候,我們需要引用 spring-boot-starter-parent。
Spring 官方定義的 starter 通常命名遵循的格式為 spring-boot-starter-{name},例如 spring-boot-starter-web。
非官方 starter 命名應(yīng)遵循 {name}-spring-boot-starter 的格式,例如,dubbo-spring-boot-starter。
2、需求
寫一個(gè)序列化的插件,并且可以自由的選擇 fastjson 還是 gson,如果沒選的情況下默認(rèn)選擇fastjson。
3、stater步驟
創(chuàng)建一個(gè)Spring Boot項(xiàng)目,這里項(xiàng)目名字叫 jackformat-spring-boot-starter
3.1 引入依賴
<!-- autoconfigure--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <!-- 這個(gè)是用來(lái)提示用的--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <!-- fastjson--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.56</version> </dependency> <!-- gson--> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.2.4</version> </dependency>
注意: 如果在后續(xù)引用stater工程中出現(xiàn) :Unable to read meta-data for class 這個(gè)錯(cuò)誤
處理意見,可以參考文末。
參考博客里面是對(duì)依賴進(jìn)行處理,防止stater引用失敗。
3.2 格式化接口
3.3 配置類
先定義一個(gè)配置類,具體的實(shí)現(xiàn)邏輯在具體的實(shí)現(xiàn)類里面實(shí)現(xiàn)。
public interface FormatProcessor { /** * 定義一個(gè)格式化的方法 */ <T> String format(T obj); }
下面是兩個(gè)具體的配置類
import com.google.gson.Gson; public class GsonFormatProcessor implements FormatProcessor{ @Override public <T> String format(T obj) { return "GsonFormatProcessor" + new Gson().toJson(obj); } }
import com.alibaba.fastjson.JSON; public class FastJsonFormatProcessor implements FormatProcessor{ @Override public <T> String format(T obj) { return "FastJsonFormatProcessor:" + JSON.toJSONString(obj); } }
3.3.1 條件配置
這個(gè)條件配置里面用到了條件注解,如果fastjson和gson類存在的情況下才加載對(duì)應(yīng)的實(shí)現(xiàn)類。
因?yàn)樵趐om文件里面都引用了,所以在這里是都會(huì)被加載的。
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; @Configuration public class FormatAutoConfiguration { /** * @return * @ConditionalOnClass條件注解。如果 fastjson 類存在的情況下才加載對(duì)應(yīng)的實(shí)現(xiàn)類 * 同一個(gè)接口,有幾種不同的實(shí)現(xiàn)類時(shí),@Autowired 是按類型注入的,不知道要選哪一個(gè). * 按照第二點(diǎn)需求,用戶在沒選的情況下默認(rèn)選擇 fastjson,所以這里給 fastjson 的實(shí)現(xiàn)上打上 @Primary */ @ConditionalOnClass(name = "com.alibaba.fastjson.JSON") @Bean @Primary public FormatProcessor fastJsonFormat() { return new FastJsonFormatProcessor(); } /** * 如果 Gson 類存在的情況下才加載對(duì)應(yīng)的實(shí)現(xiàn)類 * * @return */ @ConditionalOnClass(name = "com.google.gson.Gson") @Bean public FormatProcessor gsonJsonFormat() { return new FastJsonFormatProcessor(); } }
代碼段里面有 @Primary 注解,這是為了用戶在沒有手動(dòng)選擇的時(shí)候,默認(rèn)選擇fastjson。(如果自動(dòng)注入選的是@Autowired的話,因?yàn)锧Autowired默認(rèn)是類型注入的,不知道選擇哪一種類型)
3.3.2 讀取配置
這個(gè)配置類主要是用來(lái)讀取用戶的選擇,作用和@Value作用一致
import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = FormatProperties.ORMAT_PREFIX) public class FormatProperties { public static final String ORMAT_PREFIX = "jackluo.format"; private String type; public String getType() { return type; } public void setType(String type) { this.type = type; } }
3.4 序列化實(shí)現(xiàn)類
import com.jackluo.autoconfiguration.FormatProcessor; public class FormatTemplate { private FormatProcessor formatProcessor; public FormatTemplate(FormatProcessor formatProcessor) { this.formatProcessor = formatProcessor; } public <T> String doFormat(T obj) { return formatProcessor.format(obj); } }
序列化實(shí)現(xiàn)類,這個(gè)是來(lái)提供給用戶序列化的。
3.5 邏輯配置類
import com.jackluo.format.FormatTemplate; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Import(FormatAutoConfiguration.class) @EnableConfigurationProperties(FormatProperties.class) @Configuration public class JackluoFormatConfiguration { @Bean public FormatTemplate helloFormatTemplate(FormatProperties formatProperties, @Qualifier("fastJsonFormat") FormatProcessor formatProcessor) { if ("fastjson".equals(formatProperties.getType())) { return new FormatTemplate(new FastJsonFormatProcessor()); } if ("gson".equals(formatProperties.getType())) { return new FormatTemplate(new GsonFormatProcessor()); } return new FormatTemplate(formatProcessor); } }
@Import 導(dǎo)入配置類,就是將該配置類中的 Bean 注入到容器
@EnableConfigurationProperties 這是在將屬性類激活,注入到容器中,也可以用 @Bean 的方式
@Configuration 說(shuō)明這是一個(gè)配置類
流程是 FormatProperties 屬性類注入到容器當(dāng)中,如果是fastjson就去走fastjaon的邏輯實(shí)現(xiàn)類;反之是gson也是一樣。如果沒有以上情況,就走上面配置的默認(rèn)項(xiàng)。
3.6 創(chuàng)建 META-INF/spring.factories
因?yàn)閟pringboot在啟動(dòng)的時(shí)候是讀取該文件下面的配置類,從而將Bean加載到容器當(dāng)中。所以我們寫stater也是一樣的道理。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.jackluo.autoconfiguration.JackluoFormatConfiguration
注意:有多個(gè)文件的時(shí)候是需要用 ,\ 來(lái)隔開的。如:
以上。一個(gè)手寫的stater就OK了,我們需要引用直接打jar包在其他項(xiàng)目直接引用即可。
下面是引用過(guò)程。
4、 引用-測(cè)試
4.1 打包
4.2 引入依賴
<dependency> <groupId>com.jackluo</groupId> <artifactId>jackformat-spring-boot-starter</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
這個(gè)依賴命名方式就是我們寫的stater工程的名稱,這個(gè)一眼就是能看出來(lái)的。
4.3 選用序列化
在.yml文件中配置我們需要選用的序列化方式。
我們選用gson。測(cè)試完可以試試什么也不選出來(lái)什么結(jié)果
4.4 調(diào)用
定義一個(gè)實(shí)體類,定義一個(gè)controller,直接調(diào)用即可。
4.5結(jié)果
當(dāng)選用gson的時(shí)候出來(lái)的是:GsonFormatProcessor。
默認(rèn)什么也不選的時(shí)候,出現(xiàn)的是:FastJsonFormatProcessor。
和我們?cè)趕tater的結(jié)果是一樣的。
至此,一個(gè)完整的stater和引用已經(jīng)OK了。
補(bǔ)充:自定義starter出現(xiàn)Unable to read meta-data for class 這樣解決
錯(cuò)誤:
在自己寫了一個(gè)stater包后,在其他工程進(jìn)行調(diào)用。
正常情況是自定義的stater包打包完畢,在另一個(gè)工程maven里面調(diào)用就行。
但是這次調(diào)用的時(shí)候出現(xiàn)了以下情況。
這種情況,由截圖錯(cuò)誤可知,就是:不能在XXX包中讀取XXX文件
排查:
查找很多方法,大多數(shù)問(wèn)題是由于spring.factories配置有問(wèn)題。
大多存在的問(wèn)題是多行之間沒有用.\連接,或者是.和\之間有空格之類的問(wèn)題
或者是要掃描的包路徑直接寫錯(cuò)了(說(shuō)明確實(shí)得檢查一下)
我們?nèi)ゲ榭磗pring.factories,發(fā)現(xiàn)沒有什么問(wèn)題。
糾錯(cuò):
鑒于這個(gè)問(wèn)題是個(gè)細(xì)節(jié)問(wèn)題,不能輕言放棄。
ok,又在找到底是什么錯(cuò)。
看到了網(wǎng)上的一篇帖子。
主要解決方案就是去掉springboot的打包插件,然后打包就正常了。在此感謝。
我采用的是直接在maven打包插件中間加了一行。
最后就可以了。
后記:遇見問(wèn)題還是得一點(diǎn)點(diǎn)排查,不能輕言放棄。多看看大家的想法和思路。根據(jù)自己的實(shí)際情況酌情采用。
總結(jié)
到此這篇關(guān)于SpringBoot如何手寫一個(gè)starter并使用這個(gè)starter的文章就介紹到這了,更多相關(guān)SpringBoot手寫starter并使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mybatis-plus實(shí)體類主鍵策略有3種(小結(jié))
這篇文章主要介紹了mybatis-plus實(shí)體類主鍵策略有3種(小結(jié)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08Java Swing實(shí)現(xiàn)簡(jiǎn)單的體重指數(shù)(BMI)計(jì)算器功能示例
這篇文章主要介紹了Java Swing實(shí)現(xiàn)簡(jiǎn)單的體重指數(shù)(BMI)計(jì)算器功能,涉及Java Swing窗口組件布局、響應(yīng)及數(shù)值運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2017-12-12Java實(shí)現(xiàn)簡(jiǎn)單點(diǎn)餐系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單點(diǎn)餐系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01spring Boot查詢數(shù)據(jù)分頁(yè)顯示的方法實(shí)例
這篇文章主要給大家介紹了關(guān)于spring Boot查詢數(shù)據(jù)分頁(yè)顯示的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08Mybatis中動(dòng)態(tài)SQL,if,where,foreach的使用教程詳解
MyBatis的動(dòng)態(tài)SQL是基于OGNL表達(dá)式的,它可以幫助我們方便的在SQL語(yǔ)句中實(shí)現(xiàn)某些邏輯。這篇文章主要介紹了Mybatis中動(dòng)態(tài)SQL,if,where,foreach的使用教程,需要的朋友可以參考下2017-11-11