软件测试—— Selenium 常用函数(一)

news2024/11/23 3:37:56

前一篇文章:软件测试 —— 自动化基础-CSDN博客

目录

·前言

一、窗口

1.屏幕截图

2.切换窗口

3.窗口设置大小

4.关闭窗口

二、等待

1.等待意义

2.强制等待

3.隐式等待

4.显式等待

·总结


·前言

        在前一篇文章中,我们介绍了自动化的一些基础知识,还介绍及简单使用了 Selenium 这个 Web 自动化测试工具及部分函数,本篇文章来对 Selenium 里的常用函数继续进行介绍,这里介绍的函数主要是对浏览器窗口与等待方式的常见操作进行自动化,下面就开始本篇文章的内容介绍吧。

一、窗口

1.屏幕截图

        在介绍屏幕截图前,先给大家演示一段代码示例,这里的代码及详细介绍和运行效果如下所示:

public class Test {
    WebDriver driver;
    // 创建驱动
    void createDriver() {
        // 1. 创建驱动对象, 打开浏览器
        WebDriverManager.chromedriver().setup();
        // 2. 增加浏览器配置, 创建驱动对象要强制指定允许访问所有链接
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        driver = new ChromeDriver(options);
        // 3. 输入完整的网址: https:www.baidu.com
        driver.get("https://www.baidu.com/");
    }

    void test05() throws IOException, InterruptedException {
        createDriver();
        // 查找元素并进行点击, 这里查找的是 "百度首页" 中的 "新闻"
        driver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click();
        // 观察结果
        Thread.sleep(3000);
        // 使用 element 获取查找的元素
        WebElement element = driver.findElement(By.cssSelector("#news-hotwords > div.bd > ul > li.li_0.li_color_0.button-slide > a"));
        // 打印元素的文本信息
        System.out.println(element.getText());
        driver.quit();
    }

    public static void main(String[] args) throws InterruptedException, IOException {
        Test test = new Test();
        test.test05();
    }
}

        此时代码出现了报错,我们把跳转后要查找的元素选择器的值在相应页面进行查找,如下图所示: 

        既然跳转后的网站可以查找到对应元素,为什么运行程序后会报错呢?此时我们就可以通过屏幕截图来抓拍程序运行时的错误场景。

        使用屏幕截图方法需要添加相应的依赖,添加依赖代码如下所示:

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>

        添加完依赖之后,我们就可以编写一个简单的屏幕截图代码,添加到上述代码中,来观察结果,代码及详细介绍如下所示: 

    void test05() throws IOException, InterruptedException {
        createDriver();
        // 查找元素并进行点击, 这里查找的是 "百度首页" 中的 "新闻"
        driver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click();
        // 观察结果
        Thread.sleep(3000);
        // 屏幕截图
        File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
        // 把截图 srcFile 放到指定的位置
        FileUtils.copyFile(srcFile, new File("my.png"));
        // 使用 element 获取查找的元素
        WebElement element = driver.findElement(By.cssSelector("#news-hotwords > div.bd > ul > li.li_0.li_color_0.button-slide > a"));
        // 打印元素的文本信息
        System.out.println(element.getText());
        driver.quit();
    }

        此时,我们屏幕截取的图片如下所示: 

        通过观察屏幕截图抓拍程序运行时的图片可以发现,程序在点击“新闻”这个标签后,并不像我们眼睛所观察的结果一样跳转到了“新闻”这个标签页,而是还停留在百度首页,所以才会出现错误,查找不到元素的情况。

        如何解决这个问题,我们留到下面“切换窗口”来介绍,下面我来对屏幕截图再做一些介绍,刚才我们在代码中使用的屏幕截图是最简单的版本,它会出现一个严重的问题,就是如果多次调用这种方式来截图,那么之后只能获取最后一次屏幕截图的图片,其余都会被覆盖,我们在使用屏幕截图一定要注意以下几点:

  • 每次生成的屏幕截图都能保存下来,避免覆盖;
  • 屏幕截图文件同一放在一个文件夹下(如:image);
  • 生成的屏幕截图名称要见名知意,即一看见这个屏幕截图就知道是什么时候的。 

        下面我来规划一下生成屏幕截图文件夹的结构,如下图所示:         规定好生成屏幕截图的文件存储方式后,我们就实现一个方法来专门处理屏幕截图的操作,方法的具体代码及详细介绍如下所示:

    // 进阶版屏幕截图
    void getScreenShot(String str) throws IOException {
        // 规定时间格式为 年-月-日, 如: 2024-11-17
        SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");
        // 规定时间格式为 时分秒毫秒, 如: 171953345
        SimpleDateFormat sim2 = new SimpleDateFormat("HHmmssSS");
        // 创建文件夹的名称, 以现在的日期来命名, 用 sim1 来转化时间格式
        String dirTime = sim1.format(System.currentTimeMillis());
        // 创建文件名称, 以现在的时间来命名, 用 sim2 来转化时间格式
        String fileTime = sim2.format(System.currentTimeMillis());
        // 拼接好完整文件名(包含:存放具体位置,及文件名称)
        String filename = "./src/test/image/" + dirTime + "/" + str + "-" + fileTime + ".png";
        // 打印完整文件名,用来调试
        System.out.println("filename: " + filename);
        // 屏幕截图
        File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
        // 把截图 srcFile 放到指定的位置
        FileUtils.copyFile(srcFile, new File(filename));
    }

