保姆级自动化测试教程(Selenium+java)

news2024/11/20 13:22:28

文章目录

  • 自动化测试
    • 1. 自动化测试介绍
    • 2. Selenium介绍与环境搭建
      • 2.1 介绍
      • 2.2 Selenium原理
      • 2.3 Selenium+Java环境搭建
    • 3. webdriver API
      • 3.1 元素的定位
      • 3.2 操作测试对象
      • 3.3 添加等待
      • 3.4 打印信息
      • 3.5 浏览器操作
      • 3.6 键盘事件
      • 3.7 鼠标事件
      • 3.9 特殊使用
      • 3.10 浏览器关闭
      • 3.11 切换窗口
      • 3.12 截图
    • 4. 实现自动化测试

自动化测试

1. 自动化测试介绍

自动化测试指软件测试的自动化,在预设状态下运行应用程序或者系统,预设条件包括正常和异常,最后评估运行结果。将人为驱动的测试行为转化为机器执行的过程。
自动化测试包括 UI自动化接口自动化单元测试自动化

  1. 单元测试 :最大的投入应该在单元测试上,单元测试运行的频率也更加高。java的单元测试框架是Junit。

  2. 接口自动化 :接口测试就是API测试,相对于UI自动化,API自动化更加容易实现,执行起来也更稳定。
    特点:

     - 可在产品前期,接口完成后介入。
     - 用例维护量小。
     - 适合接口变动较小,界面变动频繁的项目。
    

    常见的接口自动化测试工具有RobotFramework,JMeter,SoapUI,TestNG+HttpClient,Postman等。

  3. UI自动化 :虽然测试金字塔告诉我们尽量多做API层的自动化测试,但是UI层的自动化测试更加贴近用户的需求和软件系统的实际业务。并且有时候我们不得不进行UI层的测试。
    特点:

    • 用例维护量大。
    • 页面相关性强,必须后期项目页面开发完成后介入。
    • UI测试适合与界面变动较小的项目。

UI层的测试框架比较多,比如Windows客户端测试的AutoIT,web测试的selenium以及TestPlant eggPlant,Robot framework,QTP等。

以下将介绍的就是web应用中基于UI的自动化测试框架Selenium的使用;

2. Selenium介绍与环境搭建

2.1 介绍

Selenium是web应用中基于UI的自动化测试框架,支持多平台、多浏览器、多语言。早期的selenium RC已经被现在的webDriver所替代,可以简单的理解为selenium1.0+webdriver构成现在的Selenium2.0。它有由Selenium IDE,Webdriver,Selenium Grid组成。

  1. Selenium IDE :用于Selenium测试的完成集成开发环境,可以 录制在浏览器的用户操作,并且能回放,编辑和调试测试脚本。调试过程中可以逐步进行或调整执行的速度,并且可以在底部浏览日志出错信息。 录制的测试脚本可以以多种语言导出,比如java,C#,Python,Ruby等,方便掌握不同语言的测试人员操作。

  2. Webdriver :Selenium RC 在浏览器中运行 JavaScript 应用,会存在环境沙箱问题,而WebDriver可以跳出沙箱,针对不同的浏览器创建更健壮的,分布式的,跨平台的自动化测试脚本。基于特定语言绑定来驱动浏览器对Web元素进行操作和验证。

  3. selenium Grid :selenium Grid是一个服务器,提供对浏览器实例访问的服务器列表,管理各个节点的注册和状态信
    息。可以实现在同一时刻不同服务器上执行不同的测试脚本。

2.2 Selenium原理

在这里插入图片描述
解释说明 :通过自动化脚本代码创建一个HTTP请求发送到webdriver浏览器驱动,webdriver根据请求内容解析成能够操作浏览器的指令,浏览器通过指令执行测试步骤,然后返回结果给webdriver驱动,它再将结果返回给脚本。

2.3 Selenium+Java环境搭建

Chrome+Java 环境

  1. 下载chrome浏览器
    https://www.google.cn/intl/zh-CN/chrome/

  2. 查看chrome浏览器版本

  3. 下载chrome浏览器驱动
    https://chromedriver.chromium.org/downloads
    在这里插入图片描述
    在这里插入图片描述

  4. 配置环境变量
    解压下载好的驱动压缩包,将下载好的chromedriver.exe放到java系统环境变量下。
    举例:我的java路径是C:\Program Files\Java\jdk1.8.0_131\bin
    在这里插入图片描述

  5. 验证环境是否搭建成功
    创建java项目,添加pom文件中添加依赖

