自定義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.序列化實現類,這個就是提供給用戶用來序列化用的
  看名字 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