自定義一個spring-boot-starter

自定義spring-boot-starter

1.自定義starter項目

Spring 官方定義的 starter 通常命名遵循的格式爲 spring-boot-starter-{name},例如 spring-boot-starter-web。非官方 starter 命名應遵循 {name}-spring-boot-starter 的格式,例如,dubbo-spring-boot-starter 。

創建一個Spring Boot項目,名稱jsonformat-spring-boot-starter。

2.引入依賴

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <!-- 這個是用來提示用的-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.70</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.6</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.11.0</version>
        </dependency>

3.先定義一個格式化的接口,3個實現類

接口

public interface FormatProcessor {
    /**
     * 定義一個格式化的方法
     * @param obj
     * @param <T>
     * @return
     */
    <T> String format(T obj);
}

3個實現類

public class JacksonFormatProcessor implements FormatProcessor{

    Logger logger=Logger.getLogger("JacksonFormatProcessor");
    @Override
    public <T> String format(T obj) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            logger.info("===========jackson format===========");
            return mapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }
}
public class GsonFormatProcessor implements FormatProcessor{
    Logger logger=Logger.getLogger("GsonFormatProcessor");
    @Override
    public <T> String format(T obj) {
        Gson gson= new Gson();
        logger.info("===========gson format===========");
        return gson.toJson(obj);
    }
}
public class FastjsonFormatProcessor implements FormatProcessor{

    Logger logger=Logger.getLogger("FastjsonFormatProcessor");
    @Override
    public <T> String format(T obj) {
        logger.info("===========fast-json format===========");
        return JSON.toJSONString(obj);
    }
}

4.寫一個配置類,核心用了條件註解

/**
 * 本配置類其實與spring-boot-starter的實現沒啥關係,主要是爲了解釋Conditionals
 * 深入瞭解:https://www.marcobehler.com/guides/spring-boot#_spring_boot_basics_conditionals
 */
@Configuration
public class FormatAutoConfiguration {

    /**
     * 下邊3個Conditional註解代表三種滿足條件下 bean注入
     *  關於springboot,Conditional是springboot中每個組件的基礎,判斷是否使用該組件
     */
    @Bean
    @ConditionalOnProperty(prefix = "json.format", name = "enabled", havingValue = "true") //使用屬性判斷是否注入bean
    public FormatProcessor fastjsonFormatProcessor(){
        return new FastjsonFormatProcessor();
    }

    @Primary //默認開啓jackson
    @Bean
    @ConditionalOnClass(name="com.google.gson.Gson") //在classpath下存在com.google.gson.Gson則注入bean
    public FormatProcessor gsonFormatProcessor(){
        return new GsonFormatProcessor();
    }

    @Bean
    @Conditional(JacksonCondition.class)  //使用condition判斷是否注入bean
    public FormatProcessor jacksonFormatProcessor(){
        return new JacksonFormatProcessor();
    }
}

5.序列化實現類,這個就是提供給用戶用來序列化用的

&nbsp&nbsp看名字 Template 大家也能知道,比如我們常用的 RedisTemplate、JdbcTemplate,構造函數的時候直接傳入具體的實現。

public class FormatTemplate {

    private FormatProcessor formatProcessor;

    public FormatTemplate(FormatProcessor formatProcessor) {
        this.formatProcessor = formatProcessor;
    }

    public <T> String doFormat(T obj){
        return formatProcessor.format(obj);
    }
}

6.最核心主類

@Import 用來導入配置類,就是將該配置類中的 Bean 注入到容器,@EnableConfigurationProperties 這是在將屬性類激活,注入到spring容器中,也可以用 @Bean 的方式,@Configuration 說明這是一個配置類。接下來將 FormatTemplate 注入到容器中,我們看到首先是去屬性類中去讀屬性,如果是 fastjson 就返回 fastjson 的實現,如果是 gson 就返回 gson 的實現,如果沒讀取到,就用前面設置的 @Primary 的默認實現。

@Import(FormatAutoConfiguration.class)
@EnableConfigurationProperties(FormatProperties.class)
@Configuration
public class JsonFormatConfiguration {

    @Bean
    public FormatTemplate formatTemplate(FormatProperties formatProperties,FormatProcessor formatProcessor){

        if ("fastjson".equals(formatProperties.getType())){
            return new FormatTemplate(new FastjsonFormatProcessor());
        }else if ("gson".equalsIgnoreCase(formatProperties.getType())){
            return new FormatTemplate(new GsonFormatProcessor());
        }else if ("jackson".equalsIgnoreCase(formatProperties.getType())){
            return new FormatTemplate(new JacksonFormatProcessor());
        }
        return new FormatTemplate(formatProcessor);
    }
}

7.spring.factories 設置

最後一步最關鍵的就是設置,在 resources 文件夾下創建 META-INF/spring.factories 文件,通過上面的知識,Spring Boot 在啓動的時候就是讀取該文件下的配置類,從而將 Bean 加載到容器中。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.github.autoconfigure.JsonFormatConfiguration

8.調用測試

將jsonformat-spring-boot-starter項目通過mvn clean install打包到本地maven倉庫

新建一個spring-boot項目,測試自定義starter,引入pom

       <dependency>
            <groupId>com.github</groupId>
            <artifactId>jsonformat-spring-boot-starter</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

properties配置,可以多切換幾次,如gson、fastjson

json.format.type=jackson

測試類

@SpringBootApplication
public class SpringBootWebDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootWebDemoApplication.class, args);
    }

}

@RestController
class TestController{

    private FormatTemplate formatTemplate;

    TestController(FormatTemplate formatTemplate) {
        this.formatTemplate = formatTemplate;
    }

    @GetMapping("/test")
    public String formatTest(){

        return formatTemplate.doFormat(User.builder().id("1").name("ll").build());
    }
}

@Data
@Builder
class User{
    private String id;
    private String name;
}

在瀏覽器訪問localhost:8080/test,返回

// 20200602223544
// http://localhost:8080/test

{
  "id": "1",
  "name": "ll"
}

同時web日誌中有打印你使用的json format 包

JacksonFormatProcessor                   : ===========jackson format===========

如果你需要代碼請點擊

參考

https://www.marcobehler.com/guides/spring-boot#_spring_boot_basics_conditionals

https://zhuanlan.zhihu.com/p/144241356

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章