首页 > 其他分享 >springboot3.0自动配置

springboot3.0自动配置

时间:2024-10-20 20:48:19浏览次数:7  
标签:springboot3.0 return String 配置 selector 自动 org import public

目标

本文主要介绍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

相关文章

  • Windows 配置 MinGW-64
    下载地址:https://sourceforge.net/projects/mingw-w64/files/1.介绍MinGW,全称为MinimalistGNUonWindows,是将开源C语言编译器GCC移植到Windows平台的产物,它包含Win32API,能将源代码编译为可在Windows运行的可执行程序,还可使用一些Windows不具备的Linux平台下的开发工具......
  • SpringBoot使用默认的日志logback(2)—自定义配置+控制台输出sql语句
    原文链接:SpringBoot使用默认的日志logback(2)—自定义配置+控制台输出sql语句–每天进步一点点上一篇文章中简单介绍了springboot通过系统配置的方式配置日志:SpringBoot使用默认的日志logback(1)—系统配置这篇文章简单介绍一下日志的自定义配置。1.自定义配置springboot......
  • logback.xml配置文件详解
    原文链接:logback.xml配置文件详解–每天进步一点点上一篇文章介绍了springboot配置自定义日志文件logback.xml今天这篇文章简单介绍一下logback.xml配置文件的一些含义。1.基本结构logback的基本结构如下图:configuration表示配置的根节点appender用来格式化日志输出......
  • 如何自动识别CAD图中所有表格数据并导出
    在CAD图中自动识别并导出表格数据,是相关领域数据处理的重要需求。由于CAD图形并不像传统的电子表格那样具备明确的行列关系,表格常以线条和文本形式存在,手动提取不仅费时费力,还容易出错。如何通过自动化工具通过图形解析快速、高效地识别表格结构,提取数据并导出至Excel、CSV等格式......
  • 【开源】给荣耀盒子MediaQ M321增加自动进应用界面功能及扩展USB口
    很多年前买过一个荣耀盒子,型号是MediaQM321。这个盒子很精致,是我看到过的安卓机顶盒里面最小巧、紧凑的。主芯片型号是Hi3798Mv100,支持4K,虽然有点过时,但依然能用。这个机器最大的缺点是虽然可以安装app,但启动后第1屏是节目推荐,而应用列表在第7屏,开机后要按好几次遥控器按钮才能打......
  • nginx配置详解
    一、正向代理与反向代理1、正向代理客户端Client不直接访问服务器Server,通过代理服务器Proxy访问正向代理是客户主动使用的代理优点:通过代理的中转,客户端对服务器隐藏了IP,增加了安全性某些被禁止访问的IP通过代理也可以访问了2、反向代理服务器Server不直接响应客户端Clie......
  • 轻松原创!短剧,带货视频AI自动批量混剪工具!
    今天再分享这个批量剪辑神器,非常适合短剧和带货短视频的制作,轻松过原创,提供了从视频分割、合成、混剪到格式转换的多项功能。以下是它的主要功能:视频分割与提取按时长或段数分割按镜头转场变化分割按语音内容自动分割提取无声视频或音频视频合成自动合成文......
  • 轻松原创!短剧,带货视频AI自动批量混剪工具!
    今天再分享这个批量剪辑神器,非常适合短剧和带货短视频的制作,轻松过原创,提供了从视频分割、合成、混剪到格式转换的多项功能。以下是它的主要功能:视频分割与提取按时长或段数分割按镜头转场变化分割按语音内容自动分割提取无声视频或音频视频合成自动合成文......
  • 磁力万合AI智能全自动挂机掘金脚本,曰进五张
    本项目介绍了一种通过自动化脚本在磁力万合平台上刷视频以产生广告搜易的方法。用户可以通过在小号上安装脚本,自动访问特定账号的视频内容,从而获得广告搜易。项目概述通过在小号上安装自动化脚本,用户可以让这些账号自动访问并播放指定的磁力万合账号视频,模拟正常用户观......
  • 全自动掘金工具
    项目概述自动看广告任务脚本是一款专为流行短视频和资讯平台设计的辅助工具,它能够模拟用户行为,自动观看广告,从而帮助用户节省时间并完成平台设定的任务。支持平台抖音:自动观看推荐视频广告。快手:自动观看首页展示的广告。头条极速版:自动浏览信息流中嵌入的广告。3......