<dependencies>
    <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>3.141.59</version>
    </dependency>
</dependencies>
  1. 编写代码运行
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

public class Main {
    public static void main(String[] args) {
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver = new ChromeDriver(options);
        webDriver.get("https://www.baidu.com");
    }
}

在这里插入图片描述

如果打开了浏览器,此时说明安装成功

3. webdriver API

3.1 元素的定位

对象的定位应该是自动化测试的核心,要想操作一个对象,首先应该识别这个对象。webdriver 提供了一系列的对象定位方法,常用的有以下几种:不管哪种方式都应该保证定位要操作的对象是唯一的;

  1. id:通过页面元素id的值进行定位。

  2. name:如果这个元素有name,并且元素的name命名在整个页面是唯一的,那么我们可以用name来定位这个元素。

  3. class name和tag name:也是通过这两个属性的值进行定位。

  4. link text:有时候不是一个输入框也不是一个按钮,而是一个文字链接,我们可以通过链接内容来定位。

  5. xpath:XPath 是一种在XML 文档中定位元素的语言。因为HTML 可以看做XML 的一种实现,所以selenium 用户可是使用这种强大语言在web 应用中定位元素。XPath 扩展了上面id 和name 定位方式。 XPATH的获取可以用chrome的F12开发者模式中Element-右键-copy-copy xpath来获取

例如:webDriver.findElement(By.xpath(“//*[@id=“kw”]”));

  1. css selector:CSS 使用选择器来为页面元素绑定属性。这些选择器可以被selenium 用作另外的定位策略。CSS的获取可以用chrome的F12开发者模式中Element-右键-copy-copy selector来获取

例如:webDriver.findElement(By.cssSelector(“.s_ipt”)); 遵从css语法中选择器使用的规则

  1. partial link text:通过部分链接定位,可以只用链接的一部分文字进行匹配。

3.2 操作测试对象

通过上面元素定位找到操作的对象后,我们通过以下方法可以进行相关操作。具体使用参考下面完整的代码案例;

  1. click() 点击对象,可以实现提交效果。
  2. sendKeys() 在对象上模拟按键输入
  3. clear() 清除对象输入的文本内容
  4. submit() 提交,点击的元素在form标签中使用与click()效果一致。
  5. getAttribute()获取元素属性的值如value。
  6. getText ()用于获取元素的文本内容。

3.3 添加等待

  1. 强制等待:sleep()实现。
  2. 隐式等待: 等待页面所有元素。
  3. 显示等待:可以指定等待页面的某一个元素。
  4. 隐式等待和显示等待也称为智能等待。

强制等待与隐式等待区别:
如果等待时间是三天,那么强制等待,会一直等待直到三天结束,隐式等待如果等待过程中元素加载完成那么就提前结束等待。

隐式等待与显示等待的区别:
隐式等待是等待页面所有的元素加载完成后才执行下面代码,如果加载过程中超过等待时间就会报错;显示等待最长等待时间为设置的时间,在期间如果满足等待结束条件(until()方法中)就会结束等待。

使用方式:

在这里插入图片描述

显示等待,满足until方法就结束;
在这里插入图片描述

3.4 打印信息

通过getTitle() 方法打印title的值,通过getCurrentUrl() 方法打印url的值。

使用方式:

在这里插入图片描述

3.5 浏览器操作

  1. 浏览器前进
  2. 浏览器后退
  3. 浏览器滚动条操作
  4. 浏览器最大化
  5. 浏览器全屏
  6. 浏览器宽高设置

具体操作如下:

 private static void test06() throws InterruptedException {
        WebDriver webDriver = new ChromeDriver();
        //打开百度首页
        webDriver.get("https://www.baidu.com");
       //搜索迪丽热巴
        webDriver.findElement(By.cssSelector("#kw")).sendKeys("迪丽热巴");
        webDriver.findElement(By.cssSelector("#su")).click();
        //强制等待3秒
        sleep(3000);
        //浏览器后退
        webDriver.navigate().back();
        sleep(3000);
        //刷新
        webDriver.navigate().refresh();
        //强制等待
        sleep(3000);
        //浏览器前进
        webDriver.navigate().forward();
        //浏览器滚动条操作,此时需要将webDriver强制转换
        //executeScript()中是js代码,scrollTop方法是向上滚动多少个像素
        sleep(3000);
        ((JavascriptExecutor)webDriver).executeScript("document.documentElement.scrollTop=10000");

        //浏览器最大化
        webDriver.manage().window().maximize();
        sleep(3000);
        //浏览器全屏
        webDriver.manage().window().fullscreen();
        //设置浏览器宽高
        webDriver.manage().window().setSize(new Dimension(600,1000));

    }

3.6 键盘事件

通过sendKeys()调用按键:

1.sendKeys(Keys.TAB) # TAB
2.sendKeys(Keys.ENTER) # 回车
3.sendKeys(Keys.SPACE) #空格键
4.sendKeys(Keys.ESCAPE) #回退键(Esc)

组合使用:

1.sendKeys(Keys.CONTROL,‘a’) #全选(Ctrl+A)
2.sendKeys(Keys.CONTROL,‘c’) #复制(Ctrl+C)
3.sendKeys(Keys.CONTROL,‘x’) #剪贴(Ctrl+X)
4.sendKeys(Keys.CONTROL,‘v’) #粘贴(Ctrl+V)

 private static void test07() throws InterruptedException {
        ChromeOptions options = new ChromeOptions();
        //允许所有请求
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver = new ChromeDriver(options);
//        打开百度网页
        webDriver.get("https://www.baidu.com");
        webDriver.findElement(By.cssSelector("#kw")).sendKeys("迪丽热巴");
        //control+a
        webDriver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL,"A");
        sleep(3000);
        //control+x
        webDriver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL,"X");
        sleep(3000);
        //control+v
        webDriver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL,"V");
        

    }

