Python自动化测试:web自动化测试——selenium API、unittest框架的使用

web自动化测试2

  • 1. 设计用例的方法——selenium API
    • 1.1 基本元素定位
      • 1)定位单个唯一元素
      • 2)定位一组元素
      • 3)定位多窗口/多框架
      • 4)定位连续层级
      • 5)定位下拉框
      • 6)定位div框
    • 1.2 基本操作
    • 1.3 等待
    • 1.4 浏览器操作
    • 1.5 鼠标事件
    • 1.6 键盘事件
    • 1.7 弹窗处理
    • 1.8 上传文件操作
  • 2. unittest介绍
  • 3. unittest 框架的使用示例
    • 1)测试固件的编写
    • 2)单元测试用例——多场景设计测试用例
      • 测试数据导入
      • 跳过某用例
      • 测试用例断言
      • 测试结果截图
    • 3)测试套件组合与执行
      • 套件组合-借助装载器:defaultTestLoader、TestLoader
      • 套件组合-借助addTest函数
      • 套件组合-借助makeSuit
      • 套件执行-借助TextTestRunner
    • 4)测试报告输出

前言:使用Selenium框架进行简单web端UI自动化测试,简单的以百度搜索为例,复杂的模拟访问12306登陆、购票操作。

1. 设计用例的方法——selenium API

1.1 基本元素定位

web端-浏览器右键-检查,可以查看各个元素的id、class、name、text、XPath等,需要唯一才可精准定位
在这里插入图片描述

适用selenium 4.6以上语法如下:

1)定位单个唯一元素

  • driver.find_element(By.XPATH,‘XPATH’)——XPath路径如上图获取,是唯一的;
  • driver.find_element(By.CLASS_NAME,‘CLASS_NAME’)——用Class名称查找;
  • driver.find_element(By.CSS_SELECTOR,‘CSS_SELECTOR’)——用CSS选择器查找;
  • driver.find_element(By.ID,‘ID’)——用ID查找;
  • driver.find_element(By.LINK_TEXT,‘LINK_TEXT’)——用永超链接查找;
  • driver.find_element(By.PARTIAL_LINK_TEXT,‘PARTIAL_LINK_TEXT’)——用部分超链接查找;
  • driver.find_element(By.TAG_NAME,‘TAG_NAME’)——用标签名查找;

2)定位一组元素

  • switch_to.frame("框架’')——定位到页面所有input框;
inputs=driver.find_elements(By.TAG_NAME, "input")
for input in inputs:
    # 遍历定位到的input,若元素为单选框,则点击选中
   if input.get_attribute('type')=='checkbox':
      input.click()

3)定位多窗口/多框架

  • switch_to.frame("框架id’')——定位到某层级内的框架;
  • switch_to.default_content()——返回默认/最外层界面;
    举例:
    在这里插入图片描述
import switch as switch

#转换层级
driver.switch_to.frame("f1")
driver.switch_to.frame("f2")
#要想从f2回到f1,要先回到默认界面
driver.switch_to.default_content()
driver.switch_to.frame("f1")

4)定位连续层级

备注:若要定位的元素需要进行一系列操作才展示,那需要我们一层层去定位;

driver.find_element(By.ID, "元素ID").find_element(By.ID, "下一层级才能看到的元素ID")

5)定位下拉框

在这里插入图片描述

元素类型为:< option value=“1”>一月< /option>
定位并选择十月份:
方法1:option[value]

#定位到下拉框,注意elements的复数形式
options = driver.find_element(By.CLASS_NAME,"整个日历月份下拉框class名").find_elements(By.TAG_NAME, "option")
for option in options:
    if option.get_attribute('value') == '10':
        option.click()
# 第二种方法option[10].click

6)定位div框

备注:若页面元素太多,利用元素无法精准定位,可以先定位到某div框,在从该div框里去定位:

先定位到DIV1这个模块,在对模块上的元素进行操作
div1=driver.find_element(By.CLASS_NAME, "class名")
div1.find_element(By.ID, "ID").click()
#如果这个模块上多个button,还可以使用这样的方法
div1=driver.find_element(By.CLASS_NAME, "class名")
buttons=div1.find_element(By.ID, "ID")
button[0].click()

1.2 基本操作

(1)点击按钮:.click()
举例:
在这里插入图片描述