2.切换窗口

        通过上面屏幕截图的示例,我们会发现,在百度首页点击“新闻”时会新打开一个标签页,然而我们的 driver 还停留在前一个页面,这就导致我想获取新的页面中的元素获取不到,这是因为,在我们手工测试的时候可以通过眼睛来判断当前的窗口是什么,但是对应程序来说,它无法判断当前最新的窗口应该是哪一个,那么程序如何来识别每一个窗口呢?其实我们浏览器的每个窗口都有一个唯一的属性句柄(handle),我们可以通过句柄来切换我们当前的浏览器窗口。

        介绍完这些,我们就可以在代码中进行切换窗口的操作了,我们来对上面的错误代码进行修改,具体代码及详细介绍和运行结果如下所示:

    // 切换窗口
    void test05() throws IOException, InterruptedException {
        // 创建驱动
        createDriver();
        // 屏幕截图
        getScreenShot("test05()");
        // 查找元素并进行点击, 这里查找的是 "百度首页" 中的 "新闻"
        driver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click();
        // 获取当前的句柄
        String curHandle = driver.getWindowHandle();
        // 接收当前所有句柄
        Set<String> allHandles = driver.getWindowHandles();
        // 遍历获取到非当前句柄的句柄
        for (String handle : allHandles) {
            if (!handle.equals(curHandle)) {
                // 切换句柄 driver--->百度新闻
                driver.switchTo().window(handle);
            }
        }
        // 屏幕截图
        getScreenShot("test05");
        // 使用 element 获取查找的元素
        WebElement element = driver.findElement(By.cssSelector("#news-hotwords > div.bd > ul > li.li_0.li_color_0.button-slide > a"));
        // 打印元素的文本信息
        System.out.println(element.getText());
        driver.quit();
    }

        执行过程中的两次屏幕截图如下所示:

        到这,窗口的切换就介绍完了。 

3.窗口设置大小

        窗口的大小设置有以下四种情况:

  • 窗口最大化;
  • 窗口最小化;
  • 窗口全屏;
  • 手动设置窗口大小。

        对于这四种窗口大小的设置方式,Selenium 中也有对应的函数来实现,下面我就来编写代码演示一下这四个函数的用法及效果,具体代码及详细介绍如下所示:

public class Test {
    WebDriver driver;
    // 创建驱动
    void createDriver() {
        // 1. 创建驱动对象, 打开浏览器
        WebDriverManager.chromedriver().setup();
        // 2. 增加浏览器配置, 创建驱动对象要强制指定允许访问所有链接
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        driver = new ChromeDriver(options);
        // 3. 输入完整的网址: https:www.baidu.com
        driver.get("https://www.baidu.com/");
    }

    // 设置窗口大小
    void test06() throws InterruptedException {
        // 创建驱动
        createDriver();
        Thread.sleep(2000);
        // 窗口最大化
        driver.manage().window().maximize();
        Thread.sleep(2000);
        // 窗口最小化
        driver.manage().window().minimize();
        Thread.sleep(2000);
        // 全屏窗口
        driver.manage().window().fullscreen();
        Thread.sleep(2000);
        // 手动设置窗口大小
        driver.manage().window().setSize(new Dimension(700,521));
        Thread.sleep(2000);
        driver.quit();
    }