3.7 鼠标事件

通过ActionChains 类实现鼠标执行的操作:

  1. contextClick() 右击
  2. doubleClick() 双击
  3. dragAndDrop() 拖动
  4. moveToElement() 移动

以下为鼠标右击的代码,其他方法也是如此使用:

//鼠标事件
    private static void test08() throws InterruptedException {
        ChromeOptions options = new ChromeOptions();
        //允许所有请求
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver = new ChromeDriver(options);
//        打开百度网页
        webDriver.get("https://www.baidu.com");
        webDriver.findElement(By.cssSelector("#kw")).sendKeys("迪丽热巴");
        webDriver.findElement(By.cssSelector("#su")).click();
        sleep(3000);
        //找到图片按钮
        WebElement webElement = webDriver.findElement(By.cssSelector("#\\32  > div > div > div > div > div.list-scroll_7E1go > div > div:nth-child(1) > div.avatar-wrapper_622F1 > a:nth-child(1) > div > div._capsule_1e0bo_35.capsule_GwMlS.cu-line-clamp-1"));
        //鼠标右击操作
        Actions actions = new Actions(webDriver);
        //鼠标移动到图片,右击,执行
        sleep(3000);
        actions.moveToElement(webElement).contextClick().perform();
    }

3.9 特殊使用

  1. 定位一组元素
    选中一组type为checkbox,在page01页面;

代码:

private static void page01() {
        // 创建一个浏览器驱动
        WebDriver webDriver = new ChromeDriver();
        // 打开网页
        webDriver.get("http://localhost:63342/Test/src/main/page/teste01.html?_ijt=bbsd02k86b9564t8p03vfmeff1&_ij_reload=RELOAD_ON_SAVE");
        // 获取到所有的input标签对应的元素
        List<WebElement> webElements = webDriver.findElements(By.cssSelector("input"));
        // 判断每一个input标签里面type值是checkbox进行点击,否则不点击
        for(int i = 0; i < webElements.size(); i++) {
            if(webElements.get(i).getAttribute("type").equals("checkbox")) {
                webElements.get(i).click();
            } else {

            }
        }
    }

结果:

在这里插入图片描述

  1. 多层框架/窗口定位
    对于一个web 应用,经常会出现框架(iframe) 或窗口(window)的应用,这样如果我们定位元素就不能直接右击copy他的xpath或者是cssselector来定位;但是可以通过switchTo()方法定位到frame下或者window下,然后通过元素css选择器或者xpath定位。