# 通过元素ID 定位到“百度一下”的按钮,点击“百度一下”
driver = webdriver.Chrome()
driver.get('http://www.baidu.com/')
driver.find_element(By.ID, "su").click()

(2)模拟写入对象/元素的内容:.send_keys(“xxxx”)
举例:百度-搜索框输入“孙俪”-点击“百度一下”
在这里插入图片描述

driver.find_element(By.ID, "kw").clear()
driver.find_element(By.ID, "kw").send_keys("孙俪")
driver.find_element(By.ID, "su").click()

(3)模拟清空元素/对象的内容:.clear()

(4)提交表单:.submit()
备注:要求元素为表单类型才可使用
在这里插入图片描述
举例:也可通过表单方式提交.submit() == .click() == 点击“百度一下”

(5)用于获取元素的文本信息:.text ()

text=driver.find_element(By.XPATH,'//*[@id="s-top-left"]/a[1]').text
print(text)

(6)获取输入框元素内容/值:.get_attribute(‘value’)

driver.find_element(By.ID,"kw").send_keys("selenium")
qq=driver.find_element(By.ID,'kw').get_attribute('value')
print(qq)

结果:打印 输入框的值-输出 selenium

1.3 等待

(1)强制等待:time.sleep(2)——休眠2s
(2)智能等待:driver.implicitly_wait(5) ——智能等待最长5s

import time
from selenium import webdriver
driver = webdriver.Firefox()
driver.implicitly_wait(5)
time.sleep(2)

1.4 浏览器操作

(1)浏览器最大化:driver.maximize_window()
(2)设置浏览器高、宽:driver.set_window_size(500,500)
(3)浏览器后退:driver.back()
(4)浏览器前进:driver.forward()
(5)浏览器滚动条置顶与置底:(借助执行JS语句,如下示例所示)

import time
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Firefox()
driver.get('http://www.baidu.com/')
driver.maximize_window()
#设置浏览器窗口为(500,500)
driver.set_window_size(500,500)
time.sleep(1)
#设置浏览器窗口最大化
driver.maximize_window()
driver.implicitly_wait(2)
driver.find_element(By.ID,"kw").send_keys("selenium")
driver.find_element(By.ID,"su").click()
driver.implicitly_wait(3)
#将页面滚动条拖到底部
js = "var q=document.documentElement.scrollTop=10000"
driver.execute_script(js)
time.sleep(3)
#将页面滚动条拖到顶部
jjs="var q=document.documentElement.scrollTop=0"
driver.execute_script(jjs)
time.sleep(3)

1.5 鼠标事件

from selenium.webdriver.common.action_chains import ActionChains
(1)context_click() 右击
(2)double_click() 双击
(3)drag_and_drop() 拖动
(4)move_to_element() 移动

  • ActionChains(driver)
    生成用户的行为。所有的行动都存储在actionchains 对象。通过perform()存储的行为。
  • move_to_element(menu)
    移动鼠标到一个元素中,menu 上面已经定义了他所指向的哪一个元素
  • perform()
    执行所有存储的行为
qq=driver.find_element(By.ID,"kw")
ActionChains(driver).context_click(qq).perform() #右键
ActionChains(driver).double_click(qq).perform() #双击

1.6 键盘事件

from selenium.webdriver import Keys
(1)快捷回车-enter键:.send_keys(Keys.ENTER) 等价于点击按钮

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import Keys
driver = webdriver.Firefox()
driver.get('http://www.baidu.com/')
driver.maximize_window()
driver.find_element(By.ID, "kw").clear()
driver.find_element(By.ID, "kw").send_keys("孙俪")
driver.find_element(By.ID, "su").send_keys(Keys.ENTER)

(2)切换焦点-Tab键:.send_keys(Keys.TAB)
作用:将元素定位位置由当前元素切换至下一个元素
在这里插入图片描述
(3)输入框内容-全选与剪切-组合键:全选、剪切、复制、粘贴

#ctrl+a 全选输入框内容
send_keys(Keys.CONTROL,'a')
#ctrl+x 剪切输入框内容
send_keys(Keys.CONTROL,'x')
#ctrl+c 复制输入框内容
.send_keys(Keys.CONTROL,'c')
#ctrl+v 粘贴输入框内容
.send_keys(Keys.CONTROL,'v')

