黑魔法!徒手撸啊撸Spring Boot Starter启动器

我们在项目中经常会引用一些spring-boot-starter-xxx之类的依赖,然后就在配置文件中进行配置 ,例如:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.zaxxer.hikari.HikariDataSource
    url: jdbc:mysql://10.82.232.149:3306/rc?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&zeroDateTimeBehavior=round&serverTimezone=UTC&allowMultiQueries=true
    username: root
    password: sf.qz
    hikari:
      pool-name: Hikari-Pool
      idle-timeout: 30000
      maximum-pool-size: 50
      minimum-idle: 10
    servlet:
      multipart:
        max-file-size: -1
        max-request-size: -1
    http:
      multipart:
        maxRequestSize: -1
        maxFileSize: -1

那么我们能否自定义个starter工程呢? 答案是:yes

一、创建自定义的 jsonformatter-spring-boot-starter工程

通常一些第三方的starter依赖都是按照xxx-spring-boot-starter 的格式去命名的,所以我们按照这种方式创建一个jsonformatter-spring-boot-starter 工程,该工程主要就是利用fastjson 和 gson 进行对象和json字符串之间的互相转换。

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>


    <groupId>com.dzx.springboot</groupId>
    <artifactId>jsonformatter-spring-boot-starter</artifactId>
    <version>1.0.0</version>
    <name>jsonformatter-spring-boot-starter</name>
    <description>json转换starter</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.3.4.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure-processor</artifactId>
            <version>2.3.4.RELEASE</version>
        </dependency>
        
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.73</version>
        </dependency>

        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.6</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

 二、编写json转换业务相关类

package com.dzx.springboot.jsonformatterspringbootstarter.config;

/**
 * @author 80004819
 * @ClassName:
 * @Description:
 * @date 2020年09月27日 11:17:07
 */
public interface FormatProcessor {
    //定义一个格式化的方法
    String objectToJson(Object obj);

    Object jsonToObject(String str,Class aClass);
}
package com.dzx.springboot.jsonformatterspringbootstarter.config;

import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import org.springframework.stereotype.Component;
import sun.swing.plaf.synth.SynthIcon;

/**
 * @author 80004819
 * @ClassName:
 * @Description:
 * @date 2020年09月27日 10:30:38
 */
@Component("jsonFormatterTemplate")
public class JsonFormatterTemplate implements  FormatProcessor{


    /**
     * 格式化器
     */
    private Object formatter;


    public Object getFormatter() {
        return formatter;
    }

    public void setFormatter(Object formatter) {
        this.formatter = formatter;
    }


    /**
     * 将对象转成字符串
     *
     * @param o
     * @return
     */
    public String objectToJson(Object o) {
        if (this.formatter instanceof JSON) {
            System.out.println("使用fastjson转换数据");
            return JSON.toJSONString(o);
        }
        System.out.println("使用gson转换数据");
        return new Gson().toJson(o);
    }

    /**
     * 将字符串转成对象
     * @param str
     * @return
     */
    public Object jsonToObject(String str, Class aClass) {
        if (this.formatter instanceof JSON) {
            System.out.println("使用fastjson转换数据");
            return JSON.parse(str);
        }
        System.out.println("使用gson转换数据");
        return new Gson().fromJson(str, aClass);
    }
}

三、编写property类,用来读取配置文件中的配置项

package com.dzx.springboot.jsonformatterspringbootstarter.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/**
 * @author 80004819
 * @ClassName:
 * @Description:
 * @date 2020年09月27日 10:23:08
 */

@ConfigurationProperties(prefix = "json.formatter")
@Configuration
public class JsonFormatterProperty {

    private String type;


    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

 四、编写Configuration 和 autoConfiguration类

package com.dzx.springboot.jsonformatterspringbootstarter.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.JdbcProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

/**
 * @author 80004819
 * @ClassName:
 * @Description:
 * @date 2020年09月27日 10:34:39
 */

@Configuration
//启用对添加了@ConfigurationProperties注解类的支持,使之能够以bean的形式进行注入
@EnableConfigurationProperties({JsonFormatterProperty.class})
public class JsonFormatterConfiguration {


