三分鐘實戰手寫Spring Boot Starter

2023-02-21 18:01:58

1 背景

在平時的開發中,開發的同學會把一些通用的方法,寫成一個工具類,例如日期轉換的,JSON轉換的等等,方便業務後續呼叫,使程式碼更容易維護。

如果一些更常用的方法,例如鑑權的,加解密的等等,幾乎每個專案都會使用到,這時候開發的同學就會從以前的專案中再抄過來,隨著專案的增多,幾乎每個專案都有一份一模一樣的工具類。經過技術評審決定,將這些工具類打包成jar包,後續的新專案可以直接以jar包的形式引入,重用就會變得非常的好。

由於專案本身是基於Spring Boot進行開發,jar包以Spring Boot Starter的方式釋出似乎是不錯的選擇。

2 介紹

Spring Boot Starter 和普通jar包的區別在於,Spring Boot Starter 更加靈活,提供了自動裝配的機制,以及可供使用者設定等。下面以 加解密作為例子,手寫一個 Spring Boot Starter ,從實戰到原理去了解它的工作過程。

3 建立專案

建立一個Spring Boot 的專案,專案命名為digest-spring-boot-starter

spring官方的包命名為:spring-boot-starter-xxx

第三方包命名為:xxx-spring-boot-starter

pom.xml中引入依賴commons-codec(apache官方提供的加解密演演算法的工具包)

       <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
        </dependency>

4 主體部分

加密邏輯書寫,提供一個 Digest 介面,使用常用的 Md5Sha256摘要演演算法進行加密實現。

public interface Digest {

    /**
     * 摘要演演算法
     * @param raw 字串
     * @return 加密後的字串
     */
    String digest(String raw);

}
public class Md5Digest implements Digest {
    @Override
    public String digest(String raw) {
        System.out.println("使用MD5演演算法生成摘要");
        return DigestUtils.md5Hex(raw);
    }
}
public class Sha256Digest implements Digest {
    @Override
    public String digest(String raw) {
        System.out.println("使用SHA256演演算法生成摘要");
        return DigestUtils.sha256Hex(raw);
    }
}

如果需要使用者來指定使用哪種加密演演算法,需要在application.properties中新增一項設定:

digest.type=sha

建立一個設定類,拿到使用者設定的type:

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "digest")
public class Config {

    private String type;

    /**
     * <bean id="md5Digest" class="com.xiaofengstu.digest.impl.Md5Digest"/>
     * @return Digest
     */
    @Bean
    @ConditionalOnProperty(prefix = "digest", name = "type", havingValue = "md5")
    public Digest md5Digest() {
        return new Md5Digest();
    }

   @Bean
   @ConditionalOnProperty(prefix = "digest", name = "type", havingValue = "sha")
    public Digest sha256Digest() {
        return new Sha256Digest();
    }
}

日常開發中,比較常用的幾個註解為:

@ConditionalOnBean:當容器中存在指定Bean的條件下

@ConditionalOnClass:當類路徑匣有指定類的條件下

@ConditionalOnProperty:指定的屬性是否有指定的值

5 設定自動裝配

在 resources 目錄下,建立一個資料夾名為 META-INF,建立一個檔名為spring.factories

這一步是固定寫法

由於我們自己開發的starter是沒有啟動類的,所以需要告訴參照 starter 的專案,需要去載入哪些類。

spring.factories中填寫:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.xiaofengstu.digest.conf.Config

註釋掉pom.xml中關於spring-boot-maven-plugin的部分,以至於後續執行 mvn package 操作得到是一個標準的jar包。

再執行mvn installstarter打包到本地倉庫中。

6 使用starter

在需要的專案中引入剛剛打包好的starter

	<dependency>
            <groupId>com.xiaofengstu</groupId>
            <artifactId>digest-spring-boot-starter</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

在程式碼中直接注入 Digest 即可:

@Resource
private Digest digest;

總結

  1. spring boot 2.7+ 的版本,spring.factorys寫法稍有改動:

    檔案內容,一行就是一個裝配類:

  2. 如果沒看明白的,可以參考一下 mybatis-plus-spring-boot-starter的寫法