dark magic! Use your bare hands to play Spring Boot Starter

We often quote some dependencies such as spring-boot-starter-xxx in our projects, and then configure them in the configuration file, for example:

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

So can we customize a starter project? The answer is: yes

1. Create a custom jsonformatter-spring-boot-starter project

Usually some third-party starter dependencies are named according to the format of xxx-spring-boot-starter, so we create a jsonformatter-spring-boot-starter project in this way, which mainly uses fastjson and gson for objects And json string conversion between each other.

<?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>

 Two, write json conversion business related classes

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);
    }
}

Three, write the property class, used to read the configuration items in the configuration file

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;
    }
}

 Fourth, write Configuration and autoConfiguration classes

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 {


}

Five, configure the spring.factories file

After completing the above steps, even if our automated configuration class is complete, we still need a spring.factories file, so what does this file do? Everyone knows that the startup class of our Spring Boot project has an @SpringBootApplication annotation, which is defined as follows:

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

You see that this is a combined annotation, and one of the combined items is @EnableAutoConfiguration. What does this annotation do?

@EnableAutoConfiguration means to enable automatic configuration of the Spring application context. This annotation will automatically import a class named AutoConfigurationImportSelector, and this class will read a file named spring.factories, and spring.factories defines the automation that needs to be loaded Configuration class, when we open the Starter of any framework, we can see that it has a spring.factories file. For example, the Starter of MyBatis is as follows:

So of course, we need such a file to customize the Starter. We first create a folder named META-INF under the resources directory of the Maven project, and then create a file named spring.factories in the folder. The content of the file is as follows : 

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

Just specify the path of our automated configuration class here.

After that, our automated configuration class is complete.

Six, local installation

If you are in a company, everyone may need to package the automation configuration class that you just wrote, and upload it to the Maven private server for other colleagues to download and use. I will make it simpler here. I will not upload the private server. I will use this automation configuration class. Install it to the local warehouse, and then use it in other projects. The installation method is very simple. In IntelliJ IDEA, click Maven Project on the right, then select install in Lifecycle, and double-click it, as follows:

After double-clicking, the Starter will be installed in our local warehouse. Of course, friends can also use the Maven command to install it. 

Seven, use Starter

Next, let's create a new ordinary Spring Boot project. After this Spring Boot is successfully created, add the dependency of our custom Starter, as follows:

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

 At this time, we introduced the custom Starter above, that is, there is now a default jsonFormatterTemplate instance available in our project, and we can also configure the data of this instance in application.properties, as follows:

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

After the configuration is complete, we can write a test 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());
    }

}

  Use postman or swagger to request http://localhost:8085/json/trans, and see the console print as follows:

If we need to use gson, we can directly modify the configuration file as follows:

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

Request http://localhost:8085/json/trans again, and see the console print as follows:

This is the end~~

Guess you like

Origin blog.csdn.net/qq_31905135/article/details/108825098