4.1.7.手寫實現一個spring boot starter實現
時長:40min
4.1.springboot starter組件
4.1.1.springboot starter組件的實現原理
如果創建一個springboot項目,會在pom.xml自動添加一個starter組件。
4.1.1.1.stater組件的類型
starter包有官方定義包,和第三方定義包。
1.官方starter
命名格式:spring-boot-starter-xxx,如:spring-boot-starter-web
自動裝配,是基於條件裝配。
2.第三方starter
命名格式:xxx-spring-boot-starter,如:mybatis-spring-boot-starter
自動裝配,是基於spring.factories配置文件裝配
4.1.1.2.starter組件做了哪些事情?
starter組件,實際是定義一個模塊。它所做的工作包括:
》整合相關依賴包
》完成自動裝配
4.1.2.基於redis手寫一個starter
4.1.2.1.開發准備
查看本機本地環境是否有安裝redis服務端。個人通過virtualbox + vagrant安裝centos7系統。
希望在centos上安裝redis服務器程序。【這里是在windows系統下】
1.啟動虛擬機
首先,運行virtualbox軟件,剛開始虛擬機是關閉狀態。
然后到centos安裝目錄,打開cmd,啟動vagrant,使用命令:
D:\soft\centos7>vagrant up
啟動完成后,虛擬機變成運行狀態,如下所示:
然后,進入虛擬機,使用命令:
D:\soft\centos7>vagrant ssh
Last login: Mon Jan 6 08:43:36 2020 from 10.0.2.2
[vagrant@localhost ~]$ //這里是vagrant普通用戶登錄
查看ip,使用命令:ip a【這里可以當作是127.0.0.1】
然后,使用xshell工具連接服務端。
然后,查看是否有安裝redis服務器,如果沒有,先進行安裝。
然后,啟動redis,如下所示:
4.1.2.2.開發一個starter
1.創建一個maven工程,開發一個redission的starter組件
因為是自定義的第三方starter包,項目命名為:redission-spring-boot-starter
【1】pom.xml中引入相關依賴包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> //需要springboot的相關注解 <version>2.3.1.RELEASE</version> <optional>true</optional> </dependency> <dependency> <groupId>org.redisson</groupId> //作為redis客戶端組件 <artifactId>redisson</artifactId> <version>3.13.1</version> </dependency>
【2】創建redisson配置類
主要實現RedissonClient這個bean實現條件裝配。
這個client類是用來連接redis服務器的。代碼如下:
package com.wf.redission; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.redisson.config.SingleServerConfig; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @ClassName RedissonAutoConfiguration * @Description 配置類 * @Author wf * @Date 2020/7/8 13:44 * @Version 1.0 */ @Configuration @ConditionalOnClass(Redisson.class) @EnableConfigurationProperties(RedissonProperties.class) public class RedissonAutoConfiguration { //這里傳參RedissonProperties實例,是要求這個bean自動裝配到spring中的。如果未注入,是會報錯的。 //這里通過@EnableConfigurationProperties(RedissonProperties.class)配置類自動裝配 @Bean public RedissonClient redissonClient(RedissonProperties redissonProperties){ Config config = new Config(); String prefix = "redis://"; //是否加密判斷 if(redissonProperties.isSsl()){ prefix = "rediss://"; } String address = prefix + redissonProperties.getHost()+":" + redissonProperties.getPort(); SingleServerConfig singleServerConfig = config.useSingleServer().setAddress(address) .setConnectTimeout(redissonProperties.getTimeout()); return Redisson.create(config); } }
在這種遠程連接的工具類,經常涉及到一個連接參數配置。可以在springboot的外部配置文件中
進行自行配置,這是如何實現的呢?
實際上,是依賴注入一個外部文件配置類。
【3】外部文件配置類創建
package com.wf.redission; import org.springframework.boot.context.properties.ConfigurationProperties; /** * @ClassName RedissonProperties * @Description 配置文件類 * @Author wf * @Date 2020/7/8 13:57 * @Version 1.0 */ @ConfigurationProperties(prefix = "wf.redisson") public class RedissonProperties { private String host = "localhost"; private int port = 6379; private int timeout;//超時時間 private boolean ssl;//是否加密傳輸 public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public int getTimeout() { return timeout; } public void setTimeout(int timeout) { this.timeout = timeout; } public boolean isSsl() { return ssl; } public void setSsl(boolean ssl) { this.ssl = ssl; } }
說明:
這里其實是@ConfigurationProperties(prefix = "wf.redisson")注解起重要作用。
【4】創建配置文件實現自動裝配
創建resources資源文件夾,然后創建META-INF文件夾,並在該目錄下創建spring.factories配置文件,
如下所示:
配置內容如下所示:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.wf.redission.RedissonAutoConfiguration
然后,這個組件就開發完成了。下面進行打包發布。
2.創建springboot項目,引入該starter,進行使用
【1】pom.xml中引入starter依賴
<!--引入 自定義redission starter組件--> <dependency> <groupId>com.wf.redission</groupId> <artifactId>redission-spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
【2】創建redisTestController
package com.wf.demo.springbootdemo.web; import org.redisson.api.RBucket; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @ClassName RedisTestController * @Description redis使用 * @Author wf * @Date 2020/7/8 14:34 * @Version 1.0 */ @RestController public class RedisTestController { @Autowired private RedissonClient redissonClient; @GetMapping("set") public String set(){ RBucket<Object> bucket = redissonClient.getBucket("name"); if(bucket.get() == null){ bucket.set("wf.com"); } return bucket.get().toString(); } }
【3】配置連接參數
具體配置內容如下所示:
wf.redisson.host=127.0.0.1 wf.redisson.port=6379 wf.redissson.timeout=3000
【4】啟動springboot項目,進行測試
啟動失敗,因為redis連接失敗。如下所示:
連接失敗的原因,可能是ip配置不對。
目前配置ip為127.0.0.1,需要查看虛擬機中ip地址是多少。
然后,配置成靜態ip:192.168.33.10,再次啟動失敗。猜想是redis遠程連接未設置好。
結果,果然是這樣。所以,啟動成功。訪問接口如下:
說明:
redis遠程連接,測試通過。說明starter定義成功。
3.開發問題總結
雖然我們的starter開發成功了,功能沒有問題。但是,我在springboot進行配置連接參數時,
key是沒有提示的。
如何能夠實現這種提示功能呢?還是需要修改starter組件。
【1】開發外部配置key提示功能
A.starter組件中引入依賴包
<!--外部配置提示功能--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <version>2.3.1.RELEASE</version> </dependency>
B.META-INF下添加配置文件additional-spring-configuration-metadata.json
這個文件會配置屬性解析,屬性值。從而可以增加一些自動化的描述。
文件內容如何配置,可以參考springboot中的配置文件,如下所示:
{ "properties": [ { "sourceType": "org.apache.ibatis.session.Configuration", "defaultValue": "org.apache.ibatis.scripting.xmltags.XMLLanguageDriver", "name": "mybatis.configuration.default-scripting-language", "description": "A default LanguageDriver class.", "type": "java.lang.Class<? extends org.apache.ibatis.scripting.LanguageDriver>", "deprecation": { "reason": "Because when this configuration property is used, there is case that custom language driver cannot be registered correctly.", "replacement": "mybatis.default-scripting-language-driver" } }, { "sourceType": "org.apache.ibatis.session.Configuration", "defaultValue": "org.apache.ibatis.type.EnumTypeHandler", "name": "mybatis.configuration.default-enum-type-handler", "description": "A default TypeHandler class for Enum.", "type": "java.lang.Class<? extends org.apache.ibatis.type.TypeHandler>" }, { "defaultValue": false, "name": "mybatis.lazy-initialization", "description": "Set whether enable lazy initialization for mapper bean.", "type": "java.lang.Boolean" }, { "name": "mybatis.scripting-language-driver.velocity.userdirective", "deprecation": { "level": "error", "reason": "The 'userdirective' is deprecated since Velocity 2.x. This property defined for keeping backward compatibility with older velocity version.", "replacement": "mybatis.scripting-language-driver.velocity.velocity-settings.runtime.custom_directives" } } ] }
當前組件的配置內容如下:
{ "properties": [ { "name": "wf.redisson.host", "type": "java.lang.String", "description": "redis的服務器地址", "defaultValue": "localhost" }, { "name": "wf.redisson.port", "type": "java.lang.Integer", "description": "redis服務開放端口號", "defaultValue": 6379 }, { "name": "wf.redisson.timeout", "type": "java.lang.Integer", "description": "redis的服務器連接超時時間", "defaultValue": 3000 }, { "name": "wf.redisson.ssl", "type": "java.lang.Boolean", "description": "redis數據傳輸是否加密", "defaultValue": false } ] }
開發就完成了,重新打包發布。
【2】回到springboot項目中測試
發現已經重新打包,還是不能提示。后面我找到原因。
配置的這個路徑:wf.redisson必須與包路徑定義一樣,原來我的包路徑定義為com.wf.redission
所以,不能解析成功。
現在我修改一致之后,重新打包starter項目,在jar包中會自動生成一個spring-configuration-metadata.json
文件,這個文件才是導致key配置提示的關鍵。生成文件如下所示:
下面回到springboot項目中,進行配置,驗證是否會key提示。 可以發現,提示功能成功了。
4.2.Actuator監控
下節再述。