自定义一个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

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