javascript
Spring Boot 如何自定义Starter,你知道吗?
原文:https://shimo.im/docs/ywxu41XEYxYXYy3U/read
如果我們系統中想要擁有自動配置的功能,可以自己編寫一個starter?(啟動器),想想就覺得很酷,因為這意味著我們不僅有自己定義的自動配的功能,而且具有更通用的耦合度更低的配置。
以一個簡單功能為例:瀏覽器發送?sayHello?請求,服務器接受請求并處理,響應?Hello?。
首先我們看下工程結構:
helloworld-spring-boot-starter-autoconfigure(以下簡稱autoconfigure):該模塊用來實現?Helloworld?的自動配置功能,它的打包方式為?jar;
helloworld-spring-boot-starter(以下簡稱starter):該模塊的打包方式是?jar,依賴?autoconfigure?模塊,它不寫任何代碼,只做自動配置包的自動引入,如果要使用?helloworld?自動配置功能,只要在?pom?文件中引入?starter?模塊即可:
<dependency><groupId>com.seagetech.spring.boot</groupId><artifactId>helloworld-spring-boot-starter</artifactId><version>0.0.1-SNAPSHOT</version> </dependency>1 項目工程的創建
1.1 創建Empty Project
1) 新建一個空的項目,如下圖,點擊Next
2) 輸入項目名稱以及選擇項目存放路徑,點擊Finish
1.2 創建starter模塊
1) 在1.1節中新建的空項目基礎上新建一個Module
2) 選擇Maven,點擊Next
3) 輸入GroupId、ArtifactId 和 Version 信息,點擊Finish
4)?由于這個模塊只做自動配置包的引入,所有刪除?src?下的包,最終項目結構如下:
pom.xml?文件:
<?xml version="1.0"?encoding="UTF-8"?> <project?xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0?http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.seagetech.spring.boot</groupId><artifactId>helloworld-spring-boot-starter</artifactId><version>1.0-SNAPSHOT</version> </project>1.3 創建 autoconfigure 模塊
1) 按1.2節第1步,新建一個 Module,并選擇 Spring Initializr,點擊Next
2)?輸入項目相關信息,如下圖所示:
3) 選擇依賴,我們這里只選擇web場景的依賴,點擊Next
4) 默認,不需要改動,點擊Finish
5)?刪除?SpringBoot?自動創建的主配置類、resources?下所有文件(夾)以及?test?文件夾,最終項目結構如下:
?
pom.xml(已刪除 test 測試模塊的自動配置包以及 build 下的 Maven 插件)
<?xml version="1.0"?encoding="UTF-8"?> <project?xmlns="http://maven.apache.org/POM/4.0.0"?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0?http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.seagetech.spring.boot</groupId> <artifactId>helloworld-spring-boot-starter-autoconfigure</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>helloworld-spring-boot-starter-autoconfigure</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>6)?在1.2節創建的?helloworld-spring-boot-starter?的?pom?下模塊引入本節創建的?autoconfigure?模塊:
<dependency> <groupId>com.seagetech.spring.boot</groupId> <artifactId>helloworld-spring-boot-starter-autoconfigure</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>1.4 實現HelloWorld自動配置
1)?在?helloworld?包下新建?HelloWorldProperties?類,作為配置類,目的是后面使用這個自動配置,直接可以在?application.properties?文件中配置:
package?com.seagetech.spring.boot.helloworld;import?org.springframework.boot.context.properties.ConfigurationProperties;/** * HelloWorld屬性配置類 *?@auther:?wangzb *?@date:?2018/11/13?22:21 */ @ConfigurationProperties(prefix =?"hello") public?class?HelloWorldProperties?{/***?打招呼的內容,默認為“World!”*/private?String msg =?"World!";public?String?getMsg()?{return?msg;}public?void?setMsg(String msg)?{this.msg = msg;}}2)?新建?HelloWorldService?接口,并實現:
接口:
/** *?@auther:?wangzb *?@date:?2018/11/13?22:28 */ public?interface?HelloWorldService?{/*** 打招呼方法*?@param?name 人名,向誰打招呼使用*?@return*/String sayHello(String name);}實現類:
/** *?@auther:?wangzb *?@date:?2018/11/13?22:33 */ @Component public?class?HelloWorldServiceImpl?implements?HelloWorldService{@Autowiredprivate?HelloWorldProperties helloWorldProperties;/*** 打招呼方法**?@param?name 人名,向誰打招呼使用*?@return*/@Overridepublic?String?sayHello(String name)?{return?"Hello "?+ name +?" "?+ helloWorldProperties.getMsg();}}3) 新建 HelloWorldAutoConfiguration 配置類
/** *?@auther:?wangzb *?@date:?2018/11/13?22:37 */ @Configuration @ConditionalOnWebApplication @EnableConfigurationProperties({HelloWorldProperties.class}) @Import(HelloWorldServiceImpl.class) public class HelloWorldAutoConfiguration {}1.5 創建 spring.factories 文件
在?SpringBoot自動配置原理?中,我們提到?@EnableAutoConfiguration?的關鍵功能是使用?SpringFactoriesLoader.loadFactoryNames?方法來掃描具有?META-INF/spring.factories?文件的?jar?包,這樣我們的自動配置類才能生效,所以我們在?autoconfigure?模塊的?resources?下創建?META-INF/spring.factories?文件:
在?spring.factories?中寫入:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.seagetech.spring.boot.helloworld.HelloWorldAutoConfiguration2. helloworld 自動配置的使用
創建好?helloworld?自動配置項目后,接下來就是使用了,我們在?Idea?中使用?install?將1節中創建好的?starter/autoconfigure?模塊打包到本地?Maven?創庫,然后在?SpringBoot入門?章節創建的?sping-boot-demo?項目中使用,在其?pom?文件中引入:
<dependency><groupId>com.seagetech.spring.boot</groupId><artifactId>helloworld-spring-boot-starter</artifactId><version>0.0.1-SNAPSHOT</version> </dependency>在主配置類路徑下創建?HelloWorldController?:
package?com.seagetech.springbootdemo;import?com.seagetech.spring.boot.helloworld.HelloWorldService; import?org.springframework.beans.factory.annotation.Autowired; import?org.springframework.stereotype.Controller; import?org.springframework.web.bind.annotation.RequestMapping;/** *?@auther:?wangzb *?@date:?2018/11/17?11:17 */ @Controller public class HelloWorldController {@Autowiredprivate HelloWorldService helloWorldService;@RequestMapping(value?=?"/sayHello")public String sayHello(String name){return?helloWorldService.sayHello(name);}}啟動項目,在瀏覽器輸入:http://localhost:8080/sayHello?name=wangzb,瀏覽器返回:
我們在重啟項目,重復以上步驟,瀏覽器響應:
3. 元數據的配置
到目前為止,helloworld?的自動配置功能已實現,并且正確使用了,但還有一點不夠完美,如果你也按上面步驟實現了自己的?helloworld?自動配置,在?application.properties?中配置?hello.msg?屬性時,你會發現并沒有提示你有關該配置的信息,但是如果你想配置?Tomcat?端口時,輸入?server.port?是有提示的:
這種功能我們如何做呢,我們打開?SpringBoot入門?章節下載的?“spring-boot-reference.pdf”?文件,在目錄中找到?“Appendix?B.?Configuration?Metadata(附錄B.配置元數據)”,下面我們使用谷歌來翻譯下相關原文:
? ?Spring Boot jars include metadata files that provide details of all supported configuration properties.The files are designed to let IDE developers offer contextual help and “code completion” as users are working with application.properties or application.yml files.
Spring?Boot?jar?包含元數據文件,提供所有支持的配置屬性的詳細信息。這些文件旨在讓?IDE?開發人員使用?application.properties或?application.yml?文件像用戶一樣提供上下文幫助和“代碼完成”
……
B.1 Metadata Format
Configuration?metadata?files?are?located?inside?jars?under?META-INF/spring-configurationmetadata.json?They?use?a?simple?JSON?format?with?items?categorized?under?either?“groups”?or?“properties”?and?additional?values?hints?categorized?under?“hints”,?as?shown?in?the?following?example:
B.1 元數據格式
配置元數據文件位于?META-INF?/?spring-configuration-metadata.json下的?jar?中。它們使用簡單的?JSON?格式,其中的項目分類為?“groups”?或?“properties”?和其他值提示分類在?“hints”?下。
??….
看看它的例子:
{"groups":?[{ "name":?"server", "type":?"org.springframework.boot.autoconfigure.web.ServerProperties", "sourceType":?"org.springframework.boot.autoconfigure.web.ServerProperties" }, ... ], "properties":?[{ "name":?"server.port", "type":?"java.lang.Integer", "sourceType":?"org.springframework.boot.autoconfigure.web.ServerProperties" },{ "name":?"server.address", "type":?"java.net.InetAddress", "sourceType":?"org.springframework.boot.autoconfigure.web.ServerProperties" }, ... ], "hints":?[{ "name":?"spring.jpa.hibernate.ddl-auto", "values":?[{ "value":?"none", "description":?"Disable DDL handling." },{ "value":?"validate", "description":?"Validate the schema, make no changes to the database." },{ "value":?"update", "description":?"Update the schema if necessary." }] ]}所以元數據是在位于?META-INF/spring-configuration-metadata.json?下配置的,下面就列出有關?groups、properties、hints?使用。
3.1 Group屬性
“groups”?中包含的?JSON?對象可以包含下表中顯示的屬性:
3.2 Property屬性
properties?數組中包含的?JSON?對象可由以下屬性構成:
3.3 hints屬性
hints?數組中包含的?JSON?對象可以包含以下屬性:
每個?“hints”?元素的?values?屬性中包含的?JSON?對象可以包含下表中描述的屬性:
每個?“hints”?元素的?providers?屬性中的?JSON?對象可以包含下表中描述的屬性:
3.4 配置元數據
所以如果想有更好的用戶體驗,可以為我們自定義的?starter?配置元數據,下面就為?HelloWorld?配置元數據。
在?META-INF?下創建?spring-configuration-metadata.json?文件:
在文件中輸入如下內容:
{ "hints":[{ "name":"hello.msg", "values":[{ "value":"你好", "description":"中文方式打招呼" },{ "value":"Hi", "description":"英文方式打招呼" }] }], "groups":[ { "sourceType":?"com.seagetech.spring.boot.helloworld.HelloWorldProperties", "name":?"hello", "type":?"com.seagetech.spring.boot.helloworld.HelloWorldProperties" }], "properties":[ { "sourceType":?"com.seagetech.spring.boot.helloworld.HelloWorldProperties", "name":?"hello.msg", "type":?"java.lang.String", "description":?"打招呼的內容", "defaultValue":?"Worlds" }] }然后將?autoconfigure?模塊重新打包,接下來就是在?spring-boot-demo?項目中使用,如下圖所示,就有了屬性的提示:
總結
以上是生活随笔為你收集整理的Spring Boot 如何自定义Starter,你知道吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 迄今为止把同步/异步/阻塞/非阻塞/BI
- 下一篇: 激烈竞争的时代,哪些能力可以帮你脱颖而出