    @Bean("jsonFormatterTemplate")
    @Primary
    public JsonFormatterTemplate jsonFormatterTemplate(JsonFormatterProperty jsonFormatterProperty) throws Exception {
        JsonFormatterTemplate jsonFormatterTemplate = new JsonFormatterTemplate();
        Object o = Class.forName(jsonFormatterProperty.getType()).newInstance();
        jsonFormatterTemplate.setFormatter(o);
        return jsonFormatterTemplate;
    }
}
package com.dzx.springboot.jsonformatterspringbootstarter.config;

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;


/**
 * @author 80004819
 * @ClassName:
 * @Description:
 * @date 2020年09月27日 10:33:15
 */
@Configuration
@ConditionalOnClass({JsonFormatterTemplate.class})
//以组件的形式导入JsonFormatterConfiguration
@Import({JsonFormatterConfiguration.class})
//如果application.properties中json.formatter.enabled=true 则启用自动配置
@ConditionalOnProperty(prefix = "json.formatter", value = "enabled", matchIfMissing = true)
public class JsonFormatterAutoConfiguration {


}

五、配置spring.factories文件

做完以上步骤之后,我们的自动化配置类就算是完成了,接下来还需要一个 spring.factories 文件,那么这个文件是干嘛的呢?大家知道我们的 Spring Boot 项目的启动类都有一个 @SpringBootApplication 注解,这个注解的定义如下:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM,
                classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}

大家看到这是一个组合注解,其中的一个组合项就是 @EnableAutoConfiguration ,这个注解是干嘛的呢?

@EnableAutoConfiguration 表示启用 Spring 应用程序上下文的自动配置,该注解会自动导入一个名为 AutoConfigurationImportSelector 的类,而这个类会去读取一个名为 spring.factories 的文件, spring.factories 中则定义需要加载的自动化配置类,我们打开任意一个框架的 Starter ,都能看到它有一个 spring.factories 文件,例如 MyBatis 的 Starter 如下:

那么我们自定义 Starter 当然也需要这样一个文件,我们首先在 Maven 项目的 resources 目录下创建一个名为 META-INF 的文件夹,然后在文件夹中创建一个名为 spring.factories 的文件,文件内容如下: 

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.dzx.springboot.jsonformatterspringbootstarter.config.JsonFormatterAutoConfiguration

在这里指定我们的自动化配置类的路径即可。

如此之后我们的自动化配置类就算完成了。

六、本地安装

如果在公司里,大伙可能需要将刚刚写好的自动化配置类打包,然后上传到 Maven 私服上,供其他同事下载使用,我这里就简单一些,我就不上传私服了,我将这个自动化配置类安装到本地仓库,然后在其他项目中使用即可。安装方式很简单,在 IntelliJ IDEA 中,点击右边的 Maven Project ,然后选择 Lifecycle 中的 install ,双击即可,如下:

双击完成后,这个 Starter 就安装到我们本地仓库了,当然小伙伴也可以使用 Maven 命令去安装。 

七、使用 Starter

接下来,我们来新建一个普通的 Spring Boot 工程,这个 Spring Boot 创建成功之后,加入我们自定义 Starter 的依赖,如下:

  <dependency>
        <groupId>com.dzx.springboot</groupId>
        <artifactId>jsonformatter-spring-boot-starter</artifactId>
        <version>1.0.0</version>
        </dependency>

 此时我们引入了上面自定义的 Starter ,也即我们项目中现在有一个默认的 jsonFormatterTemplate 实例可以使用,而且关于这个实例的数据,我们还可以在 application.properties 中进行配置,如下:

json:
  formatter:
    enabled: true
    type: com.alibaba.fastjson.JSONObject

配置完成后,我们可以编写一个测试controller

package com.sf.gis.boot.rcboot.controller;

import com.dzx.springboot.jsonformatterspringbootstarter.config.JsonFormatterTemplate;
import com.sf.gis.boot.rcboot.shiro.entity.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author 80004819
 * @ClassName:
 * @Description:
 * @date 2020年09月27日 11:13:43
 */
@RestController
@RequestMapping("/json")
public class JsonController {

    @Autowired
    private JsonFormatterTemplate jsonFormatterTemplate;

    @GetMapping("/trans")
    public void trans() {
        String dzx = jsonFormatterTemplate.objectToJson(new SysUser().setName("dzx"));
        System.out.println(dzx);
        Object o = jsonFormatterTemplate.jsonToObject(dzx,SysUser.class);
        System.out.println(((SysUser) o).getName());
    }

}

  使用 postman或者swagger请求 http://localhost:8085/json/trans,看到控制台打印如下:

如果我们需要使用gson呢,可以直接修改配置文件如下:

json:
  formatter:
    enabled: true
    type: com.google.gson.Gson

再次请求 http://localhost:8085/json/trans,看到控制台打印如下:

至此结束~~

猜你喜欢

转载自blog.csdn.net/qq_31905135/article/details/108825098