你还不会手写SpringBoot启动器吗

Starter是什么 ?

Spring Boot 对比 Spring MVC 最大的优点就是使用简单,约定大于配置。不用 Spring MVC 的时候,时不时被 xml 配置文件搞的晕头转向,冷不防还因为 xml 配置上的一点疏忽,导致整个项目莫名其妙的不可用,顿感生无可恋。这要归功于Spring Boot 的各种各样的 starters,有官方提供以及第三方开源出来的。这些依赖模块都遵循着约定成俗的默认配置,并允许我们根据自身情况调整这些配置。基本上你打算用的功能都可以找到,如果没有找到,那就请再找一找。SpringBoot 会自动扫描需要加载的信息并启动相应的默认配置。

Starter 提供了以下功能:

  • 整合了模块需要的所有依赖,统一集合到 Starter 中。
  • 提供了默认配置,并允许我们调整这些默认配置。
  • 提供了自动配置类对模块内的 Bean 进行自动装配,注入 Spring 容器中。

Starter 命名规则

Spring 官方定义的 Starter 通常命名遵循的格式为 spring-boot-starter-{name},例如 spring-boot-starter-data-mongodb。Spring 官方建议,非官方 Starter 命名应遵循 {name}-spring-boot-starter 的格式,例如,myjson-spring-boot-starter。

Starter可以用来解决什么问题?

日常开发中有一些独立于业务系统之外的配置模块,它是可以在不同项目中进行复用的。如果在每个项目中都编写重复的模块代码,除了浪费时间和人力耦合性还高。将这些可独立于业务代码之外的功能配置模块封装成一个 Starter,在需要用到此功能模块的项目中,只需要在其 pom.xml 文件中引用依赖即可。

手写SpringBoot启动器的主要步骤

  1. 定义业务接口、需要的实体类等业务对象
  2. 定义配置属性类、
  3. 定义自动装配类、
  4. Resources目录下新建META-INF/spring.factories,加入自定义starter的配置项
  1. idea——new  project——spring initializr——填写group、artifact名称,选择java的jdk版本——next ——next——finish

pom文件依赖

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

    <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>2.4.4</version>

        <relativePath/> <!-- lookup parent from repository -->

    </parent>

    <groupId>com.example</groupId>

    <artifactId>my-starter</artifactId>

    <version>0.0.1-SNAPSHOT</version>

    <name>my-starter</name>

    <description>Demo project for Spring Boot</description>

    <properties>

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

    </properties>

    <dependencies>

        <dependency>

            <groupId>com.example</groupId>

            <artifactId>myjson-spring-boot-starter-autoconfigurer</artifactId>

            <version>0.0.1-SNAPSHOT</version>

        </dependency>

    </dependencies>

 

    <build>

        <plugins>

            <plugin>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-maven-plugin</artifactId>

            </plugin>

        </plugins>

    </build>

 

</project>

 

  1. 在当前工程创建module——name为myjson,流程同上

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

    <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>2.4.4</version>

        <relativePath/> <!-- lookup parent from repository -->

    </parent>

    <groupId>com.example</groupId>

    <artifactId>myjson-spring-boot-starter-autoconfigurer</artifactId>

    <version>0.0.1-SNAPSHOT</version>

    <name>myjson-spring-boot-starter-autoconfigurer</name>

    <description>Demo project for Spring Boot</description>

    <properties>

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

    </properties>

    <dependencies>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-configuration-processor</artifactId>

            <version>2.3.8.RELEASE</version>

            <optional>true</optional>

        </dependency>

        <dependency>

            <groupId>com.alibaba</groupId>

            <artifactId>fastjson</artifactId>

            <version>1.2.73</version>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-autoconfigure</artifactId>

            <version>2.3.8.RELEASE</version>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-test</artifactId>

            <scope>test</scope>

        </dependency>

    </dependencies>

 

    <build>

        <plugins>

            <plugin>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-maven-plugin</artifactId>

                <configuration>

                    <mainClass>com.example.myjson.MyjsonApplication</mainClass>

                    <skip>true</skip>

                </configuration>

            </plugin>

        </plugins>

    </build>

 

</project>

加红色的三个依赖,fastjson是我们需要的第三方依赖,其他的spring-boot-configuration-processor 依赖是可选的,加入此依赖主要是打包时,自动生成配置元信息文件 META-INF/spring-configuration-metadata.json,并放入到 jar 中。绿色的artifact是我们自定义starter的名称,蓝色的插件依赖是我们

  1. 手写starter
  1. 定义我们的service业务类:主要是对传入的对象转换为json字符串,同时在其首位做额外的拼接处理

public class MyJsonService {

    private String prefixName;

    private String suffixName;

 

    public String getPrefixName() {

        return prefixName;

    }

 

    public void setPrefixName(String prefixName) {

        this.prefixName = prefixName;

    }

 

    public String getSuffixName() {

        return suffixName;

    }

 

    public void setSuffixName(String suffixName) {

        this.suffixName = suffixName;

    }

 

    public String objectToMyJson(Object obj) {

        return prefixName + JSON.toJSONString(obj) + suffixName;

    }

}

 

  1. 定义控制的实体类对象

public class Person {

    private String name;

    private int age;

    private String address;

