《基于Selenium的论坛系统自动化测试实战报告》
一、项目背景与技术选型
-
项目简介
-
目标系统:论坛系统
-
核心功能:用户注册/登录、会话框发送信息、好友列表、信息发送
-
技术栈:html + Springboot + MySQL数据库
-
-
为什么选择Selenium
-
支持多浏览器兼容性测试(Chrome/Firefox/Edge)
-
完善的元素定位体系(XPath/CSS Selector)
-
动态内容处理能力(WebDriverWait机制)
-
跨平台执行能力(Windows/Linux/macOS)
-
-
测试环境
在开始测试之前,我们需要准备好测试环境。以下是测试所需的硬件和软件环境:
-
硬件:普通个人电脑
-
操作系统:Windows 10 或 Windows 11
-
浏览器:Chrome(版本 128.0.6613.84 或以上)
-
项目运行环境:maven、JDK1.8
-
自动化测试工具:Selenium
二、测试用例设计+手动测试

用户注册

用户登录

用户退出+站内私信

个人中心

帖子模块


三、功能测试用例设计
3.1 注册页面测试

3.1.1 测试场景 1:注册信息不全
-
预期结果:页面提示部分信息不能为空。
-
实际结果:系统确实给出了相应的提示,要求补全所有必填项,与预期一致。

3.1.2 测试场景 2:用户名已存在
-
预期结果:系统应该提示用户该用户名已经存在。
-
实际结果:系统确实给出了提示,提示用户该用户名已经存在,与预期结果一致。

3.1.3 测试场景 3:密码与确认密码不一致
-
预期结果:系统应该提示用户检查确认密码是否输入一致。
-
实际结果:系统确实给出了相应的提示,指示用户检查确认密码,与预期结果一致。

3.1.4 测试场景 4:注册成功
-
预期结果:系统应该显示注册成功,并跳转回登录界面。
-
实际结果:系统确实显示了注册成功,并且跳转回了登录界面,符合预期。


3.2 登录页面测试

3.2.1 测试场景 1:用户名和密码正确
-
预期结果:系统应该显示登录成功,并跳转到论坛首页。
-
实际结果:系统确实显示了登录成功,并且跳转到了论坛首页,与预期结果一致。


3.2.2 测试场景 2:用户名正确,密码错误
-
预期结果:系统应该显示登录失败,并给出相应的错误提示。
-
实际结果:系统确实显示了登录失败,并给出了错误提示,符合预期。

3.2.3 测试场景 3:用户名不存在
-
预期结果:系统应该显示登录失败,并给出相应的错误提示。
-
实际结果:系统确实显示了登录失败,并给出了错误提示,符合预期。

3.3 首页测试

3.3.1 测试场景 1:未登录或登录过期
-
预期结果:系统应该自动跳转回登录界面,要求用户重新登录。
-
实际结果:系统确实执行了跳转回登录界面的操作,与预期一致。

3.3.2 测试场景 2:登录状态下点击“首页”按钮
-
预期结果:应该显示导航栏中的所有版块名称,下方应显示所有帖子列表,并且右上方应该显示登录用户的信息。
-
实际结果:系统确实展示了导航栏中的所有版块名称,下方显示了所有帖子列表,并且右上方显示了登录用户的信息,与预期一致。

3.4 编辑界面测试
3.4.1 测试场景 1:未登录状态下尝试进入编辑页面
-
预期结果:系统应该自动跳转回登录界面,要求用户重新登录。
-
实际结果:系统确实执行了跳转回登录界面的操作,与预期一致。

3.4.2 测试场景 2:登录状态下发布帖子时不输入帖子标题
-
预期结果:系统应该给出提示,要求用户输入帖子标题。
-
实际结果:系统确实给出了提示,要求用户输入帖子标题,与预期一致。

3.4.3 测试场景 3:登录状态下发布帖子时不输入帖子内容
-
预期结果:系统应该给出提示,要求用户输入帖子内容。
-
实际结果:系统确实给出了提示,要求用户输入帖子内容,与预期一致。

3.4.4 测试场景 4:登录状态下输入了帖子标题和帖子内容,然后点击发布按钮
-
预期结果:系统应该成功编辑帖子,并跳转回首页,最上方应该显示刚发布的帖子信息。
-
实际结果:系统确实执行了编辑成功的操作,跳转回了首页,并在最上方显示了刚发布的帖子信息,与预期一致。