    public static void main(String[] args) throws InterruptedException, IOException {
        Test test = new Test();
        test.test06();
    }
}

​​​​​​​

4.关闭窗口

        关闭窗口之后要注意 driver 要重新定义,当 driver 调用关闭窗口的函数之后,driver 所在的就是一个空的窗口了,此时使用 driver 进行的所有操作就都会报错,所以需要在关闭窗口后对 driver 进行重新定义,函数的具体使用方式如下:

// 关闭当前窗口
driver.close();

二、等待

1.等待意义

        我们来观察一段代码示例的运行结果,这里的代码及详细介绍和运行效果如下所示:

public class Test {
    WebDriver driver;
    // 创建驱动
    void createDriver() {
        // 1. 创建驱动对象, 打开浏览器
        WebDriverManager.chromedriver().setup();
        // 2. 增加浏览器配置, 创建驱动对象要强制指定允许访问所有链接
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        driver = new ChromeDriver(options);
        // 3. 输入完整的网址: https:www.baidu.com
        driver.get("https://www.baidu.com/");
    }

    void test07() {
        // 创建驱动
        createDriver();
        // 查找搜索框, 输入 "彭于晏"
        driver.findElement(By.cssSelector("#kw")).sendKeys("彭于晏");
        // 查找 "百度一下" 按钮, 点击搜索
        driver.findElement(By.cssSelector("#su")).click();
        // 在跳转后的页面查找 "百度百科" 的元素位置
        driver.findElement(By.cssSelector("#\\31  > div > div > div > div > div > div.new-tag_4ozgi.new-text-link_3k9GD > div > div.flex-wrapper-top_3ucFS > div.flex-col-left_3trtY.baike-wrapper_6AORN.cu-pt-xs-lg.baike-wrapper-pc_26R04.cu-pt-xl.baike-wrapper-left-pc_5eYY8.cos-space-pb-sm > div > div > p > span:nth-child(1) > span"));
        driver.quit();
    }

    public static void main(String[] args) throws InterruptedException, IOException {
        Test test = new Test();
        test.test07();
    }

}

        此时代码出现了报错,我们把跳转后要查找的元素选择器的值在相应页面进行查找,如下图所示:

        既然跳转后的网站可以查找到对应元素,为什么运行程序后会报错呢?此时我们就可以通过屏幕截图来抓拍程序运行时的错误场景,截取的页面如下所示:

        根据截取的图片我们会发现,在点击“百度一下”之后,跳转的页面还没有把我们要获取的元素渲染出来,所以导致了我们查找元素失败的结果, 此时我们在报错的代码前加上 Thread.sleep(秒),设置时间长一点就可以获取到查找的元素了。

        我们使用等待,就是为了预防由于代码执行速度比页面渲染速度快导致页面没有渲染出来,程序就已经开始查找元素使元素没有被找到的问题,在 Selenium 中,为我们提供了三种等待方法:强制等待、隐式等待、显示等待。

2.强制等待

        强制等待对我们来说已经是非常熟悉了,它使用的就是 Thread.sleep() 这个方法,前面使用的地方有很多,这里就不再进行演示了,关于强制等待,它的优缺点如下:

  • 优点:使用简单,调试的时候比较有效;
  • 缺点:影响运行效率,浪费大量的时间。

        对于强制等待这种方式主要应用的场景就是在我们调试代码期间。 

3.隐式等待

        隐式等待是一种智能等待,它可以规定在查找元素时,在指定时间内不断查找元素,如果找到则代码继续执行,如果直到超时还没找到元素就会报错。下面我在上面代码中进行使用隐式等待,具体代码及运行结果如下所示:

public class Test {
    WebDriver driver;
    // 创建驱动
    void createDriver() {
        // 1. 创建驱动对象, 打开浏览器
        WebDriverManager.chromedriver().setup();
        // 2. 增加浏览器配置, 创建驱动对象要强制指定允许访问所有链接
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        driver = new ChromeDriver(options);
        // 3. 输入完整的网址: https:www.baidu.com
        driver.get("https://www.baidu.com/");
    }