实现代码: 以下通过 switchTo() 实现定位到 iframe下的click按钮。

 private static void page02() {
        // 创建浏览器驱动
        WebDriver webDriver = new ChromeDriver();
        // 打开网页
        webDriver.get("http://localhost:63342/Test/src/main/page/test02.html?_ijt=ukda3p0a62ntrthar4gi039p32&_ij_reload=RELOAD_ON_SAVE");
        // 需要先定位到frame下再定位到click
        webDriver.switchTo().frame("f1");
        webDriver.findElement(By.cssSelector("body > div > div > a")).click();
        // 目标元素不在iframe,可以直接获取
//        String h3_text = webDriver.findElement(By.cssSelector("body > div > div > h3")).getText();
//        System.out.println(h3_text);
    }

效果:

在这里插入图片描述

  1. 操作下拉框
    下拉框是我们最常见的一种页面元素,对于一般的元素,我们只需要一次就定位。
    但下拉框里的内容需要进行两次定位,先定位到下拉框对下拉框进行操作后,再定位到下拉框内里的选项。

代码实现: 通过select实现选择下拉框中的内容,可以通过下拉框选择内容定位也可以通过下拉框选项位置定位

 private static void page03() {
        // 创建浏览器驱动
        WebDriver webDriver = new ChromeDriver();
        // 打开网页
        webDriver.get("http://localhost:63342/Test/src/main/page/test03.html?_ijt=obcfq47vlv4pfo2lointovotam&_ij_reload=RELOAD_ON_SAVE");
        // 操作下拉框
        Select select = new Select(webDriver.findElement(By.cssSelector("#ShippingMethod")));
//        select.selectByValue("12.51");
        select.selectByIndex(2);
    }

实现效果:

在这里插入图片描述

  1. 针对页面弹窗操作
    通过 alert操作其中方法有:
    1.text 返回alert 中的文字信息。
    2.accept 点击确认按钮。
    3.dismiss 点击取消按钮,如果有的话。
    4.sendKeys 输入值,如果alert 没有对话框就不能用了,不然会报错。

代码实现:先定位到弹窗按钮,然后通过webDriver.switchTo().alert() 对弹窗进行操作;

private static void page04() throws InterruptedException {
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("http://localhost:63342/Test/src/main/page/test04.html?_ijt=6gn3g58a7ubvp1honn2t773m7c&_ij_reload=RELOAD_ON_SAVE");
        webDriver.findElement(By.cssSelector("button")).click();
        sleep(3000);
        // alert弹窗确定
//        webDriver.switchTo().alert().accept();
        // alert弹窗取消
//        webDriver.switchTo().alert().dismiss();
        webDriver.switchTo().alert().sendKeys("你好");
        webDriver.switchTo().alert().accept();
    }

效果:

在这里插入图片描述

在这里插入图片描述

  1. 上传文件操作
    上传过程一般要打开一个本地窗口,从窗口选择本地文件添加,所以,一般会卡在如何操作本地窗口添加上传文件。
    在selenium webdriver 只要定位上传按钮,通过sendKeys 添加本地文件路径就可以了。
    绝对路径和相对路径都可以,关键是上传的文件存在。

代码实现:

 private static void page05() {
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("http://localhost:63342/Selenium01/src/main/Page/test05.html?_ijt=tmsdfhdm1lf1ururkjefb479tj&_ij_reload=RELOAD_ON_SAVE");
        // 找到按钮(上传文件的按钮),输入一个字符串
        webDriver.findElement(By.cssSelector("input")).sendKeys("C:\Users\34085\Desktop\hello.txt");
    }

实现效果

在这里插入图片描述

3.10 浏览器关闭

可以通过quit()和close()方法关闭浏览器,quit关闭整个浏览器并且清空缓存,close关闭当前页面。

直接通过webDriver.close()或者webDriver.quit()使用。

 //浏览器关闭操作
    private static void test09() throws InterruptedException {
        WebDriver webDriver = new ChromeDriver();
        //打开百度首页
        webDriver.get("https://www.baidu.com");
        //搜索迪丽热巴
        webDriver.findElement(By.cssSelector("#kw")).sendKeys("迪丽热巴");
        webDriver.findElement(By.cssSelector("#su")).click();
        //强制等待3秒
        sleep(3000);
        webDriver.close();
        webDriver.quit();

    }

3.11 切换窗口

进入百度页面然后点击新闻进入新闻页面,此时如果我们需要在新闻页面输入相关内容,是不能直接通过选择器定位实现的,此时我们需要先实现页面切换才能在新闻页面搜索内容。

代码实现:

//浏览器切换窗口
    private static void test10() throws InterruptedException {
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("https://www.baidu.com/");
        //点击新闻页面,在新闻面输入相关信息
        webDriver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click();
        //getWindowHandles获得所有窗口句柄
        //getWindowHandle获取get打开的窗口句柄
        // 获取到浏览器所有的窗口句柄
        Set<String> handles = webDriver.getWindowHandles();
        //遍历所有的窗口句柄
        String target_handle = "";
        for(String handle:handles) {
            //赋值
            target_handle = handle;
        }
        //System.out.println(target_handle);
        //在新闻页面搜索新闻联播
        webDriver.switchTo().window(target_handle);
        sleep(3000);
        webDriver.findElement(By.cssSelector("#ww")).sendKeys("新闻联播");
        webDriver.findElement(By.cssSelector("#s_btn_wr")).click();
       
    }

3.12 截图

实现截图功能,首先要在maven仓库下载对应的依赖比如Apache Commons IO » 2.13.0,复制到pom.xml文件中。

代码实现:

//浏览器截图
    private static void test11() throws InterruptedException, IOException {
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("https://www.baidu.com/");
        webDriver.findElement(By.cssSelector("#kw")).sendKeys("软件测试");
        webDriver.findElement(By.cssSelector("#su")).click();
        sleep(3000);
        //强制转换进行截图以文件形式存储
        File file = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);
        FileUtils.copyFile(file,new File("d://测试.png"));

    }

4. 实现自动化测试

完整代码: 首先我们通过webdriver建立连接,然后通过前端页面的选择器或者xpath定位我们的搜索框,通过sendKeys()方法输入内容,通过css选择器找到百度一下按钮,click()方法点击搜索。

  1. test01(): 测试百度搜索软件测试结果是否正确。
  2. test 02() : 通过百度搜索Java之后一定时间后清空搜索框。
  3. test03(): 获取百度页面某元素属性的值。
/**
 * @author zq
 */
 
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static java.lang.Thread.sleep;

//创建驱动所需
public class Main {
    public static void main(String[] args) throws InterruptedException {
      //test01();
      test02();
        //test03();

    }
   
    private static void  test01() throws InterruptedException {
        ChromeOptions options = new ChromeOptions();
        //允许所有请求
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver = new ChromeDriver(options);
//        打开百度网页
        webDriver.get("https://www.baidu.com");
//        找到百度搜索输入框,通过CSS中类选择器
        WebElement element = webDriver.findElement(By.cssSelector(".s_ipt"));
//         通过xPath
        WebElement element1 = webDriver.findElement(By.xpath("//*[@id=\"kw\"]"));
        //输入软件测试
        //element.sendKeys("软件测试");
        element1.sendKeys("软件测试");
        //找到百度一下按钮//点击
       webDriver.findElement(By.cssSelector("#su")).click();
       //强制休眠一会
       sleep(3000);
       //校验
        //找到搜索结果,通过父子类标签找到为软件测试的结果
       List<WebElement> elements =  webDriver.findElements(By.cssSelector("a em"));
        for (int i = 0; i < elements.size(); i++) {
            //System.out.println(elements.get(i).getText());
            if (!(elements.get(i).getText().contains("软件测试")||elements.get(i).getText().equals("测试"))){
                System.out.println("测试不通过");
                System.out.println(elements.get(i).getText());
            }else{
                System.out.println("测试通过");
            }
        }
    }
    private static void test02() throws InterruptedException {
        ChromeOptions options = new ChromeOptions();
        //允许所有请求
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver = new ChromeDriver(options);
//        打开百度网页
        webDriver.get("https://www.baidu.com");
        //输入java
        webDriver.findElement(By.cssSelector("#kw")).sendKeys("java");
        //点击百度一下
  webDriver.findElement(By.cssSelector("#su")).click();

        //设置sleep等待,会一直等到时间结束才执行下面的
        //sleep(300000000);
        //设置隐式等待,查询到结果就结束没有就一直到指定时间
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.DAYS);
       //清空结果
        webDriver.findElement(By.cssSelector("#kw")).clear();

    }
    
     private static void test03() {
        ChromeOptions options = new ChromeOptions();
        //允许所有请求
        options.addArguments("--remote-allow-origins=*");
        WebDriver webDriver = new ChromeDriver(options);
//        打开百度网页
        webDriver.get("https://www.baidu.com");
        WebElement element =webDriver.findElement(By.cssSelector("#su"));
        String s =   element.getText();
       // System.out.println(s); 通过这个无法获取元素属性值
        //通过getAttribute获取
        String s1 = element.getAttribute("value");
        System.out.println(s1);
    }

}

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

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