3.5 帖子详情页面测试
3.5.1 测试场景 1:未登录或者登录过期的状态下,点击首页中的任意一条帖子内容
-
预期结果:系统应该自动跳转回登录界面,要求用户重新登录。
-
实际结果:系统确实执行了跳转回登录界面的操作,与预期一致。

3.5.2 测试场景 2:登录状态下,点击首页中的一条帖子内容–作者和登录用户不一样
-
预期结果:系统应该跳转到该帖子的详情页面。
-
实际结果:系统确实跳转到了该帖子的详情页面。

3.5.3 测试场景 3:登录状态下,点击首页中的一条帖子内容–作者和当前登录用户一样
-
预期结果:系统应该跳转到该帖子的详情页面,最上方应该显示该帖子的信息,左侧应该显示帖子作者的信息,下方应该显示点赞按钮、删除按钮和编辑按钮。
-
实际结果:系统没有展示了预期的内容,包括帖子信息、作者信息、帖子内容以及点赞按钮、删除按钮和编辑按钮,与预期一致。
、
等等一系列功能的手动测试实践
四、自动化测试实现
整体设计如下

4.1导入pom.xml依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>ForumAutoTest</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>io.github.bonigarcia</groupId><artifactId>webdrivermanager</artifactId><version>5.8.0</version></dependency><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.0.0</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency></dependencies><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties></project>
这次没有用到Junit单元测试方法,用的都是平常常见依赖
4.2 Utils类
package common;import io.github.bonigarcia.wdm.WebDriverManager;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;/*** Created with IntelliJ IDEA.* Description:自动化测试论坛系统公共方法*/public class Utils {public static WebDriver driver;public static WebDriver createDriver(){if(driver == null){WebDriverManager.chromedriver().setup();ChromeOptions options = new ChromeOptions();//允许访问所有链接options.addArguments("--remote-allow-origins=*");driver = new ChromeDriver(options);//等待driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));}return driver;}public Utils(String url) {//调用driver对象driver = createDriver();//访问urldriver.get(url);//窗口最大化driver.manage().window().maximize();}//屏幕截图public void getScreenShot(String str) throws IOException, IOException {// ./src/test/image/// /2024-07-17/// /test01-17453010.png// /2024-07-18/// /test01-17453030.png//屏幕截图SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");SimpleDateFormat sim2 = new SimpleDateFormat("HHmmssSS");String dirTime = sim1.format(System.currentTimeMillis());String fileTime = sim2.format(System.currentTimeMillis());//./src/test/image/2025-xx-xx/test01-17453020.pngString filename ="./src/test/image/"+ dirTime +"/" + str + "-" + fileTime+".png";File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);//srcFile放到指定位置FileUtils.copyFile(srcFile,new File(filename));}}
常见的浏览器驱动和屏幕快照
4.3注册页面功能测试 RegisterPageTest.java
package Test;import common.Utils;
import org.openqa.selenium.By;import java.io.IOException;/*** Created with IntelliJ IDEA.* Description:自动化测试论坛系统注册页面* Author: WJW*/
public class RegisterPageTest extends Utils {public static String url = "http://127.0.0.1:9580/sign-up.html";public RegisterPageTest() {super(url);}public void RegisterPageRight() {//论坛logo图标driver.findElement(By.cssSelector("body > div > div > div.text-center.mb-4 > img"));//用户注册driver.findElement(By.cssSelector("#signUpForm > div > h2"));}//注册成功public void RegisterSuc() throws InterruptedException {//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("橘子004");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("橘子树0");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();Thread.sleep(1000);//校验注册是否成功并返回登录页面String title = driver.getTitle();assert title.equals("比特论坛 - 用户登录");}//注册失败01--该用户已存在public void RegisterFai01() throws IOException {//在登录页面点击注册按钮// driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.text-center.text-muted.mt-3 > a")).click();//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("1");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("1");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String fail01 = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();//对当前异常进行截图getScreenShot(getClass().getName());//断言assert fail01.equals("警告");}//注册失败02--用户名为空public void RegisterFai02() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名 当前用户名为空driver.findElement(By.cssSelector("#username"));//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("1");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String fail02 = driver.findElement(By.cssSelector("#signUpForm > div > div:nth-child(2) > div")).getText();//对当前异常进行截图getScreenShot(getClass().getName());//断言assert fail02.equals("用户名不能为空");}//注册失败03--昵称为空public void RegisterFai03() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("1");//输入昵称 当前昵称为空driver.findElement(By.cssSelector("#nickname"));//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String fail03 = driver.findElement(By.cssSelector("#signUpForm > div > div:nth-child(3) > div")).getText();//截图保存当前异常getScreenShot(getClass().getName());//断言assert fail03.equals("昵称不能为空");}//注册失败04--密码与确认密码不一致public void RegisterFai04() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("101");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("111");;//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("13");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String fail04 = driver.findElement(By.cssSelector("#signUpForm > div > div:nth-child(5) > div > div")).getText();getScreenShot(getClass().getName());assert fail04.equals("请检查确认密码");}//注册失败05--未点击同意使用条款和隐私服务public void RegisterFai05() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("101");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("111");;//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//未点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy"));//点击注册driver.findElement(By.cssSelector("#submit")).click();//截图保存当前异常getScreenShot(getClass().getName());}}
4.4登录页面功能测试 LoginPageTest.java
package Test;import common.Utils;
import org.openqa.selenium.By;import java.io.IOException;/*** Created with IntelliJ IDEA.* Description:自动化测试论坛系统登录页面*/
public class LoginPageTest extends Utils {public static String url = "http://127.0.0.1:9580/sign-in.html";public LoginPageTest() {super(url);}//通过查看页面元素是否存在来检查页面加载成功与否public void loginPageRight(){//论坛logo图标driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.text-center.mb-4 > img"));//用户登录driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2"));}//检查登录功能public void LoginSuc(){//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("xiaoweng");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("0123");//点击登录按钮driver.findElement(By.cssSelector("#submit")).click();//检查点击登录是否成功//通过查看比特论坛logo是否登录成功driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > h1 > a > img"));//通过查看发布帖子是否登录成功driver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post"));//通过页面标题来检查是否成功String title = driver.getTitle();assert title.equals("比特论坛");//返回登录页面// driver.navigate().back();//刷新页面// driver.navigate().refresh();}//检查登录失败01--密码错误public void LoginFail01() throws IOException {//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("aaa");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123456");//点击登录按钮driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String res01 = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div>h2")).getText();//截图保存测试结果验证警告提示内容是否与预期一致getScreenShot(getClass().getName());assert res01.equals("警告");//通过刷新保证输入框没有文本driver.navigate().refresh();}//检查登录失败02--用户名为空public void LoginFail02() throws IOException {//输入用户名driver.findElement(By.cssSelector("#username"));//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123456");//点击登录按钮driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String res02 = driver.findElement(By.cssSelector("#signInForm > div.mb-3 > div")).getText();//截图保存测试结果验证警告提示内容是否与预期一致getScreenShot(getClass().getName());assert res02.equals("用户名不能为空");//通过刷新保证输入框没有文本driver.navigate().refresh();}//检查登录失败03--密码为空public void LoginFail03() throws IOException {//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("swhdf");//输入密码driver.findElement(By.cssSelector("#password"));//点击登录按钮driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String res03 = driver.findElement(By.cssSelector("#signInForm > div.mb-2 > div > div")).getText();//截图保存测试结果验证警告提示内容是否与预期一致getScreenShot(getClass().getName());assert res03.equals("密码不能为空");//通过刷新保证输入框没有文本driver.navigate().refresh();}}
4.5 不登入页面功能测试 PageByNoLogin.java
package Test;import common.Utils;public class PageByNoLogin extends Utils {public static String listurl = "http://127.0.0.1:9580/index.html";public PageByNoLogin() {super(listurl);}public void ListPageByNoLogin() throws InterruptedException {// driver.get(listurl);//直接返回登录界面Thread.sleep(1000);String title = driver.getTitle();assert title.equals("比特论坛 - 用户登录");}
}
4.6 总测试用例 RunTests.java
import common.Utils;
import Test.ListPageTest;
import Test.LoginPageTest;
import Test.PageByNoLogin;
import Test.RegisterPageTest;import java.io.IOException;/*** Created with IntelliJ IDEA.* Description:论坛系统自动化测试* Author: HY* Date: 2025-03-02* Time: 21:16*/
public class RunTests {public static void main(String[] args) throws IOException, InterruptedException {//未登录页面测试PageByNoLogin pageByNoLogin = new PageByNoLogin();pageByNoLogin.ListPageByNoLogin();RegisterPageTest register = new RegisterPageTest();
// //测试注册页面是否加载成功register.RegisterPageRight();
// //注册成功register.RegisterSuc();//注册失败register.RegisterFai01();register.RegisterFai02();register.RegisterFai03();register.RegisterFai04();register.RegisterFai05();LoginPageTest login = new LoginPageTest();//测试登录页面是否加载成功login.loginPageRight();//登录失败login.LoginFail01();login.LoginFail02();login.LoginFail03();// 登录成功login.LoginSuc();ListPageTest list = new ListPageTest();//测试列表页面是否加载成功list.ListByLoging();//测试站内信息回复成功list.MessageSuc();//测试站内信息回复失败list.MessageFail();//成功发布帖子list.PublishPostSuc();//发布帖子失败list.PublishPostFail();//显示个人帖子list.ShowPost();// 点赞list.LickCount();/*//编辑成功list.EditSuc();//编辑失败list.EditFail();//删除成功list.DeleteSuc();//删除失败list.DeleteFail();*///回复成功list.RepleSuc();//回复失败list.RepleFail();//个人中心list.PersonalCenter();//个人中心修改失败list.PersonalCenterModifyFail01();list.PersonalCenterModifyFail02();list.PersonalCenterModifyFail03();//个人中心修改成功list.PersonalCenterModifySuc();//退出list.Exit();//释放driver对象Utils.driver.quit();}
}
五、常见错误Exception in thread "main" org.openqa.selenium.ElementClickInterceptedException: element click intercepted: Element is not clickable at point
常见的很多都是一些基础的写法,有一部分地方当我们直接使用
类似于
driver.findElement(By.cssSelector("#setting_submit_email")).click();
这样的写法时,我们会发现,如果这个提交或者修改按钮不在你打开的这个页面当中时,我们会发现一个
Exception in thread "main" org.openqa.selenium.ElementClickInterceptedException: element click intercepted: Element is not clickable at point
这样的一个报错,我所作的修改是类似于
// 定位提交按钮WebElement submitButton = driver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > div:nth-child(14) > div > div > form > div.form-footer>button"));((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center', inline: 'nearest'});",submitButton);// 添加短暂等待确保滚动完成Thread.sleep(1000);WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));wait.until(ExpectedConditions.elementToBeClickable(submitButton)).click();
这样的写法,显示等待并用js去定位我们的按钮,当然,很重要的一点,你在自己将页面滑下去的时候,它会停留在你定位按钮的位置,接下来当然要把它在返回上去
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, 0);");
这是我在编写我的测试时遇到的一个比较常见且应该记住的一个错误
测试完整版视频可见我主页视频资源内
论坛测试
相关文章:
《基于Selenium的论坛系统自动化测试实战报告》
一、项目背景与技术选型 项目简介 目标系统:论坛系统 核心功能:用户注册/登录、会话框发送信息、好友列表、信息发送 技术栈:html Springboot MySQL数据库 为什么选择Selenium 支持多浏览器兼容性测试(Chrome/Firefox/Edge&…...
深入解析SQL Server高级SQL技巧
SQL Server 是一种功能强大的关系型数据库管理系统,广泛应用于各种数据驱动的应用程序中。在开发过程中,掌握一些高级SQL技巧,不仅能提高查询性能,还能优化开发效率。这篇文章将全面深入地探讨SQL Server中的一些高级技巧…...
分布式中间件:环境准备
在当今数字化的时代,分布式系统已经成为了开发领域的主流。分布式中间件在其中扮演着至关重要的角色,它能够帮助我们更好地处理高并发、高可用等复杂的业务场景。在这个系列的博客中,我将带大家深入学习分布式中间件的相关知识,主…...
c# winform程序 vs2022 打包生成安装包
最近,利用c# winform程序该客户开发一套进销存管理系统,项目在部署前,需要生成安装包,以便部署在客户电脑上面。总结步骤如下: 1、在打包之前 (VS中需要包括Microsoft visual studio installer projects扩展项目)&…...
探索Elasticsearch:文档的CRUD
在企业环境中,Elasticsearch对文档操作的支持不仅是实现高效搜索的关键,更是数据驱动决策的重要支柱。它通过强大的索引机制和灵活的查询语言,使企业能够实时处理和分析海量文档数据,迅速获取有价值的洞察,从而加速创新…...
面试基础--Spring Boot启动流程及源码实现
深度解析Spring Boot启动流程及源码实现 一、Spring Boot启动全景图(含核心阶段) #mermaid-svg-dYTQ6WPa3o6vKFHh {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-dYTQ6WPa3o6vKFHh .error-i…...
火语言RPA--PDF提取图片
【组件功能】:提取PDF文档指定位置图片 配置预览 配置说明 文件路径 支持T或# 默认FLOW输入项 待提取图片的PDF文件的完整路径。 提取位置 全部、指定页、指定范围3种位置供选择。 PDF文件密码 支持T或# 打开PDF文件的密码。 页码 支持T或# 提取指定页的页…...
力扣977.有序数组的平方(双指针)
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。 方法一:直接将每个元素的平方压入ans数组中,再对ans数组进行排序 class Solution { public:vector<int> sort…...
QT——文件IO
QFile 类 构造函数 QFile() 无参构造 仅仅构建一个QFile 对象,不设定文件名 QFile(文件名) 构建一个QFile对象的同时,设定文件名 但是注意,仅仅设定文件名,并不会打开该文件 设定文件名 QFile file file.setFileName…...
分布式中间件:Redis介绍
目录 Redis 概述 Redis 的特点 高性能 丰富的数据结构 持久化 分布式特性 简单易用 Redis 的数据结构 字符串(String) 哈希(Hash) 列表(List) 集合(Set) 有序集合&…...
服务器和本地电脑之间如何传输文件
在服务器和本地电脑之间传输文件可以通过多种方式实现,常见的方法包括使用 SFTP(安全文件传输协议)、SCP(安全复制协议)、FTP(文件传输协议)、rsync、以及 云存储 等工具。以下是几种常见的方法…...
经验分享:用一张表解决并发冲突!数据库事务锁的核心实现逻辑
背景 对于一些内部使用的管理系统来说,可能没有引入Redis,又想基于现有的基础设施处理并发问题,而数据库是每个应用都避不开的基础设施之一,因此分享个我曾经维护过的一个系统中,使用数据库表来实现事务锁的方式。 之…...
嵌入式学习前要了解的基础知识
一、电压和电流 在嵌入式开发中,电压和电流是两个基本的电气概念,对于理解和设计电子电路至关重要。它们直接影响到嵌入式系统的性能、功耗、可靠性和安全性。 电压(Voltage) 电压是电场力推动电荷移动的能力,通常以…...
RTC、直播、点播技术对比|腾讯云/即构/声网如何选型 — 2025 版
前言 作为一个有多年实战经验的开发者,在音视频技术领域我深刻体会到 RTC(实时通信)、直播和点播三者的不同。虽然它们的核心都涉及音视频内容的传输,但在实际应用中,它们的技术实现、使用场景以及所面临的挑战各不相…...
《白帽子讲 Web 安全》之文件操作安全
目录 引言 (一)文件上传与下载漏洞概述 1.文件上传的常见安全隐患 1.1前端校验的脆弱性与服务端脚本执行危机在文件上传流程中,部分开发者可能会在前端使用 JavaScript 代码对文件后缀名进行简单校验,试图以此阻止非法文件上传…...
yolov8训练模型、测试视频
yolov8先训练生成best.pt文件,用这个生成的模型进行视频的测试 因为本来用的代码生成的测试视频打不开,格式应该是损坏了,或者部分帧没有正常保存吧。 修改了一下代码,现状可以正常打开生成的视频了。 1、训练代码train.py im…...
03.网络编程套接字(二)
文章目录 简单的TCP网络程序 服务端创建套接字 服务端绑定 服务端监听 服务端获取连接 服务端处理请求 客户端创建套接字 客户端发起请求 服务器测试 单执行流服务器的弊端 多进程版的TCP网络程序 线程池版的TCP网络程序 简单的TCP网络程序 服务端创建套接字 我…...
一周学会Flask3 Python Web开发-Flask3之表单处理WTForms安装与定义WTForms表单类
锋哥原创的Flask3 Python Web开发 Flask3视频教程: 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 我们平时开发项目,都会用到表单,编写表单,提交表单,验证表单,如果…...
Git基本命令索引
GIT基本命令索引 创建代码库修改和提交代码日志管理远程操作操作分支 创建代码库 操作指令初始化仓库git init克隆远程仓库git clone 修改和提交代码 操作指令查看文件状态git status文件暂存git add文件比较git diff文件提交git commit回滚版本git reset重命名或者移动工作…...
【论文阅读笔记】SL-YOLO(2025/1/13) | 小目标检测 | HEPAN、C2fDCB轻量化模块
目录 摘要 1 引言 2 相关工作 3 方法 3.1 为小目标检测增加一个头 3.2 优化网络结构 3.3 改进轻量化模块 3.3.1 C2fDCB 3.3.2 SCDown 4 实验 4.1 数据集 4.2 实验环境 4.3 与其他模型的比较 4.4 消融研究 ▲不同网络结构的分析 ▲不同模块的分析 ▲不同降采样…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