    void test07() {
        // 创建驱动
        createDriver();
        // 加入隐式等待, 超时时间为 3 秒
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
        // 查找搜索框, 输入 "彭于晏"
        driver.findElement(By.cssSelector("#kw")).sendKeys("彭于晏");
        // 查找 "百度一下" 按钮, 点击搜索
        driver.findElement(By.cssSelector("#su")).click();
         // 点击搜索之后,进行 "屏幕截图"
        getScreenShot("test07");
        // 在跳转后的页面查找 "百度百科" 的元素位置
        driver.findElement(By.cssSelector("#\\31  > div > div > div > div > div > div.new-tag_4ozgi.new-text-link_3k9GD > div > div.flex-wrapper-top_3ucFS > div.flex-col-left_3trtY.baike-wrapper_6AORN.cu-pt-xs-lg.baike-wrapper-pc_26R04.cu-pt-xl.baike-wrapper-left-pc_5eYY8.cos-space-pb-sm > div > div > p > span:nth-child(1) > span"));
        driver.quit();
    }

    public static void main(String[] args) throws InterruptedException, IOException {
        Test test = new Test();
        test.test07();
    }

}

         此时,程序就可以正确的找到元素了。

        隐式等待用到的方法是 implicitlyWait(),参数:Duration 类中提供的毫秒、秒、分钟等方法,隐式等待的作用域是整个脚本的所有元素,只要 driver 对象没有被释放掉(driver.quit()),隐式等待就会一直生效,有关隐式等待的优缺点如下:

  • 优点:智能等待,作用于全局;
  • 缺点:只能查找元素时才会触发。

4.显式等待

        显式等待也是一种智能等待,在指定超时时间范围内只要满足操作条件就会继续执行后续代码,它的使用代码如下所示:

new WebDriverWait(driver, Duration.ofSeconds(3)).until($express)

        这里的 $express:涉及到 Selenium.support.ui.ExpectedConditions 包下的 ExpectedConditions 类,在这个类中包含了许多方法,如下图所示:        这里我来简单介绍其中几个方法,如下表所示:

方法作用
elementToBeClickable(By locator)用于检查元素的期望是可见的并已启用,以便我们可以点击它。
textToBe(By locator, String str)检查元素是否存在(精确匹配)。
presenceOfElementLocated(By locator)检查页面的 DOM 上是否存在元素。
urlToBe(String url)检查当前页面的 URL 是一个特定的 URL

        下面我来编写一段显式等待的使用代码,具体代码及结果如下所示:

public class Test {
    WebDriver driver;
    // 创建驱动
    void createDriver() {
        // 1. 创建驱动对象, 打开浏览器
        WebDriverManager.chromedriver().setup();
        // 2. 增加浏览器配置, 创建驱动对象要强制指定允许访问所有链接
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        driver = new ChromeDriver(options);
        // 3. 输入完整的网址: https:www.baidu.com
        driver.get("https://www.baidu.com/");
    }

    // 测试显示等待
    void test08() {
        createDriver();
        // 连续写法
        // new WebDriverWait(driver, Duration.ofSeconds(3)).until(ExpectedConditions.elementToBeClickable(By.cssSelector("#su")));
        // 分开写法
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));
        // 百度输入框是否存在
        wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#kw")));
        driver.findElement(By.cssSelector("#kw"));
        driver.quit();
    }

    public static void main(String[] args) throws InterruptedException, IOException {
        Test test = new Test();
        test.test08();
    }
}

        此时程序正确运行, 

        显式等待只作用在当前的条件上,有关显式等待的优缺点如下:

  • 优点:显式等待是智能等待,可以自定义显示等待的条件,操作灵活;
  • 缺点:写法复杂。 

        如果显式等待和隐式等待一起使用效果会如何呢?我们可以再编写一段代码来观察其运行结果,具体代码及运行结果如下所示:

public class Test {
    WebDriver driver;
    // 创建驱动
    void createDriver() {
        // 1. 创建驱动对象, 打开浏览器
        WebDriverManager.chromedriver().setup();
        // 2. 增加浏览器配置, 创建驱动对象要强制指定允许访问所有链接
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        driver = new ChromeDriver(options);
        // 3. 输入完整的网址: https:www.baidu.com
        driver.get("https://www.baidu.com/");
    }

    // 测试显式等待与隐式等待一起使用
    void test09() {
        createDriver();
        //隐式等待设置为5s,显式等待设置为10s,那么结果会是等待多少?
        SimpleDateFormat sim =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 打印运行之前时间
        System.out.println(sim.format(System.currentTimeMillis()));
        // 设置隐式等待
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
        // 设置显式等待
        WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(10));
        try {
            // 查找的元素不存在
            wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#iiiii")));
        }catch (Exception e) {
            System.out.println("没有找到元素!");
        }
        // 打印运行结束后的时间
        System.out.println(sim.format(System.currentTimeMillis()));
        driver.quit();
    }

    public static void main(String[] args) throws InterruptedException, IOException {
        Test test = new Test();
        test.test09();
    }
}

        经过多次次运行,打印的等待时间有 10s 与 11s,由此我们可以看出,在混合使用隐式等待和显式等待时,可能会导致不可预测的等待时间。

·总结

        文章到此就要结束了,本篇文章介绍了使用 Selenium 中函数来对浏览器中窗口各种操作的自动化实现,以及介绍了等待这一操作的作用及相关用法,如果对文章内容有所疑惑,欢迎在评论区进行留言,如果感觉本篇文章还不错希望能收到你的三连支持,那么我们下一篇文章再见吧~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2245703.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UE5 腿部IK 解决方案 footplacement

UE5系列文章目录 文章目录 UE5系列文章目录前言一、FootPlacement 是什么&#xff1f;二、具体实现 前言 在Unreal Engine 5 (UE5) 中&#xff0c;腿部IK&#xff08;Inverse Kinematics&#xff0c;逆向运动学&#xff09;是一个重要的动画技术&#xff0c;用于实现角色脚部准…

私有化部署视频平台EasyCVR宇视设备视频平台如何构建视频联网平台及升级视频转码业务?

在当今数字化、网络化的时代背景下&#xff0c;视频监控技术已广泛应用于各行各业&#xff0c;成为保障安全、提升效率的重要工具。然而&#xff0c;面对复杂多变的监控需求和跨区域、网络化的管理挑战&#xff0c;传统的视频监控解决方案往往显得力不从心。 EasyCVR视频融合云…

山东春季高考-C语言-综合应用题

&#xff08;2018年&#xff09;3.按要求编写以下C语言程序&#xff1a; &#xff08;1&#xff09;从键盘上输入三个整数a、b、c&#xff0c;判断能否以这三个数为边构成三角形&#xff0c;若可以则计算机三角形的面积且保留两位小数&#xff1b;若不可以则输出“不能构成三角…

Linux移植IMX6ULL记录 一:编译源码并支持能顺利进入linux

目录 前言 一、不修改文件进行编译 二、修改设备树文件进行编译 前言 我用的开发板是100_ask_imx6ull_pro&#xff0c;其自带的linux内核版本linux-4.9.88&#xff0c;然后从linux官网下载过来的linux-4.9.88版本的arch/arm/configs/defconfig和dts设备树文件并没有对imx6ull…

从Stream的 toList() 和 collect(Collectors.toList()) 方法看Java的不可变流

环境 JDK 21Windows 11 专业版IntelliJ IDEA 2024.1.6 背景 在使用Java的Stream的时候&#xff0c;常常会把流收集为List。 假设有List list1 如下&#xff1a; var list1 List.of("aaa", "bbbbbb", "cccc", "d", "eeeee&qu…

大语言模型---LoRA简介;LoRA的优势;LoRA训练步骤;总结

文章目录 1. 介绍2. LoRA的优势3. LoRA训练步骤&#xff1a;4.总结 1. 介绍 LoRA&#xff08;Low-Rank Adaptation&#xff09;是一种用于高效微调大模型的技术&#xff0c;它通过在已有模型的基础上引入低秩矩阵来减少训练模型时所需的参数量和计算量。具体来说&#xff0c;L…

Debug-031-近期功能实现小结

由于时间原因&#xff0c;没办法对每个小的功能点进行比较细致的总结&#xff0c;这里统一去记录一下最近的实现了的功能&#xff0c;算是存档备份&#xff0c;为今后开发带来便利和参考。 一、ACEeditor ACEeditor使用手册&#xff08;一&#xff09;_ace editor-CSDN博客 AC…

深度学习中的mAP