    public Person(String name, int age, String address) {

        super();

        this.name = name;

        this.age = age;

        this.address = address;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public int getAge() {

        return age;

    }

 

    public void setAge(int age) {

        this.age = age;

    }

 

    public String getAddress() {

        return address;

    }

 

    public void setAddress(String address) {

        this.address = address;

    }

}

 

  1. 定义我们的属性配置类(也即yml配置文件中配置的属性)

/**

 * @author:cp

 * @time:2021-4-12

 * @Description: 配置类(类名一般为模块名+Properties) cp.json为Starter使用者通过yml配置文件动态修改属性值的变量名前缀

 */

@ConfigurationProperties(prefix = "cp.json")

public class MyJsonProperties {

    // Starter使用者没在配置文件中配置prefixName属性的值时的默认值

    public static final String DEFAULT_PREFIX_NAME = "@";

 

    // Starter使用者没在配置文件中配置suffixName属性的值时的默认值

    public static final String DEFAULT_SUFFIX_NAME = "#";

    private String prefixName = DEFAULT_PREFIX_NAME;

    private String suffixName = DEFAULT_SUFFIX_NAME;

 

    public String getPrefixName() {

        return prefixName;

    }

 

    public void setPrefixName(String prefixName) {

        this.prefixName = prefixName;

    }

 

    public String getSuffixName() {

        return suffixName;

    }

 

    public void setSuffixName(String suffixName) {

        this.suffixName = suffixName;

    }

}

 

  1. 定义自动装配类,让spring装配我们的service业务类,同时调用我们的属性配置类,让业务service类获取到属性配置类的值并进行处理

package com.example.myjson.config;

 

import com.example.myjson.service.MyJsonService;

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

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

import org.springframework.boot.context.properties.EnableConfigurationProperties;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

 

/**

 * @author:cp

 * @time:2021-4-12

 * @Description: 自动装配类

 */

@Configuration

@ConditionalOnClass(MyJsonService.class) // 表示只有指定的classclasspath上时才能被注册

@EnableConfigurationProperties(MyJsonProperties.class)

// 激活被@ConfigurationProperties注解修饰的类

public class MyJsonConfiguration {

    private MyJsonProperties myJsonProperties;

 

    // 自动注入配置类

    public MyJsonConfiguration(MyJsonProperties myJsonProperties) {

        this.myJsonProperties = myJsonProperties;

    }

 

    // 创建MyJsonService对象,注入到Spring容器中

    @Bean

    @ConditionalOnMissingBean(MyJsonService.class)  // 当容器没有此bean时,才注册

    public MyJsonService myJsonService() {

        MyJsonService myJsonService = new MyJsonService();

        myJsonService.setPrefixName(myJsonProperties.getPrefixName());

        myJsonService.setSuffixName(myJsonProperties.getSuffixName());

        return myJsonService;

    }

}

 

  1. 在我们的启动类模块的resources文件下创建META-INF/spring.factories 文件,增加如下内容,将自动装配的类配置上

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\

com.example.myjson.config.MyJsonConfiguration

 

  1. 上述工作完成后,我们可以使用mvn install命令在本地仓库生成我们手写的starter的jar,可以提供给他其他工程依赖引用。也可以快捷的使用idea提供的快捷打包
  2. 新建一个工程,名称为kk,流程同(1)中,在pom文件中引入我们的starter依赖,

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

    <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>2.4.4</version>

        <relativePath/> <!-- lookup parent from repository -->

    </parent>

    <groupId>com.example</groupId>

    <artifactId>kk</artifactId>

    <version>0.0.1-SNAPSHOT</version>

    <name>kk</name>

    <description>Demo project for Spring Boot</description>

    <properties>

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

    </properties>

    <dependencies>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

        <dependency>

            <groupId>com.example</groupId>

            <artifactId>myjson-spring-boot-starter-autoconfigurer</artifactId>

            <version>0.0.1-SNAPSHOT</version>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-test</artifactId>

            <scope>test</scope>

        </dependency>

    </dependencies>

 

    <build>

        <plugins>

            <plugin>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-maven-plugin</artifactId>

            </plugin>

        </plugins>

    </build>

 

</project>

 

  1. 更新maven依赖后,可以看我们的自定义starter已经被引入进来,在kk工程的resources文件下将application.properties文件改为application.yml并进行如下配置

cp:

  json:

    prefix-name: hello

    suffix-name: world

 

  1. 在kkApplication下新建controller

@RestController

@RequestMapping("demo")

public class DemoController {

    @Autowired

    private MyJsonService myJsonService;

 

    @GetMapping()

    public String test() {

        Person p = new Person(“千与千寻” , 18, "拉斯维加斯");

        // 调用服务方法

        return myJsonService.objectToMyJson(p);

    }

}

引入我们自定义启动器中的业务service类,启动springboot工程,访问http://localhost:8080/demo,验证我们的service类即可。

中间问题点:在打包自定义启动器类jar包本地仓库时,没有添加构建插件,导致生成包多了一个BOOT-INF的文件,无法被其他工程引用导入自定义service类:添加如下构建插件后问题解决:

<build>

        <plugins>

            <plugin>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-maven-plugin</artifactId>

                <configuration>

                    <mainClass>com.example.myjson.MyjsonApplication</mainClass>

                    <skip>true</skip>

                </configuration>

            </plugin>

        </plugins>

    </build>

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值