目标
本文主要介绍springboot3.0是如何创建一个可以进行自动配置的jar包的
自动配置的定义是,一个jar包里面定义了一些spring的bean,当导入这个jar包的时候会自动将这些bean导入进去
方法
创建 AutoConfiguration.imports 文件
创建目录 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
在该文件里面写入自动配置类的全限域名,例如:cn.hellozjf.game.pcr.common.CommonAutoConfiguration
创建自动配置类
代码内容如下:
package cn.hellozjf.game.pcr.common;
import cn.hellozjf.game.pcr.common.config.WebDriverAutoConfiguration;
import cn.hellozjf.game.pcr.common.config.WebDriverConfig;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Import;
@Import({WebDriverAutoConfiguration.class})
@EnableConfigurationProperties({WebDriverConfig.class})
public class CommonAutoConfiguration {
}
其中,WebDriverAutoConfiguration 定义了自动配置时会导入的 bean,WebDriverConfig 定义了自动配置时需要读取的配置文件
WebDriverAutoConfiguration
这个类里面定义了各种需要导入的 bean
package cn.hellozjf.game.pcr.common.config;
import cn.hellozjf.game.pcr.common.service.IWebDriverService;
import cn.hellozjf.game.pcr.common.service.WebDriverServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
@AllArgsConstructor
public class WebDriverAutoConfiguration {
private final WebDriverConfig webDriverConfig;
@Bean
@ConditionalOnMissingBean(IWebDriverService.class)
public IWebDriverService webDriverService() {
return new WebDriverServiceImpl(webDriverConfig);
}
}
如上面的代码所示,它会在构造的时候将 WebDriverConfig 配置信息全部导入进来,如果在初始化的时候发现没有定义 IWebDriverService 这个 bean,那么就会实例化这个 bean
WebDriverConfig
它的代码如下所示
package cn.hellozjf.game.pcr.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "webdriver")
public class WebDriverConfig {
private Boolean headless;
private String proxy;
private String driverKey;
private String driverValue;
}
它对应配置文件中的内容如下
IWebDriverService
这是 bean 的定义基类,代码如下
package cn.hellozjf.game.pcr.common.service;
import org.openqa.selenium.WebElement;
import org.springframework.beans.factory.InitializingBean;
import java.util.List;
/**
* web浏览器操作服务
*/
public interface IWebDriverService extends InitializingBean {
/**
* 初始化
*/
void init();
/**
* 退出浏览器
*/
void quit();
/**
* 执行 JS 脚本
* @param script
*/
void executeScript(String script);
/**
* 通过执行 JS 脚本,获取网页元素
* @param script
* @return
*/
WebElement findByExecuteScript(String script);
/**
* 从网页元素中,通过 JS 脚本获取该元素里面的字符串数据
* @param webElement
* @param script
* @return
*/
String getStrByExecuteScript(WebElement webElement, String script);
/**
* 根据 CSS 选择器查找网页元素
* @param selector
* @return
*/
List<WebElement> findByCssSelector(String selector);
/**
* 在某个网页元素下,根据 CSS 选择器查找网页元素
* @param webElement
* @param selector
* @return
*/
List<WebElement> findByCssSelector(WebElement webElement, String selector);
/**
* 根据 ID 选择器查找网页元素
* @param selector
* @return
*/
List<WebElement> findByIdSelector(String selector);
/**
* 在某个网页元素下,根据 ID 选择器查找网页元素
* @param webElement
* @param selector
* @return
*/
List<WebElement> findByIdSelector(WebElement webElement, String selector);
/**
* 根据标签查找网页元素
* @param tag
* @return
*/
List<WebElement> findByTag(String tag);
/**
* 打开网页
* @param url
*/
void openUrl(String url);
/**
* 判断打开页面操作是否完成
* @return
*/
boolean isOpenComplete();
/**
* 阻塞进程,直到页面元素出现,或者超过timeout秒
* @param element
* @param timeout
*/
void waitUntilElementExist(String element, int timeout);
/**
* 不需要实现 afterPropertiesSet(),我也不知道这有啥用,照着抄就对了
* @throws Exception
*/
@Override
default void afterPropertiesSet() throws Exception {
}
}
WebDriverServiceImpl
这是 IWebDriverService 的实现类,内容如下
package cn.hellozjf.game.pcr.common.service;
import cn.hellozjf.game.pcr.common.config.WebDriverConfig;
import cn.hellozjf.game.pcr.common.util.OSUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.util.StringUtils;
import java.time.Duration;
import java.util.List;
@Slf4j
@RequiredArgsConstructor
public class WebDriverServiceImpl implements IWebDriverService {
private final WebDriverConfig webDriverConfig;
private boolean bInit = false;
private WebDriver driver;
private JavascriptExecutor js;
@Override
public void init() {
if (bInit) {
log.error("WebDriverService已经初始化");
return;
}
// 设置 ChromeDriver 的路径
System.setProperty(webDriverConfig.getDriverKey(), webDriverConfig.getDriverValue());
ChromeOptions options = new ChromeOptions();
// 获取 driver 和 js 变量
if (StringUtils.hasLength(webDriverConfig.getProxy())) {
// 说明需要走代理
options.addArguments("--proxy-server=" + webDriverConfig.getProxy());
}
// 设置无界面
if (webDriverConfig.getHeadless()) {
options.addArguments("--headless");
}
if (OSUtil.isLinux()) {
options.addArguments("--no-sandbox"); // 适用于Linux环境
options.addArguments("--disable-dev-shm-usage"); // 适用于Linux环境
}
// 创建 WebDriver 实例
driver = new ChromeDriver(options);
js = (JavascriptExecutor) driver;
bInit = true;
}
@Override
public void quit() {
checkInit();
driver.quit();
bInit = false;
}
@Override
public void executeScript(String script) {
checkInit();
js.executeScript(script);
}
@Override
public WebElement findByExecuteScript(String script) {
checkInit();
return (WebElement) js.executeScript(script);
}
@Override
public String getStrByExecuteScript(WebElement webElement, String script) {
return (String) js.executeScript(script, webElement);
}
@Override
public List<WebElement> findByCssSelector(String selector) {
checkInit();
List<WebElement> webElementList = driver.findElements(By.cssSelector(selector));
return webElementList;
}
@Override
public List<WebElement> findByCssSelector(WebElement webElement, String selector) {
// todo 为啥这里不用 checkInit?
return webElement.findElements(By.cssSelector(selector));
}
@Override
public List<WebElement> findByIdSelector(String selector) {
checkInit();
List<WebElement> webElementList = driver.findElements(By.id(selector));
return webElementList;
}
@Override
public List<WebElement> findByIdSelector(WebElement webElement, String selector) {
// todo 为啥这里不用 checkInit?
return webElement.findElements(By.id(selector));
}
@Override
public List<WebElement> findByTag(String tag) {
checkInit();
List<WebElement> webElementList = driver.findElements(By.tagName(tag));
return webElementList;
}
@SneakyThrows
@Override
public void openUrl(String url) {
checkInit();
// 打开网页
driver.get(url);
while (!isOpenComplete()) {
// 页面还没有打开,等待 1 秒
Thread.sleep(1000);
}
log.debug("open {} success", url);
}
@Override
public boolean isOpenComplete() {
// 使用 JavaScript 检查页面加载状态,确保网页打开之后才执行后续的操作
String readyState = (String) js.executeScript("return document.readyState");
return "complete".equals(readyState);
}
@Override
public void waitUntilElementExist(String element, int timeout) {
checkInit();
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(timeout));
wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(element)));
}
private void checkInit() {
if (!bInit) {
throw new RuntimeException("WebDriverService还未初始化");
}
}
}
流程说明
当我在其他项目中导入了这个 jar
那么这个 jar 包里面的 META-INF/spring/AutoConfiguration.imports 就会被 spring 容器扫描到,然后就回去加载自动配置类CommonAutoConfiguration
因为CommonAutoConfigruation
引用了WebDriverConfig
,所以就会读取application.yml
中的配置
因为CommonAutoConfiguration
导入了WebDriverAutoConfiguration
,所以就会加载WebDriverAutoConfiguration
,并且创建出一个IWebDriverService
的bean,这个bean的内容会根据配置进行初始化
最后其它项目就能获取到这个bean,并进行使用了
IWebDriverService webDriverService = SpringUtil.getBean(IWebDriverService.class);
webDriverService.init();
后话
本文是我在等待gradle下载依赖时候编写,依赖下载太耗时间了,等的我心很烦,所以本文写的也就意思一下
这个自动配置我是参考pigx实现的,有兴趣的读者还是研究pigx的源码更好,我的代码也就我自己的项目用用,写的对不对也不知道呢
标签:springboot3.0,return,String,配置,selector,自动,org,import,public From: https://www.cnblogs.com/hellozjf/p/18487870