在深度学习中&#xff0c;mAP是指平均精度均值(mean Average Precision)&#xff0c;它是深度学习中评价模型好坏的一种指标(metric)&#xff0c;特别是在目标检测中。 精确率和召回率的概念&#xff1a; (1).精确率(Precision)&#xff1a;预测阳性结果中实际正确的比例(TP / …

基于SpringBoot+Vue的影院管理系统(含演示视频+运行截图+说明文档)

web启动链接地址&#xff1a; http://localhost:8082&#xff08;管理端&#xff09; http://localhost:8081&#xff08;用户端&#xff09; http://localhost:8082&#xff08;员工端&#xff09; 一、项目介绍 基于框架的系统&#xff0c;系统分为用户、员工和管理员三个…

科研实验室的数字化转型:Spring Boot系统

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理实验室管理系统的相关信息成为必然。开发合…

网络无人值守批量装机-cobbler

网络无人值守批量装机-cobbler 一、cobbler简介 ​ 上一节中的pxe+kickstart已经可以解决网络批量装机的问题了,但是环境配置过于复杂,而且仅针对某一个版本的操作系统进批量安装则无法满足目前复杂环境的部署需求。 ​ 本小节所讲的cobbler则是基于pxe+kickstart技术的二…

基于Java Springboot二手商品网站

一、作品包含 源码数据库全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据库&#xff1a;…

使用chrome 访问虚拟机Apache2 的默认页面,出现了ERR_ADDRESS_UNREACHABLE这个鸟问题

本地环境 主机MacOs Sequoia 15.1虚拟机Parallels Desktop 20 for Mac Pro Edition 版本 20.0.1 (55659)虚拟机-操作系统Ubuntu 22.04 服务器版本 最小安装 开发环境 编辑器编译器调试工具数据库http服务web开发防火墙Vim9Gcc13Gdb14Mysql8Apache2Php8.3Iptables 第一坑 数…

java: spire.pdf.free 9.12.3 create pdf

可以用windows 系统中文字体&#xff0c;也可以从文件夹的字体文件 /*** encoding: utf-8* 版权所有 2024 ©涂聚文有限公司* 许可信息查看&#xff1a;言語成了邀功盡責的功臣&#xff0c;還需要行爲每日來值班嗎* 描述&#xff1a;* # Author : geovindu,Geovin Du 涂…

PSO融合DWA路径规划(附MATLAB源代码)

PSO&#xff08;粒子群优化算法&#xff09;和DWA&#xff08;动态窗口法&#xff09;是路径规划领域常用的两种算法&#xff0c;它们结合使用可以充分发挥各自的优势&#xff0c;实现高效且安全的机器人路径规划。 1. PSO算法的全局路径规划 - 工作原理&#xff1a;PSO模拟群…

双因子认证:统一运维平台安全管理策略

01双因子认证概述 双因子认证&#xff08;Two-Factor Authentication&#xff0c;简称2FA&#xff09;是一种身份验证机制&#xff0c;它要求用户提供两种不同类型的证据来证明自己的身份。这通常包括用户所知道的&#xff08;如密码&#xff09;、用户所拥有的&#xff08;如…

蓝桥杯每日真题 - 第19天

题目&#xff1a;&#xff08;费用报销&#xff09; 题目描述&#xff08;13届 C&C B组F题&#xff09; 解题思路&#xff1a; 1. 问题抽象 本问题可以看作一个限制条件较多的优化问题&#xff0c;核心是如何在金额和时间约束下选择最优方案&#xff1a; 动态规划是理想…

MyBatis实践:提高持久化层数据处理效率

一、MyBatis简介: 1.简介:https://mybatis.org/mybatis-3/zh/index.html?spmwolai.workspace.0.0.66162306mX2SuC MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code。随着开发团队转投Google Code旗下&#xff…

HTML5实现剪刀石头布小游戏(附源码)

文章目录 1.设计来源1.1 主界面1.2 皮肤风格1.2 游戏中界面 2.效果和源码源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/143798520 HTM…

Three.js + AI:AI 算法生成 3D 萤火虫飞舞效果~

AI 驱动 3D 动画 大家好&#xff0c;我是石小石&#xff01;随着 Web 技术的发展&#xff0c;Three.js 成为构建 3D 图形和动画的主流工具。与此同时&#xff0c;人工智能&#xff08;AI&#xff09;在图像处理、动作生成等领域表现出强大能力。将 AI 与 Three.js 结合&#x…