(4)输入空格:.send_keys(Keys.SPACE)
(5)单个删除:.send_keys(Keys.BACK_SPACE)

1.7 弹窗处理

(1)Alert弹窗:只有信息及确认按钮
(2)Confirm弹窗:在Alert弹窗基础上增加了取消按钮
(3)Prompt类型弹框:在Confirm的基础上增加了可输入文本内容的功能

driver.switch_to.alert.accept() #确定、同意;三种弹窗都可使用
driver.switch_to.alert.dismiss() #取消、不同意;confirm和prompt弹窗中使用
title = driver.switch_to.alert.text #打印弹窗信息
alert = driver.switch_to.alert #获取alert对象
alert.send_keys() #Prompt弹窗中输入内容

1.8 上传文件操作

driver.find_element(By.CLASS_NAME, "class名").send_keys("文件路径")

2. unittest介绍

  • unittest是Python自带的一个单元测试框架, 它可以做单元测试,提供了去创建测试用例的方法,并能用于编写和运行重复的测试工作;
  • 可以利用unittest创建一个类,该类集成unittest的TestCase,其中每个case作为一个最小单元,由测试容器组织起来,统一执行并引入测试报告输出结果;
  1. test fixture:初始化与清理测试环境。如创建临时的数据库、文件/目录,其中如setUp()用于启动浏览器驱动、setDown()用于关闭游览器驱动等统一操作;
  2. test case:单元测试用例,在类TestCase中设计编写测试用例;
  3. test suite:单元测试用例集合,将不同的测试用例封装至类TestSuite中; test runner:执行单元测试用例;
  4. test report:生成测试报告
    在这里插入图片描述

3. unittest 框架的使用示例

  • 前置:资源导入
import csv #用于解析data数据
import sys #用于访问本地资源路径
from selenium import webdriver
import time
import os  #用于输出
import unittest   #用于使用unittest资源
from ddt import ddt, data, file_data, unpack  #用于data数据读取与输入操作
from unittest import TestLoader   #用于输出测试报告

1)测试固件的编写

  • 每个测试用例都需要包含测试固件:包含基本的setUp()、tearDown()等统一操作;
    def setUp(self):
        print("------setUp")
        self.driver=webdriver.Firefox()
        self.url="https://www.baidu.com"
        self.driver.maximize_window()
        time.sleep(3)

    def tearDown(self):
        print("-------tearDown")
        self.driver.quit()

2)单元测试用例——多场景设计测试用例

  • 单元测试:可以是同一个场景设计多个测试用例;

示例:该单元测试场景——模拟每次进入百度首页-点击进入不同标签页面

from selenium import webdriver
import os
import time
import unittest

class Test1(unittest.TestCase):
    #绑定浏览器驱动,设置url
    def setUp(self):
        print("-----setUp")
        self.driver=webdriver.Firefox()
        self.url="https://www.baidu.com"
        self.driver.maximize_window()
        time.sleep(3)

    #测试用例执行结束进行清理,关闭浏览器驱动
    def tearDown(self):
        print("-----tearDown")
        self.driver.quit()

     #编写测试用例 def test_xxx:
    def test_baidu1(self):
        driver=self.driver
        url=self.url
        driver.get(url)
        driver.find_element_by_link_text("hao123").click()
        time.sleep(2)

    def test_baidu2(self):
        driver=self.driver
        url=self.url
        driver.get(url)
        driver.find_element_by_link_text("图片").click()
        time.sleep(2)

    def test_baidu3(self):
        driver=self.driver
        url=self.url
        driver.get(url)
        driver.find_element_by_link_text("地图").click()
        time.sleep(3)

    if __name__ == "__main__":
        unittest.main()

示例:该单元测试场景——模拟百度搜索功能(对于不同数据类型)

测试数据导入

@data(不带的列表)会将整个列表作为参数传入
@data(带的列表)会将整个列表的子元素作为参数逐个传入,可将二维列表的元素逐个传入,一个元素一个case
@unpack 将要传入的元素解包后传入,将二维列表的元素逐个传入,便于一个测试用例中使用一组数据中的多个不同变量;

首先需要了解数据导入的方法:
在这里插入图片描述
备注:数据导入可以选择txt文件、json文件格式、或直接导入数据数组;其中dataTest.py为某单元测试文件;

1)读取txt文件

  • 需要引入data数据包-并要设置读取方法;
def getTxT(file_name):
    rows = []
    path = sys.path[0]
    with open(path + '/data/' + file_name, 'rt',encoding='UTF-8') as f:
        readers = csv.reader(f, delimiter=',', quotechar='|')
        next(readers, None)
        for row in readers:
            temprow = []
            for i in row:
                temprow.append(i)
            rows.append(temprow)
        return rows
  • 给该单元测试的类和某测试用例设置@ddt与@data修饰器
@data(*getTxT("baidu_data.txt"))

2)读取json文件

  • 格式如下:
[
  "hao123",
  "图片",
  "地图"
]

3)直接在某用例上输入数组

  • 格式如下:
@data(["hao123", "hao123"], [u"视频", u"视频_百度搜索"])

跳过某用例

想跳过某单元用例中的某用例,则添加如下代码至某用例方法上即可:

@unittest.skip("skipping")  #表示跳过该测试用例

测试用例断言

unittest单元测试框架提供了一整套内置的断言方法:
1)如果断言失败,抛出AssertionError的错误,case为失败状态
2)如果断言成功,会标识case为成功状态

方法检查描述
assertEqual(a, b)a == b验证a是否等于b
assertNotEqual(a, b)a != b验证a是否不等于b
assertTrue(x)bool(x) is True验证x是否为ture
assertFalse(x)bool(x) is False验证x是否为flase
assertIs(a, b)a is b验证a,b是否为同一个对象
assertIsNot(a, b)a is not b验证a,b不是同一个对象
assertIsNone(x)x is None验证x是否是None
assertIsNotNone(x)x is not None验证x是否非None
assertIn(a, b)a in b验证a是否是b的子串
assertNotIn(a, b)a not in b验证a是否非b的子串
assertIsInstance(a, b)isinstance(a, b)验证a是否是b的实例
assertNotIsInstance(a, b)not isinstance(a, b)验证a是否不是b的实例

举例:百度搜索某字段,判断标题是否一致,不一致则断言失败,打印结果:标题不相等!

    @data(["hao123", "hao123"], [u"视频", u"视频_百度搜索"])
    def test_baidu7(self, value, title):
        driver = self.driver
        url = self.url
        driver.get(url)
        driver.find_element_by_id("kw").send_keys(value)
        driver.find_element_by_id("su").submit()
        time.sleep(5)
        print(driver.title)
        self.assertEqual(title, driver.title, msg="标题不相等!")

测试结果截图

可以设置保存截图的方法,根据断言结果调用截图方法并保存截图:
1)设置截图保存方法

    def savescreenshot(self, driver, file_name):
        if not os.path.exists('./image'):
            os.makedirs('./image')

        now = time.strftime("%Y%m%d-%H%M%S", time.localtime(time.time()))
        # 截图保存
        driver.get_screenshot_as_file('./image/' + now + '-' + file_name)
        time.sleep(1)

2)根据断言抛出异常,调用截图方法

    def test_baidu4(self):
        driver=self.driver
        url=self.url
        driver.get(url)
        driver.find_element_by_id("kw").clear()
        driver.find_element_by_id("kw").send_keys("孙俪")
        driver.find_element_by_id("su").click()
        time.sleep(3)
        print(driver.title)
        try:
            self.assertEqual("孙俪_百度搜索", driver.title, msg=None)
            self.assertNotEqual("孙俪_百度搜索",driver.title,msg=None)
        except:
            self.savescreenshot(driver,"sunli.png")

3)截图:百度搜索“孙俪”
结果保存至项目文件的/image文件夹中
在这里插入图片描述

3)测试套件组合与执行

套件组合-借助装载器:defaultTestLoader、TestLoader

将单元测试文件中的某类测试用例塞入测试套件中,创建一个测试用例组合套件的方法:

def createSuit():
    # 添加不同测试用例到套件里
    testSuit=unittest.defaultTestLoader.discover("../py2Unittest",pattern="test*.py",top_level_dir=None)
    return testSuit

注:此方法可以把一个文件夹下面所有的满足test*.py命名规则的测试脚本中的测试用例放入测试套件

套件组合-借助addTest函数

可以将某单元测试文件中的某个用例塞入测试套件中:
注:这样放需要在当前测试套件脚本中引入此处的单元测试脚本,否则addTest()会报错

import test1
import test2

def creatSuit():
    #要把不同的测试脚本的类中的需要执行的方法放在一个测试套件中
    suit = unittest.TestSuite()
    suit.addTest(test1.Test1("test_baidu1")) # test_baidu1为某测试用例方法的名称
    suit.addTest(test2.Test2("test_baidu3"))
    return suit

套件组合-借助makeSuit

利用makeSuit不需要导入单元测试用例文件

def creatSuit():
   #如果我需要把一个测试脚本中所有的测试用例都添加到suit中-实际将整个单元测试脚本中的类都加入套件中实现
   # makeSuit
   suit = unittest.TestSuite()
   suit.addTest(unittest.makeSuite(test1.Test1))
   suit.addTest(unittest.makeSuite(test2.Test2))
   return suit

套件执行-借助TextTestRunner

举例:
将测试套件执行并打印测试结果:

import unittest
from unittest import TestLoader

def creatSuit():
    #TestLoader
    suit1 = unittest.TestLoader().loadTestsFromTestCase(test1.Test1)
    suit2 = unittest.TestLoader().loadTestsFromTestCase(test2.Test2)
    suit = unittest.TestSuite([suit1, suit2])
    return suit

if __name__ == "__main__":
    suit = creatSuit()
    # verbersity= 0, 1, 2
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suit)

注:unittest.TextTestRunner的verbosity参数用于控制测试运行时的详细程度。它可以接受的值如下:
0: 静默模式,不输出任何信息。
1: 默认模式,输出每个测试方法的简要摘要和总体摘要(通过、失败、错误等)。
2: 详细模式,输出每个测试方法的详细执行结果,包括测试方法的名称、运行时间、状态等信息。

4)测试报告输出

测试套件&执行&测试报告输出脚本程序入口的设置:
if name ==“main”:
1.设置测试结果文件输出路径
2.设置结果文件名
3.创建并打开文件,执行测试套件,写入测试结果,保存文件

举例:
单元测试脚本:

import csv
import sys
# -*- coding: utf-8 -*-
from selenium import webdriver
import os
import time
import unittest
from ddt import ddt, data, file_data, unpack
from selenium.webdriver.common.by import By

def getTxT(file_name):
    rows = []
    path = sys.path[0]
    with open(path + '/data/' + file_name, 'rt',encoding='UTF-8') as f:
        readers = csv.reader(f, delimiter=',', quotechar='|')
        next(readers, None)
        for row in readers:
            temprow = []
            for i in row:
                temprow.append(i)
            rows.append(temprow)
        return rows

@ddt
class Test4(unittest.TestCase):
    # 绑定浏览器驱动,设置url
    def setUp(self):
        print("-----setUp")
        self.driver = webdriver.Firefox()
        self.url = "https://www.baidu.com"
        self.driver.maximize_window()
        time.sleep(3)

    # 测试用例执行结束进行清理,关闭浏览器驱动
    def tearDown(self):
        print("-----tearDown")
        self.driver.quit()

    # @unittest.skip("skipping")  # 注释表示跳过该测试用例
    @file_data("data_baidu.json")
    def test_baidu6(self, value):
        driver = self.driver
        url = self.url
        driver.get(url)
        driver.find_element(By.LINK_TEXT,value).click()
        time.sleep(3)

    # @unittest.skip("skipping")
    @unpack
    @data(*getTxT("baidu_data.txt"))
    # @data(["hao123", "hao123"], [u"视频", u"视频_百度搜索"])
    def test_baidu7(self, value, title):
        driver = self.driver
        url = self.url
        driver.get(url)
        driver.find_element(By.ID,"kw").send_keys(value)
        driver.find_element(By.ID,"su").submit()
        time.sleep(5)
        print(driver.title)
        self.assertEqual(title, driver.title, msg="标题不相等!")

套件组合与执行&报告输出脚本:

import HTMLTestRunner  # 基于html文件的测试执行与报告输出资源模块
import os
import sys
import time
import unittest

def createSuit():
    # 添加不同测试用例到套件里
    testSuit=unittest.defaultTestLoader.discover("../py2Unittest",pattern="dataTest.py",top_level_dir=None)
    return testSuit