相关文章

让你不再好奇ai绘画生成器有哪些

绘画爱好者李明最近遇到了一个难题&#xff1a;他需要在短时间内完成一幅复杂的数字油画作品&#xff0c;但是他的手绘技能仍然不够熟练。于是&#xff0c;他想到了借助一些ai绘画软件来帮助他进行绘画创作。那么&#xff0c;你知道ai智能绘画软件有哪些吗&#xff1f;接下来我…

Vue中使用ElementUItable表格显示图片问题

1.问题 说明&#xff1a;table表格显示不了图片问题 品牌logo中显示的是url地址&#xff0c;因此我们要使用作用域插槽。 <template slot scope"{row,$index}"> </template> 说明&#xff1a;使用Vue的插槽功能&#xff0c;允许在当前列的内容上添加…

git暂存功能(只需要两步)

使用场景 我在写一个功能的时候发现一个bug&#xff0c;但是这个bug在我上一次提交的时候好像是没有的&#xff0c;所有我需要把当前的代码暂存,然后查看上一次提交是否正常。 一、暂存 暂存当前所有的修改 git stash二、恢复 恢复最近一次暂存&#xff0c;并把暂存删掉 …

获阿布扎比政府11亿美元投资将使蔚来改变电动汽车行业游戏规则?

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 总结 &#xff08;1&#xff09;6月20日&#xff0c;蔚来宣布与阿布扎比政府控股的投资公司CYVN Holdings签订了股份认购协议&#xff0c;蔚来将获得CYVN Holdings11亿美元的战略投资&#xff0c;这可能会导致蔚来在阿布扎…

从零开始 Spring Boot 50:Entity Lifecyle Event

从零开始 Spring Boot 50&#xff1a;Entity Lifecyle Event 图源&#xff1a;简书 (jianshu.com) 在上篇文章&#xff0c;我介绍了 Hibernate 中的实体生命周期以及可以转换实体状态的 Session API。就像 Spring Bean 的生命周期拥有一些事件&#xff0c;通过监听这些事件我们…

C# 中【委托】的简单理解

先不说 C# 中的委托编程&#xff0c;先从生活中的例子入手。 场景一&#xff1a; 防疫期间&#xff0c;外卖人员不能进入花园小区。外卖小哥到了花园小区门口&#xff0c;只好【委托】花园的保安人员&#xff0c;把东西送上楼去。 场景二&#xff1a; 有资格的人&#xff0c;都…

慢谈漫威--来龙去脉

慢谈漫威 背景介绍一、抛开电影看漫威相关公司背景、关系二、漫威宇宙和索尼漫威宇宙三、 漫威宇宙四、话外--美国6大影视公司 背景介绍 最近在看一部漫威电影&#xff0c;可能是年纪大了&#xff0c;看美国英雄大片以及系列电影提不起兴趣&#xff0c;各种人物背景关系也不清…

途乐证券|光伏概念发力上扬,好利科技涨停,隆基绿能等拉升

光伏概念28日盘中发力上扬&#xff0c;截至发稿&#xff0c;露笑科技、好利科技、宁波能源等涨停&#xff0c;中国动力、欧晶科技、聚合材料、鹿山新材等涨超5%&#xff0c;帝科股份、隆基绿能、福斯特等涨超3%。 露笑科技昨日晚间披露的半年度业绩预告&#xff0c;预计上半年归…

ST - 如何下载带有.ioc的官方工程

文章目录 ST - 如何下载带有.ioc的官方工程概述下载带有.ioc文件的官方工程的方法备注END ST - 如何下载带有.ioc的官方工程 概述 有些CubeMX的官方工程, 自己复现不出来. 但是官方工程是好使的. 这是, 可能差别就在工程配置上. 如果仅仅靠BC4比对官方工程和自己重建的工程, …

简单指令实现Docker构建镜像启动运行保存导出后再导入新环境完整全流程

项目场景及问题描述 本文做一个简单Docker使用指令指南&#xff0c;可快速实现Docker构建镜像、启动、运行、保存、导出后再导入新环境完整全流程。具体每一个指令又有很多参数和学问&#xff0c;大家可自行查询更详细的解释&#xff0c;本文可用于小白快速构建镜像并使用。 使…

