在springboot中,使用的最多的就是starter。starter可以理解为一个可拔插式的插件,例如,你想使用jdbc插件,那么可以使用spring-boot-starter-jdbc;我们也可以根据自己项目的需要,定义自己的starter:
1. 创建一个maven工程
创建一个maven工程,
注意artifactId的命名规则,Spring官方Starter通常命名为spring-boot-starter-{name}如 spring-boot-starter-web, Spring官方建议非官方Starter命名应遵循{name}-spring-boot-starter的格式, 如mybatis-spring-boot-starter。这里创建的项目的artifactId为format-spring-boot-starter
2. 引入必要的依赖
注意:这里的packaging为jar,starter需要使用到Spring boot的自动配置功能,所以需要引入自动配置相关的依赖。fastjson这个依赖是因为我们的demo中要用到,所以需要依赖进来。
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.1.6.RELEASE</version>
<optional>true</optional>
</dependency>
</dependencies>
3. XxxProperties
在使用Spring官方的Starter时通常可以在application.properties中来配置参数覆盖掉默认的值,例如在使用redis时一般就会有对应的RedisProperties,这里我们也定义一个我们自己的properties。
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.Map;
@ConfigurationProperties(prefix = HelloProperties.HELLO_FORMAT_PREFIX)
public class HelloProperties {
public static final String HELLO_FORMAT_PREFIX = "hello.format";
private Map<String, Object> info;
public Map<String, Object> getInfo() {
return info;
}
public void setInfo(Map<String, Object> info) {
this.info = info;
}
}
4. 核心服务类
每个starter都有自己的功能,例如在spring-boot-starter-jdbc中最重要的类时JdbcTemplate,每个starter中的核心业务类明白都不同,也没什么规律(像spring-boot-starter-data-xxx的命名是比较有规律的),我们这个starter提供一个format的简单功能,主要就是把传过来的参数转换成字符串,我们这里提供两种格式的返回值,一种是String类型,一种是Json类型。
先定义一个FormatProcess接口,里面只提供一个format方法:
public interface FormatProcess {
// 定义一个格式化的方法
<T> String format(T object);
}
然后提供两个实现类,StringFormatProcessBean和JsonFormatProcessBean:
StringFormatProcessBean:
public class StringFormatProcessBean implements FormatProcess {
@Override
public <T> String format(T object) {
return "StringFormatProcess : " + object.toString();
}
}
JsonFormatProcessBean:
public class JsonFormatProcessBean implements FormatProcess {
public <T> String format(T object) {
return "JsonFormatProcess : " + JSON.toJSONString(object);
}
}
然后我们还提供一个template给客户方调用,类似springJdbcTemplate,我们这里叫做HelloFormatTemplate:
public class HelloFormatTemplate {
private FormatProcess formatProcess;
private HelloProperties helloProperties;
public HelloFormatTemplate(HelloProperties helloProperties, FormatProcess formatProcess) {
this.helloProperties = helloProperties;
this.formatProcess = formatProcess;
}
public <T> String doFormat(T object) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Execute format : ").append("</br>");
stringBuilder.append("HelloProperties: ").append(formatProcess.format(helloProperties.getInfo())).append("</br>");
stringBuilder.append("Object format result : ").append(formatProcess.format(object)).append("</br>");
return stringBuilder.toString();
}
}
HelloFormatTemplate中定义一个doFormat方法,这个方法的作用是输出执行过format之后的参数,并且把用户自定义的properties打印出来。
5. 自动配置类
因为我们定义了两种format的实现类,在我们的starter中要定义这两个实现类初始化,如果调用方没有依赖Json,那就使用String的format。否则使用JsonFormat:
@Configuration
public class FormatAutoConfiguration {
@ConditionalOnMissingClass("com.alibaba.fastjson.JSON")
@Bean
@Primary
public FormatProcess stringFormat() {
return new StringFormatProcessBean();
}
@Bean
@ConditionalOnClass(name = "com.alibaba.fastjson.JSON")
public FormatProcess jsonFormat() {
return new JsonFormatProcessBean();
}
}
一般每个starter都至少会有一个自动配置类,一般命名规则使用XxxAutoConfiguration, 例如RedisAutoConfiguration,我们这里叫HelloAutoConfiguration
@Import(FormatAutoConfiguration.class)
@EnableConfigurationProperties(HelloProperties.class)
@Configuration
public class HelloAutoConfiguration {
@Bean
public HelloFormatTemplate helloFormatTemplate(HelloProperties helloProperties, FormatProcess formatProcess) {
return new HelloFormatTemplate(helloProperties, formatProcess);
}
}
6.src/main/resources/META-INF/spring.factories
为了我们的starter能够被spring自动加载,需要添加spring.factories文件
注意:META-INF是自己手动创建的目录,spring.factories也是手动创建的文件,在该文件中配置自己的自动配置类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.yrk.springboot.autoconfiguration.HelloAutoConfiguration
这样一个starter就完成了。
7. 打包mvn clean install
8. 创建一个Spring Boot工程并引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.yrk.springboot</groupId>
<artifactId>format-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
</dependencies>
9.配置application.properties
hello.format.info.country=CN
hello.format.info..city=HZ
10.测试类
@RestController
public class FormatController {
@Autowired
private HelloFormatTemplate helloFormatTemplate;
@GetMapping("/format")
public String format() {
User user = new User();
user.setAge(16);
user.setName("test");
return helloFormatTemplate.doFormat(user);
}
}
启动后在浏览器中访问这个url,会显示一下信息: