自定义starter
首先、需要确定自定义一个starter需要些什么?
- 场景启动器:该项目没有任何的源代码,只是作为引用自定义starter的启动器,
既之后其他的项目需要使用自定义的starter可以直接通过该启动器导入依赖即可 - 自定义配置项目:需要实现的自定义配置类业务逻辑代码,在该项目中编写
简单理解:场景启动器就是一个统一管理自定义starter的仓库,自定义配置项目就是starter导入的依赖
自定starter的具体步骤
1. 创建一个空项目:
到这里之后,需要创建两个项目,一个是springboot项目(自定义配置项目),另一个是maven项目(场景启动器);这两个项目的创建就不必在演示,下面的两张图需要重复一次,因为要创建两个项目
创建项目完成之后:
项目如下:
2. 首先进入场景启动器中:既第一个项目(Maven项目)
3. 主要是操作pom.xml文件:引入自动配置包
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>atguigu-hello-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
<!--引入自定义配置的项目,既引入自定义的starter的依赖-->
<dependencies>
<dependency>
<groupId>com.springbootCustmer</groupId>
<artifactId>atguigu-hello-spring-boot-starter-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!--对应自动配置包中的pom.xml的如下代码:
<groupId>com.springbootCustmer</groupId>
<artifactId>atguigu-hello-spring-boot-starter-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
-->
</dependency>
</dependencies>
</project>
4. 操作自动配置的项目:既springboot项目(第二个)
5. 操作pom.xml文件:将不需要的配置删除,如:插件和单元测试,删除后的代码如下:
<?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.5.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springbootCustmer</groupId>
<artifactId>atguigu-hello-spring-boot-starter-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>atguigu-hello-spring-boot-starter-autoconfigure</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>
</dependencies>
</project>
6. 编写业务逻辑代码:
比如,我们需要一个这样的业务组件:有一个service,service中有一个方法sayHello,需要传递一个参数name(String),sayHello会返回一个欢迎语(前缀 + name + 后缀),前缀和后缀需要从配置文件application中获取。
7. 创建一个service:
HelloService中的代码如下:
package com.springbootcustmer.hello.service;
import com.springbootcustmer.hello.bean.HelloProperties;
import org.springframework.beans.factory.annotation.Autowired;
//自定义业务逻辑场景:自动配置starter场景
//注意:不要把该类放入容器中,通过配置类来放,因为在配置类种可以根据条件判断是否将该组件放入容器中
public class HelloService {
//前缀和后缀存储在HelloProperties类中(bean)
@Autowired //从容器中自动获取
HelloProperties helloProperties; //该类中的属性是通过配置文件来设置的
public String SayHello(String name){
return helloProperties.getPrefix() + ":" + name + "------>" + helloProperties.getSuffix();
}
}
8. 由Helloservice的代码可知,我们需要一格bean类,来存储前缀和后缀,且值是从application中获取的(自动绑定配置)
HelloProperties中代码如下:
package com.springbootcustmer.hello.bean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
//指定配置文件中的前缀,通过前缀获取指定的值,赋予下面的属性
@ConfigurationProperties("sheng.hello")
public class HelloProperties {
private String prefix;
private String suffix;
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
}
9. 我们还需要一个配置类,用来将我们的业务组件放入spring容器中,创建一个配置类
HelloServiceAutoConfiguration中的代码如下:
package com.springbootcustmer.hello.config;
import com.springbootcustmer.hello.bean.HelloProperties;
import com.springbootcustmer.hello.service.HelloService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//自动配置类
@Configuration
@EnableConfigurationProperties(HelloProperties.class) //开启某个类的自动配置绑定功能,既属性可以在配置文件中设置,且把该类放入容器中
public class HelloServiceAutoConfiguration {
//这个注解的意义是:在有在容器中没有HelloService这个组件我们才向容器中注入
//为了避免用户在自己的项目中创建了一个HelloService同名的组件而出现冲突
//遵循springboot的规则:用户定义大于约定
@ConditionalOnMissingBean(HelloService.class)
@Bean //将该方法作为组件放入容器中
public HelloService HelloService(){
HelloService helloService = new HelloService();
return helloService;
}
}
如此我们的业务逻辑组件代码编写完成,那么在其他项目中配置场景启动器导入该业务组件依赖,就会自动配置呢?
答案是否定的,不能,为什么,因为在springboot的自动配置原理中,有这么一个文件spring.factories,这个文件中指定了在项目启动时需要加载哪些组件
10. 在静态资源路径(resource)下创建spring.factories文件:
11. 完成以上操作后,我们需要把自动配置项目打包并放入本地仓库中,因为我们导入依赖,导入的都是包:
注意:自动配置项目和场景启动器都需要打包,如果以后更改了业务逻辑,只需要重新打包自动配置项目且放入本地仓库中即可
12. 进行如上操作之后,自定义starter便完成了
测试自定义starter
1. 创建一个springboot项目
2. 在pom.xml中导入自定义starter的依赖
代码如下:
<dependency>
<groupId>org.example</groupId>
<artifactId>atguigu-hello-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
3. 查看是否导入了对应的依赖(包)
4. 编写一个controller测试HelloService组件是否可用:
5. 在application中配置前缀和后缀:
6. 在浏览器中访问接口:
前缀和后缀与我们配置的完全一致,由此可得自定义starter成功。
从application中自动绑定的属性值中文乱码
解决方法:
重新创建application文件即可