【doxygen】doxygen 支持 markdown 公式

文章目录 配置 doxygenmarkdown 文件中插入公式在段落中插入公式公式居中显示公式分行显示效果展示 参考链接 配置 doxygen 在 Doxygen 配置文件&#xff08;通常是 Doxyfile &#xff09;中&#xff0c;确保以下选项已启用或设置&#xff1a; MARKDOWN_SUPPORT &#xff1a;设…

100种思维模型之心流理论思维模型-86

亚里士多德说&#xff0c; 人类的终极目标是获得幸福 &#xff01; 那么到底什么是幸福&#xff1f;如何才能获得幸福&#xff1f; 米哈里契克森米哈赖&#xff0c; 积极心理学奠基人之一&#xff0c; “心流” 理论的提出者&#xff0c;他在其著作《心流》一书中这样写道…

操作系统4——存储器管理

本系列博客重点在深圳大学操作系统课程的核心内容梳理&#xff0c;参考书目《计算机操作系统》&#xff08;有问题欢迎在评论区讨论指出&#xff0c;或直接私信联系我&#xff09;。 梗概 本篇博客主要介绍操作系统第四章存储器管理与第五章虚拟存储器的相关知识。 目录 一、…

辛苦写的文章在自媒体上难以盈利的原因分析!

自媒体是指个人或组织通过互联网自主开设自己的媒体平台&#xff0c;并在其平台上发布原创内容&#xff0c;获取流量并从中获得收益的一种模式。自媒体的发展可以让更多的人有机会成为内容创作者&#xff0c;并能够通过自己的努力获得收益&#xff0c;但实际情况是&#xff0c;…

Linux ps命令常见实战用法

文章目录 一、基本介绍1.1 基本介绍1.2 常用参数1.3 字段含义 二、常见用法2.1 查看所有进程2.2 查看特定进程信息 参考资料 Linux中的ps命令是Process Status的缩写。当程序运行在系统上时&#xff0c;我们称之为进程。想监测这些进程&#xff0c;需要熟悉ps命令的用法。ps能输…

2023一造土建安装案例《十年真题▪九套模拟》

造价工程师&#xff0c;是指通过全国统一考试取得中华人民共和国造价工程师执业资格证书&#xff0c;并经注册后从事建设工程造价工作的专业人员。国家对造价工程师实行准入类职业资格制度&#xff0c;纳入国家职业资格目录。凡从事工程建设活动的建设、设计、施工、造价咨询等…

合合信息智能文字识别产品通过中国信通院“可信AI—OCR智能化服务”评估

近年来&#xff0c;我国对数据的重视程度不断加强。2022年1月&#xff0c;国务院印发的《“十四五”数字经济发展规划》进一步提出&#xff0c;到2025年要初步建立数据要素市场体系&#xff0c;并对充分发挥数据要素价值作出重要部署。然而&#xff0c;现阶段有大量的数据信息以…

Java ~ Executor ~ AbstractExecutorService【总结】

前言 文章 相关系列&#xff1a;《Java ~ Executor【目录】》&#xff08;持续更新&#xff09;相关系列&#xff1a;《Java ~ Executor ~ AbstractExecutorService【源码】》&#xff08;学习过程/多有漏误/仅作参考/不再更新&#xff09;相关系列&#xff1a;《Java ~ Execu…

《痞子衡嵌入式半月刊》 第 78 期

痞子衡嵌入式半月刊&#xff1a; 第 78 期 这里分享嵌入式领域有用有趣的项目/工具以及一些热点新闻&#xff0c;农历年分二十四节气&#xff0c;希望在每个交节之日准时发布一期。 本期刊是开源项目(GitHub: JayHeng/pzh-mcu-bi-weekly)&#xff0c;欢迎提交 issue&#xff0c…

2023双态IT北京用户大会回顾(三) | 银行分布式核心智能运维体系思考

​文末附有本场专题演讲视频 2023第五届双态IT北京用户大会&#xff0c;擎创科技专场演讲回顾之三&#xff1a;《银行分布式核心智能运维体系思考》&#xff0c;演讲嘉宾&#xff1a;擎创科技生态合作部总经理 冯陈湧 一、前言&#xff1a;分布式云原生快速发展催生更高的业务要…