dw怎么做網(wǎng)站后臺(tái)網(wǎng)站策劃運(yùn)營
starter項(xiàng)目
先來看一下Starter的官方解釋:?
Spring Boot Starter 是一種方便的依賴管理方式,它封裝了特定功能或技術(shù)棧的所有必要依賴項(xiàng)和配置,使得開發(fā)者可以快速地將這些功能集成到Spring Boot項(xiàng)目中。Spring Boot官方提供了一系列的Starters,涵蓋了從Web開發(fā)到安全、數(shù)據(jù)訪問等多個(gè)方面
其實(shí)Starter是一種SDK思想,基于SDK高度抽象快速構(gòu)建功能塊或技術(shù)塊是當(dāng)下企業(yè)技術(shù)部門實(shí)現(xiàn)技術(shù)資產(chǎn)快速開發(fā)的利器,基于Spring的starter自然就是最高效的方法。
starter項(xiàng)目結(jié)構(gòu)分析
我們先來看一下mybatis-spring-boot-starter的項(xiàng)目結(jié)構(gòu)
拋開mybatis的jdbc等逐步演化的核心功能依賴,只專注我們想要參觀的starter部分可以看到,mybatis-spring-boot-starter被引入后是以兩個(gè)jar的形式存在,即
- mybatis-spring-boot-autoconfigure
- mybatis-spring-boot-starter?
其中,mybatis-spring-boot-starter 項(xiàng)目中并無代碼,僅僅一個(gè)pom文件指明依賴
<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><parent><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot</artifactId><version>2.1.4</version></parent><artifactId>mybatis-spring-boot-starter</artifactId><name>mybatis-spring-boot-starter</name><properties><module.name>org.mybatis.spring.boot.starter</module.name></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!--mybatis-starter的代碼項(xiàng)目--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-autoconfigure</artifactId></dependency><!-- 支撐mybatis-starter的其他依賴--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId></dependency></dependencies>
</project>
也就是說,?mybatis-starter與SpringBoot對接的主要邏輯集中在mybatis-spring-boot-autoconfigure 中,mybatis-spring-boot-starter ?僅僅是個(gè)殼子,它統(tǒng)一管理mybatis在適配SpringBoot中的資源依賴統(tǒng)一管理。
根據(jù)mybatis-starter以及其他標(biāo)準(zhǔn)的start開發(fā)、SpringBoot的官方資料,我們進(jìn)行自定義一個(gè)starter的形式應(yīng)該是以maven的多module形式創(chuàng)建一個(gè)項(xiàng)目,該項(xiàng)目下包含兩個(gè)module,一個(gè)是XXX-spring-boot-starter,另一個(gè)是XXX-spring-boot-autoconfigure,且XXX-spring-boot-starter 僅僅是一個(gè)只包含pom依賴的的空白項(xiàng)目。
編寫一個(gè)自定義的starter包的流程
在之前的SpringBoot中通過自定義注解使用AOP里,我們使用AOP實(shí)現(xiàn)了日志監(jiān)聽,這里還是以這個(gè)為例子,將它改造為一個(gè)開箱即用的starter。
第一步:創(chuàng)建module
根據(jù)SpringBoot的官方結(jié)構(gòu),創(chuàng)建module項(xiàng)目lognote-spring-boot
<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>org.example</groupId><artifactId>lognote-spring-boot</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging><modules><module>lognot-spring-boot-starter</module><module>lognote-spring-boot-autoconfgure</module></modules><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties></project>
lognote-spring-boot下分別包含兩個(gè)module,作為公共對外的lognote-spring-boot-starter和與SpringBoot框架完成自動(dòng)注入對接的lognote-spring-boot-autoconfigure?
?
第二步:管理依賴
根據(jù)上述分析mybatis的例子,對starter子module的pom進(jìn)行設(shè)置,讓其依賴autoconfigure,以下是lognote-spring-boot-starter的pom文件依賴:
<dependencies><dependency><groupId>org.example</groupId><artifactId>lognote-spring-boot-autoconfgure</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies>
對autoconfigure項(xiàng)目進(jìn)行所需依賴引入,引入對接SpringBoot的核心依賴autoconfigure和一些常用的依賴,以下是lognote-spring-boot-autoconfigure的pom文件?:
<dependencies><!-- starter包必須引入該依賴,完成對SpringBoot的適配 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId><version>2.3.6.RELEASE</version></dependency><!--其他相關(guān)依賴--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.30</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.8</version></dependency></dependencies>
第三步:autoconfigure項(xiàng)目中增加配置文件
剩下的相關(guān)功能及相關(guān)配置代碼均在lognote-spring-boot-autoconfigure項(xiàng)目中完成
使用新建基礎(chǔ)配置啟動(dòng)類:
@Configuration
@ComponentScan(basePackages = "org.example.lognote.*")
public class ApplicationConfiguration {
}
配置spring.factories文件
在resources目錄下新建META-INFO目錄,新建spring.factories文件,文件中指定lognote-spring-boot-autoconfigure項(xiàng)目的啟動(dòng)類路徑即可:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.example.lognote.ApplicationConfiguration
配置yml文件及相關(guān)配置內(nèi)容(可選)
可根據(jù)組件情況是否進(jìn)行yml相關(guān)配置,這里進(jìn)行是否啟用日志記錄的開關(guān)配置,需要在yml中增加配置參數(shù):
#yml文件下新增配置,默認(rèn)為關(guān)閉
lognote:enable: false
當(dāng)被其他SpringBoot項(xiàng)目引用時(shí),可在其yml文件中進(jìn)行配置即可。
創(chuàng)建參數(shù)的實(shí)體類
@ConfigurationProperties(prefix = "lognote")
@Data
@Configuration
public class LogNoteProperties {private Boolean enable = false;
}
?創(chuàng)建判定條件邏輯類,可基于配置內(nèi)容,決定是否注入或者使用內(nèi)部相關(guān)功能,(在下面具體代碼中會(huì)使用該條件判定)
public class LogNoteCondition implements Condition {@Overridepublic boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {String able= conditionContext.getEnvironment().getProperty("lognote.enable");if(null!= able && Boolean.parseBoolean(able) ){return true;}return false;}
這里提供的是基于實(shí)現(xiàn)條件接口進(jìn)行自定義代碼的邏輯處理方式來判定條件,也可以使用:@ConditionalOnProperty等注解來實(shí)現(xiàn)這個(gè)訴求?
第四步:? 封裝功能編寫代碼
上述內(nèi)容完成后,對于lognote-spring-boot-autoconfigure來說,直接進(jìn)行相關(guān)代碼的編寫,就像在SpringBoot項(xiàng)目中一樣,可以直接使用SpringBoot中的相關(guān)注解等信息,我們在starter中創(chuàng)建的bean以及一些對象,在starter被SpringBoot的項(xiàng)目引用后,會(huì)一并交由引用方的Spring上下文去管理。
?相關(guān)AOP及注解內(nèi)容、邏輯細(xì)節(jié)可在?SpringBoot中通過自定義注解使用AOP中了解,這里僅僅放一下核心代碼部分。
首先定義一個(gè)注解:
@Target(ElementType.METHOD) // 指定注解的適用范圍
@Retention(RetentionPolicy.RUNTIME) //指定運(yùn)行時(shí)
//根據(jù)條件確定該注解是否生效
@Conditional(LognoteCondition.class)
public @interface LogNote {//方法描述String desc() default "";//是否記錄方法執(zhí)行耗時(shí)boolean timeSpan() default true;
}
進(jìn)行切面邏輯開發(fā)
@Component
@Aspect
@Slf4j(topic = "LogNote")
public class LogNoteAspect {@Around("@annotation(org.example.LogNote)")public Object aroundAdvice(ProceedingJoinPoint point) throws Throwable {MethodSignature signature = (MethodSignature) point.getSignature();//獲取被調(diào)用方法Method method = signature.getMethod();//取出被調(diào)用方法的注解,方便后續(xù)使用注解中的屬性ApiLog loglinstener = method.getAnnotation(ApiLog.class);log.info("----------------------method[{}]start--------------------",method.getName());log.info("方法描述:{}",loglinstener.desc());log.info("參數(shù) :{}",point.getArgs());long startTime = System.currentTimeMillis();Object proceed = point.proceed();long endTime = System.currentTimeMillis();log.info("耗時(shí):{}ss",endTime-startTime);log.info("----------------------method[{}] end--------------------\n",method.getName())return proceed;}
}
第五步:測試&打包
使用maven將整個(gè)lognote-spring-boot-starter項(xiàng)目進(jìn)行打包,將該依賴引入到自己項(xiàng)目中,在yml中進(jìn)行相關(guān)配置開啟,然后進(jìn)行使用:
<!-- 在相關(guān)項(xiàng)目中引入自定義的lognote-spring-boot-starter依賴 -->
<dependency><groupId>org.example</groupId><artifactId>lognote-spring-boot-starter</artifactId><version>1.0-SNAPSHOT</version>
</dependency>
使用:
@LogNote(desc = "執(zhí)行Es查詢")public JSONObject seachEsData(String indexName, SearchSourceBuilder searchSourceBuilder) {JSONObject resultMap = new JSONObject();.......return resultMap;}
運(yùn)行效果:
2023-06-05 20:00:00 [LogNote] :--------------------method[searchESData]start---------------
2023-06-05 20:00:00 [LogNote] :方法描述:執(zhí)行Es查詢
2023-06-05 20:00:00 [LogNote] :參數(shù) :{"query":{"match_all:{}","size":1,"from":0}},log
2023-06-05 20:00:00 [LogNote] :耗時(shí) : 58ss
2023-06-05 20:00:00 [LogNote] :--------------------method[searchESData] end---------------
補(bǔ)充:starter項(xiàng)目的規(guī)范結(jié)構(gòu)
結(jié)合上面的例子,其實(shí)不難發(fā)現(xiàn),starter的開發(fā)核心是與SpringBoot進(jìn)行連接,包括Spring上下文的串通、SpringBoot的自動(dòng)化配置串通等,其核心是在于lognote-spring-boot-autoconfigure,甚至直接進(jìn)行l(wèi)ognote-spring-boot-configure開發(fā),第三方直接引用lognote-spring-boot-configure都可以。亦或者只創(chuàng)建一個(gè)lognote-spring-boot-starter項(xiàng)目,把原本寫在autoconfigure的代碼和spring.factories配置放到里面都行,這樣甚至更簡便,那么官方為什么還要引導(dǎo)使用module的形式呢。此種方式可以參考這個(gè)項(xiàng)目
?其實(shí)官方的推薦是站在組件的角度去考慮,starter是以組件級為基礎(chǔ)單位,所以采用module的方式進(jìn)行開發(fā)具有更好的解耦性,可以明確層次的組件邊界的概念。
使用該結(jié)構(gòu)的優(yōu)勢主要有兩點(diǎn)
組件開發(fā)管理規(guī)范化
使用module可以使組件的開發(fā)更加規(guī)范化,同一組件相關(guān)邏輯和內(nèi)容可以集中在一個(gè)module中而不是四散的各個(gè)獨(dú)立的項(xiàng)目。
另外,對于開發(fā)中的依賴管理也可以更加友好,例如原本在lognote-spring-boot-autoconfigure中的一堆依賴,目前僅僅是單獨(dú)在autoconfigure中,如果再有新的組件擴(kuò)展需要,新項(xiàng)目可能還要再額外進(jìn)行引入依賴,這中間各個(gè)項(xiàng)目的版本管理以及組件本身的版本管理,?如果使用module集中管理的方式,組件相關(guān)的擴(kuò)展以及核心代碼都在XXX-spring-boot這個(gè)父項(xiàng)目中,各子包、組件所需的依賴也可以統(tǒng)一在一處管理,對于組件的版本、發(fā)布都是十分規(guī)范的。
例如上述例子中,可以將autoconfigure的通用依賴統(tǒng)一放到lognote-spring-boot這個(gè)父類的pom中統(tǒng)一引入管理
<modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>lognote-spring-boot</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging><modules><module>lognot-spring-boot-starter</module><module>lognote-spring-boot-autoconfgure</module></modules><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><!-- 公共依賴 --><dependencyManagement><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.30</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.8</version></dependency></dependencyManagement>
組件的擴(kuò)展和演進(jìn)更友好
XXX-spring-boot-starter作為整個(gè)組件的唯一出口,是對外交流的,所以只需要是“接口”、“封面"性質(zhì)即可,autoconfigure是作為與SpringBoot的Spring上下文和自動(dòng)化配置對接的一個(gè)銜接邏輯,本質(zhì)也是在對接層,而核心的組件則可以以jar進(jìn)行靈活開發(fā)。例如mybatis,它的核心jdbc以及mybtais相關(guān)邏輯組件,都可以獨(dú)立進(jìn)行開發(fā),最后統(tǒng)一通過autoconfigure進(jìn)行與SpringBoot進(jìn)行對接即可兼容SpringBoot,日后再有其他框架,也可以在autoconfigure層進(jìn)行適配。其核心部分?