if __name__ =="__main__":
    if not os.path.exists("./result"):
        os.makedirs("./result")

    now = time.strftime("%Y%m%d-%H%M%S",time.localtime(time.time()))
    print(now)

    fileName="./result/"+now+"result.html"

    with open(fileName, "w") as fp:
        runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title=u"测试报告", description=u"测试用例执行情况",verbosity=2)
        suit = createSuit()
        runner.run(suit)

若文件读写时 with open(fileName, “wb”) as fp:可能会报错
在这里插入图片描述
不要慌,可以查看文件读取与写入规则,主要是使用write函数时报错,检查open函数,发现参数写为‘wb’,即按二进制write,所以后面出现TypeError: a bytes-like object is required, not 'str’的报错,将此次的参数修改为w后,可以按照字符串输入,编译通过,write的结果正确(w+具有读写属性,写的时候如果文件存在,会被清空,从头开始写)

结果截图:
在这里插入图片描述
测试报告:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第三十七篇——麦克斯韦的妖:为什么要保持系统的开放性?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 如果没有详细的学习这篇文章&#xff0c;我觉得我就是被麦克斯韦妖摆弄的…

[OtterCTF 2018]Closure

既然你从内存中提取了密码&#xff0c;你能解密rick的文件吗&#xff1f; 密码是知道了&#xff0c;加密文件 &#xff1f; flag 文件&#xff1f;dump 出来 已知这个勒索软件为HiddenTear&#xff0c;直接在网上找到解密程序HiddenTearDecrypter先将加密文件的末尾多余的0去掉…

memory动态内存管理学习之weak_ptr

此头文件是动态内存管理库的一部分。std::weak_ptr 是一种智能指针&#xff0c;它持有对被 std::shared_ptr 管理的对象的非拥有性&#xff08;“弱”&#xff09;引用。在访问所引用的对象前必须先转换为 std::shared_ptr。std::weak_ptr 用来表达临时所有权的概念&#xff1a…

力扣SQL50 判断三角形 case when then end

Problem: 610. 判断三角形 Code select x,y,z,case when x y > z and x z > y and y z > x then Yeselse Noend as triangle from triangle;

Linux shell编程学习笔记59: ps 获取系统进程信息,类似于Windows系统中的tasklist 命令

0 前言 系统进程信息是电脑网络信息安全检查中的一块重要内容&#xff0c;对于使用Linux和基于Linux作为操作系统的电脑来说&#xff0c;可以使用ps命令。 1 ps命令 的功能、格式和选项说明 1.1 ps命令 的功能 Linux 中的ps&#xff08;意为&#xff1a;process status&…

<电力行业> - 《第8课:输电(一)》

1 输电环节的意义 电能的传输&#xff0c;是电力系统整体功能的重要组成环节。发电厂与电力负荷中心通常都位于不同地区。在水力、煤炭等一次能源资源条件适宜的地点建立发电厂&#xff0c;通过输电可以将电能输送到远离发电厂的负荷中心&#xff0c;使电能的开发和利用超越地…

firewalld(2)安装、配置文件、规则查询

安装firewalld 我使用的操作系统是debian 12,并没有安装firewalld。 通过apt install firewalld安装firewalld firewalld 本身是一个服务(firewalld.service),可以通过 systemctl 进行启动、停止和重启,而iptables 本身并不是一个服务,而是一个用户空间工具,被用来配置底…

使用SpringBoot整合Listener

常用的Web事件的监听接口如下&#xff1a; ServletContextListener&#xff1a;用于监听Web的启动及关闭 ServletContextAttributeListener&#xff1a;用于监听ServletContext范围内属性的改变 ServletRequestListener&#xff1a;用于监听用户请求 ServletRequestAttributeLi…

Rocketmq-集群部署(Master-Slave)

使用中间件版本:rocketmq-4.5.2环境介绍及角色划分 这里采用俩台机器做集群的搭建&#xff0c;172.0.0.1 以及 172.0.0.2 服务器172.0.0.1 做为a-master与b-slave。 服务器172.0.0.2 做为b-master与a-slave。 配置讲解图(主要说明区分点) 配置rocketmq环境变量&#xff0c;这里…

steam社区加载异常、加载失败、无法加载、黑屏的解决方法

