spring boot starter 自定义
1. Starter是什么
starter 是spring-boot的核心功能,官方提供了很多starter包, 简化了很多工作。
Spring-boot 引入starter的代码片段,如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2. 如何使用Starter
Starter在spring-boot中的引用过程可以简单的概括为以下步骤:
- Pom.xml或build.gradle中引入;
- application.properties或application.yml中配置;
- 功能模版注入;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
spring.redis.host=
spring.redis.lettuce.pool.max-active=
部分功能开启需要通过@Enable注解
package com.arcsin.payconfigserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableEurekaClient
@SpringBootApplication
@EnableConfigServer
public class PayConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(PayConfigServerApplication.class, args);
}
}
3. 如何实现一个Starter
根据starter步骤我们层层分解,简单可以猜想有以下几个步骤:
- 创建Stater项目;(这个就是在Pom.xml或build.gradle中引入Starter前一步)
- 定义Starter需要的配置(Properties)类(对应的就是application.properties或application.yml中配置)
- 编写自动配置类,自动配置类就是获取配置,根据配置来装配Bean;(例如RedisTemplate类)
- 编写spring.factories 文件加载自动配置类,Spring启动的时候会扫描spring.factories文件,指定文件的配置;
- 编写配置提示文件spring-configuration-metadata.json,在添加配置的时候,我们想要知道具体的配置项是什么作用,可以通过编写提示文件来提示;
接下来笔者就以自己封装的一个selenium-spring-boot-starter为例,实现一个starter的编写过程。
首先, 创建一个selenium-spring-boot-starter,项目命名遵循:
官方项目以spring-boot-starter-xxx命名,非官方项目以xxx-spring-boot-starter命名。
引入基本包:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
</dependencies>
其次,定义配置类Properties, SeleniumProperties:
package com.arcsin;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties("selenium")
public class SeleniumProperties {
private String driver="chrome";
private boolean headless =false;
}
我们希望在properties配置中是以selenium开头。
selenium:
driver: chrome
headless: false
接着, 编写实际业务需要的Template
package com.arcsin;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class SeleniumTemplate implements SeleniumOperations{
@Autowired
private SeleniumProperties seleniumProperties;
private static WebDriver driver = null;
public SeleniumTemplate(){
}
public SeleniumTemplate(SeleniumProperties seleniumProperties){
ChromeOptions options = new ChromeOptions();
options.setHeadless(false);
options.addEncodedExtensions();
options.addArguments("--user-agent=Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1");
driver = new ChromeDriver(options);
}
@Override
public void go(String url){
if (null== driver){
ChromeOptions options = new ChromeOptions();
options.setHeadless(false);
options.addEncodedExtensions();
options.addArguments("--user-agent=Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1");
driver = new ChromeDriver(options);
}
driver.get(url);
}
@Override
public void close() {
if (null==driver){
return;
}
driver.close();
}
}
然后,自动配置类,自动配置类就是获取配置,根据配置来装配Bean;
package com.arcsin;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@EnableConfigurationProperties(SeleniumProperties.class)
@ConditionalOnWebApplication
@Import(SeleniumTemplate.class)
public class SeleniumAutoConfigure {
}
可选步骤,有些功能开启通过注解 @Enable,需编写如下类:
package com.arcsin;
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(SeleniumAutoConfigure.class)
public @interface EnableSelenium {
}
编写spring.factories 文件加载自动配置类,Spring启动的时候会扫描spring.factories文件,指定文件的配置:
Spring.factories中添加:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.arcsin.SeleniumAutoConfigure
删除@SpringbootApplication启动类;
删除est文件;
删除;
最后,在其他项目中引入
<dependency>
<groupId>com.arcsin</groupId>
<artifactId>selenium-spring-boot-starter</artifactId>
<version>1.0</version>
</dependency>
在test中编写测试类:
package com.example.teststarter;
import com.arcsin.EnableSelenium;
import com.arcsin.SeleniumTemplate;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
@EnableSelenium
public class TestStarterApplicationTests{
@Autowired
private SeleniumTemplate seleniumTemplate;
@Test
public void test() throws InterruptedException {
seleniumTemplate.go("http://www.baidu.com");
}
}
run一下,