随着steam夏季特卖的临近&#xff0c;最近几天开启史低折扣的大作已经越来越少了&#xff0c;不过也并不是没有。最经典的知名大作文明6之前已经打到1折的骨折价了&#xff0c;没想到也能背刺&#xff0c;现在是新史低价0.5折11元&#xff0c;很多玩家入手后纷纷前往社区看新手…

spring mvc实现自定义验证器Validator

使用场景 在接口开发的日常实践中&#xff0c;确保数据准确性是保障业务稳定性的关键一环。面对诸如登录时验证用户名密码非空、创建用户时检查邮箱和手机号格式的正确性等需求&#xff0c;手动编写校验逻辑不仅耗时费力&#xff0c;还会显著降低代码的可读性和维护性。鉴于网…

搭建大型分布式服务(四十三)SpringBoot 无代码侵入实现多Kafka数据源发布到Maven中央仓库:让世界看到你的作品!

系列文章目录 文章目录 系列文章目录前言一、大概步骤二、完整教程三、参考文章 前言 在软件开发的世界里&#xff0c;分享和协作是推动技术进步的重要力量。当你开发了一个优秀的SpringBoot插件&#xff0c;并希望将其分享给全世界的开发者使用时&#xff0c;将插件发布到Mav…

在IDEA中创建Maven项目

2023版IDEA创建Maven项目&#xff08;新版&#xff09; 1.打开IDEA&#xff0c;点击 文件 -> 新建 -> 项目 2.创建Maven项目 3.编写java文件并运行 在src -> java -> 创建一个java文件并运行 如果出现下图 解决办法&#xff1a; 2022版IDEA创建Maven项目&#xf…

Leetcode[反转链表]

LCR 024. 反转链表 给定单链表的头节点 head &#xff0c;请反转链表&#xff0c;并返回反转后的链表的头节点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1]示…

JVM专题八:JVM如何判断可回收对象

在JVM专题七&#xff1a;JVM垃圾回收机制中提到JVM的垃圾回收机制是一个自动化的后台进程&#xff0c;它通过周期性地检查和回收不可达的对象&#xff08;垃圾&#xff09;&#xff0c;帮助管理内存资源&#xff0c;确保应用程序的高效运行。今天就让我们来看看JVM到底是怎么定…

基于QT开发的气体成分检测数据记录软件

1、软件概述 气体成分检测数据记录软件用于实现多种气体分析仪及相关设备实时数据的获取、存储和传送。目前支持的设备主要有气体分析仪、多通道进样阀箱、冷阱处理系统和气体采样处理系统。   气体成分检测数据记录软件可以根据实际应用需要进行配置&#xff0c;以实现不同应…

制造企业用AI可以做什么?

ChatGPT横空出世&#xff0c;有关AI的浪潮席卷全球&#xff0c;比起人工智能如何改变世界&#xff0c;可能你更感兴趣我能用AI可以做的事情是什么&#xff1f; 制造企业用AI可以做的事情是什么?人工智能在制造企业中可以做很多事情&#xff0c;以下是一些主要的应用&#xff1…

【Nginx】源码安装

nginx官网&#xff1a;nginx: download 选择文档版本安装即可 1.安装依赖包 //一键安装上面四个依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel 2.下载并解压安装包 //创建一个文件夹 cd /usr/local mkdir nginx cd nginx //将下载的nginx压缩…

Linux(Ubuntu20.04)系统中安装deb软件包错误(依赖关系问题-仍未被配置)解决的办法

在Ubuntu16.04下采用如下dpkg命令安装deb软件安装包时&#xff1a; sudo dpkg -i XXXX.deb 发生安装失败&#xff0c;返回信息为&#xff02;正处理时有错误发生&#xff02;&#xff0c;并且在安装过程中出现&#xff02;依赖关系问题-仍未被配置&#xff02;的提示&#xff0…

240629_昇思学习打卡-Day11-Vision Transformer中的self-Attention

240629_昇思学习打卡-Day11-Transformer中的self-Attention 根据昇思课程顺序来看呢&#xff0c;今儿应该看Vision Transformer图像分类这里了&#xff0c;但是大概看了一下官方api&#xff0c;发现我还是太笨了&#xff0c;看不太明白。正巧昨天学SSD的时候不是参考了太阳花的…