PostMan、LoadRunner进行并发压测流程

需求

两个记账接口在同一时间大量处理同一账户账务时,锁表顺序不同导致死锁,在修改完代码后模拟生产记账流程进行测试,需要对两个接口进行并发测试。
在进行压测的时候,需要对流水号进行递增。

PostMan处理流程

1. 新建Collections

在这里插入图片描述

2. 设置全局变量

在这里插入图片描述

3. 新建要测试的接口api

在这里插入图片描述

在这里插入图片描述

4. 在Pre-request Script中设置相关规则

使用JavaScript语言进行脚本编写

在这里插入图片描述

//postman.getGlobalVariable获取定义的全局变量
//postman.setGlobalVariable设置定义的全局变量// 将流水号加1
var seqno = Number(postman.getGlobalVariable("Seq1240"));
seqno = seqno + 1postman.setGlobalVariable("Seq1240",seqno);// 使用日期+交易码+流水号的方式避免流水号重复
var golseqno = String(String(postman.getGlobalVariable("TranDate")) + seqno);
postman.setGlobalVariable("GolSeqNo",golseqno);

5. 处理请求报文

在这里插入图片描述

6. 使用Runner进行测试

在这里插入图片描述
在这里插入图片描述

点击POST链接 查看请求和返回的信息。
在这里插入图片描述

查询数据库查看测试结果
在这里插入图片描述

感觉PostMan的并发都是每组两个接口成功返回后再进行下一次迭代,不能满足测试需求,所以学一下如何使用LoadRunner进行测试。
以下陆续更新LoadRunner学习测试的过程。

LoadRunner处理流程

【性能测试工具完整版教学—LoadRunner篇】
https://www.bilibili.com/video/BV1fY4y1N7oG/?p=33&share_source=copy_web&vd_source=9aea609762c29c24f00ebffa4e482266

视频全长10个小时左右,二倍速观看加整理笔记和进行验证,需要20~30个小时吧

1. 安装本体

在这里插入图片描述

点击开始安装
在这里插入图片描述

选择解压目录
在这里插入图片描述

组件安装
在这里插入图片描述

组件安装完成后,选择安装目录,然后进行软甲安装
在这里插入图片描述

去掉勾选
在这里插入图片描述

安装完成后桌面多了三个快捷方式
在这里插入图片描述

2. 安装语言包

选择语言安装包
在这里插入图片描述

选择LoadRunner安装的路径
在这里插入图片描述

如图所示找到目录及对应的文件
在这里插入图片描述

双击安装文件
在这里插入图片描述

打开选择语言文件夹,选择要安装的语言。本处依次打开如下文件【Chinese-Simplified】→【LoadRunner】→【LR_03457】,点击【LR_03457】将进行安装
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

语言包安装完成

3. 使用VUGEN来编写脚本以及VUGEN软件的简介

首先我们需要知道loadrunner安装完成后,这三个图标分别的作用是什么
在这里插入图片描述

Virtual User Generator 是用来编写和管理测试脚本的。
Controller 是用来创建和控制运行性能测试的场景的。
Analysis 主要是用来对运行结果的分析的分析软件。

3.1 新建解决方案和脚本

在这里插入图片描述

脚本名称:1240
解决方案名称:1240yace
单协议:Web - HTTP/HTML
多协议及可选择多种协议,在编写脚本时可以使用多种协议
在这里插入图片描述

新建完毕后会有红框中对应的几个文件
在这里插入图片描述
其中vuser_init、Action、vuser_end文件都是以.c结尾,额外文件是头文件,包含了需要使用的.h文件,这也表示我们可以使用c语言的语法来编写脚本。

3.2 运行时设置设置

在这里插入图片描述

运行逻辑
在这里插入图片描述
运行逻辑中,随着迭代数的增加,Run 的运行次数会跟着迭代数一起增加(即会多次执行Action),而 vuser_init、vuser_end的运行次数不会增加,并且只会运行一次,我们也可以在Run中再加入Action1、Action2,Run运行多次的时候,对应的Action、Action1、Action2也会运行多次。

节奏
在这里插入图片描述
设置迭代之间的时间间隔,其中Fixed选项也可以选择Random,然后的秒数选择一个区间段,标志在这个区间段内随机触发。

日志
在这里插入图片描述
勾选 启用日志记录,默认为标准日志,如果脚本中带有参数等,建议使用扩展日志,将参数替换和服务器返回数据勾选,这样可以查询到更详细的信息。

思考时间
在这里插入图片描述
我在脚本里没有使用,暂略

其他属性
在这里插入图片描述
我在脚本里没有使用,暂略

其他
在这里插入图片描述
这里面的内容没有进行变更,使用默认设置进行测试即可。

浏览器仿真
在这里插入图片描述
用户代理选择即用户使用的浏览器标识。

速度模拟
在这里插入图片描述
默认使用最大带宽,如果有需要再进行调整。

首选项
在这里插入图片描述
启用图像和文本检查允许Vuser通过执行验证函数web_find或web_image_check来执行验证检查。仅适用于在基于HTML的模式下录制的步骤。启用此选项会增加您的脚本的内存占用。

内容检查、代理服务器、下载筛选器、链配置略。

3.3 参数列表

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

参数列表的名称要与代码中的参数名对应。
使用文件映射参数时,需要看一下列选择顺序个分隔符,以及选择下一行的模式。

设置完成后我们开始进行脚本的编写

3.4 编写脚本

在这里插入图片描述
编写脚本之前我们先来熟悉一下常用的函数

标C的函数

字符串操作函数
strcat、strncat 拼接
strcmp、strncmp 比较
strcpy、strncpy 拷贝
strlen 长度
strlwr、strupr 大小写转换
strset 填充
strstr 查找字符串出现的位置缓冲区操作函数
memchr 搜索某个字符 
memcmp 比较
memcpy 拷贝
memmove 移动
memset 初始化 一定要记住如果要把一个char a[20]清零,一定是 memset(a,0,20*sizeof(char));过程控制函数
getenv 获取环境变量
putenv 设置环境变量
system 执行系统命令内存分配函数
calloc 
free
malloc
realloc 数学函数
标准输入输出函数
文件操作函数
日期时间函数
数据类型转换函数

LR的一些常见函数


命令行解析函数
lr_get_attrib_double
lr_get_attrib_long
lr_get_attrib_string数据库操作函数
lr_db_connect
lr_db_disconnect
lr_db_executeSQLStatment
lr_db_dataset_action
lr_db_getvalue信息函数
lr_end_timer Stops a timer.
lr_get_host_name Returns the name of the host executing the script. 
lr_get_master_host_name Returns the name of the machine running the LoadRunner Controller .
lr_get_vuser_ip Returns the IP address of the current Vuser. Not applicable for products that do not run Vusers.
lr_start_timer Starts a timer.
lr_user_data_point Records a user-defined data sample. 
lr_user_data_point_ex Records a user-defined data sample and enables logging option.
lr_user_data_point_instance Records a user-defined data sample and correlates it to a transaction instance.
lr_user_data_point_instance_ex Records a user-defined data sample and enables logging option.
lr_whoami  消息函数
lr_debug_message  Sends a debug message to the LoadRunner output window or Application Management agent log file.  
lr_error_message  Sends an error message to the LoadRunner output window or Application Management agent log file.  
lr_get_debug_message  Returns the current message logging settings.  
lr_log_message  Sends a message to the Vuser log file.  
lr_message  Sends a message to the log file and output window.  
lr_output_message  Sends a Vuser message to the log file and output window with location information.  
lr_remove_custom_error_message  Removes a custom text that was set by lr_set_custom_error_message. 
lr_set_debug_message  Sets a message class for output messages.  
lr_set_custom_error_message  Sets a custom text to be output after built-in error messages. 
lr_vuser_status_message  Sends a message to the Vuser status area in the LoadRunner Controller.  字符串函数
lr_advance_param  Advances to the next available value in the parameter data file.  
lr_checkpoint  Validates the value of a parameter against an expected value (checkpoint).  
lr_convert_double_to_double  Formats the string representation of a double value using a printf-style format specifier. 
lr_convert_double_to_integer  Converts the string representation of a double value to the string representation of an integer. 
lr_convert_string_encoding  Converts a string to a different encoding.  
lr_decrypt  Decrypts an encoded string.  
lr_eval_string  Returns the string argument after evaluating embedded parameters.  
lr_eval_string_ext  Creates a buffer and assigns it the input string after evaluating embedded parameters.  
lr_eval_string_ext_free  Frees the buffer allocated by lr_eval_string_ext.  
lr_free_parameter  Deletes a dynamic parameter at run-time and frees its buffer.  
lr_next_row  Advances to the next row in the parameter data file.  
lr_param_increment  Increments the value of a LoadRunner parameter.  
lr_param_sprintf  Writes formatted output to a parameter.  
lr_param_unique  Generates a unique string and assigns it to a parameter.  
lr_paramarr_idx  Returns the value of the parameter at a specified location in a parameter array.  
lr_paramarr_len  Returns the number of elements in a parameter array.  
lr_paramarr_random  Returns the value of the parameter at a random location in a parameter array  
lr_save_datetime  Saves the date and time into a parameter.  
lr_save_param_regexp  Finds a string in a buffer using a regular expression and saves capture group matches to a parameter. 
lr_save_int  Saves an integer to a parameter.  
lr_save_searched_string  Searches for an occurrence of a string in a buffer and saves a portion of the buffer after that string to a parameter.  
lr_save_string  Saves a null terminated string as a parameter.  
lr_save_timestamp  Saves the current time in a parameter. 
lr_save_var  Saves a variable length string as a parameter.  
lr_unzip  Uncompresses the information in a parameter and stores the uncompressed information in another parameter. 
lr_zip  Compresses the information in a parameter and stores the compressed information in another parameter. 事务函数
int lr_start_transaction( const char *transaction_name ); 事务开始
int lr_end_transaction( const char *transaction_name, int status) ; 事务结束

web的一些函数

int web_set_max_html_param_len( const char *length);web_utl()
请求网页,HTTP的GET请求
查看函数时,点击函数名称按F1则会跳转到函数帮助页面
int web_url( const char *StepName, const char *url, <List of Attributes>, [EXTRARES, <List of Resource Attributes>,] LAST );
例子:
web_url("www.abc.com",
"URL=http://www.abc.com/",
"TargetFrame=", 
"TargetBrowser=Mercury Technologies",
"Resource=0",
"RecContentType=text/html",
"Snapshot=t1.inf",
"Mode=HTML",
LAST );
LAST 参数列表结尾的标记int web_custom_request( const char *RequestName, <List of Attributes>, [EXTRARES, <List of Resource Attributes>,] LAST);
In the following recorded script, the user began recording from http://lazarus/html/forms/file.html. When the user submitted his request, VuGen inserted a web_add_header function, followed by a web_custom_request function.
web_url("file.html", "URL=http://lazarus/html/forms/file.html","TargetFrame=_TOP", LAST );
例子:
web_add_header("Content–Type",
"multipart/form–data; boundary=–––––––––––––––––––––––––––292742461228954");
web_custom_request("post_query.exe", "Method=POST",
"URL=http://lazarus/cgi–bin/post_query.exe",
"Body=–––––––––––––––––––––––––––––292742461228954\r\nContent–Disp"
"osition: form–data; name=\"entry\"\r\n\r\nText\r\n––––––––––"
"–––––––––––––––––––292742461228954\r\nContent–Disposition: f"
"–––––––––––292742461228954––\r\n",
"TargetFrame=",
LAST );

vuser_init.c

char recv_data[3000];
char data1[40000];vuser_init()
{return 0;
}

Action.c

/*****************************************************************
脚本编写信息描述:1240-一借一贷记账
项目名称:核心业务系统
版 本 号:V1.0
交易路径:LR -> 核心
编码语言:C
参数数据: 
开发协议:HTTP/HTML
作    者:UntifA
时    间:2024年1月11日08:43:01
历史修改记录:*****************************************************************/#include "lr_replace_string.h"Action()
{/*	定义char data[40000] 会报错 Too many local variables 原因其实是因为Action能分配的内存不多,所以若要直接使用占用内存大的变量,则建议将其定义成全局变量,或者是在Action里面使用malloc函数来进行分配*/char *data = (char *)malloc(40000); // 报文内容char *recv_data = (char *)malloc(40000); // 相应报文内容char *recv_message = (char *)malloc(40000); // 返回信息char Trace_ID[50] = {0}; // 全局流水char prcscd[100]; // transcation_id// 字符集编码转码结果int rc = 0;/*lr_eval_string()函数的主要作用:返回脚本中的一个参数当前的值(从参数中取得对应的值,并且转换为一个字符串)。格式:lr_eval_string("{参数名}");例如:lr_eval_string("{parm}");返回值类型:char由于返回值类型是char类型,所以可以直接使用lr_output_message(lr_eval_string("{parm}"))函数输出到日志中。如:lr_output_message(lr_eval_string("{parm}"));lr_save_string 函数主要是将程序中的常量或变量保存为lr中的参数char *tmp="hello";lr_save_string("192.168.10.35","ip"); //将常量保存为参数iplr_save_string(tmp,"miao");     //将变量tmp保存为参数miao*/strcpy( Trace_ID,lr_eval_string("UntifA{date}{time}{rand}") );lr_output_message("查看一下流水号-----------> Trace_ID [%s]\n ", Trace_ID);lr_save_string(Trace_ID,"gloseqno");lr_output_message("查看一下流水号-----------> {gloseqno} [%s]\n ", lr_eval_string("{gloseqno}"));// 组装请求报文:strcpy(data,lr_eval_string("{																						""\"Body\":{""\"AppHead\":{""\"jiaoyigy\":\"{jiaoyigy}\",""\"jiaoyirq\":\"{date}\",""\"jiaoyijg\":\"{jiaoyijg}\",""},""\"zrzhhumc\": \"{zrzhhumc}\",""\"zczhhumc\": \"{zczhhumc}\"""},""\"Head\":{""\"ReqTm\":\"{time}\",""\"ReqSeqNo\":\"{gloseqno}\",""\"GloSeqNo\":\"{gloseqno}\",""\"ScnNo\":\"01\"""}"
"}"));lr_output_message("查看一下报文-----------> data [%s]\n ", data);lr_convert_string_encoding(data, LR_ENC_SYSTEM_LOCALE, LR_ENC_UTF8, "request_data");// 替换报文内容结尾的^@符号,即ASCII码中的0lr_replace_string("request_data","%x00","");//	lr_save_string(data,"request_data");lr_output_message("查看一下报文-----------> request_data [%s]\n ", lr_eval_string("{request_data}"));// 报文进行转码//	rc = lr_convert_string_encoding(data, LR_ENC_SYSTEM_LOCALE, LR_ENC_UTF8, "stringInUnicode");//	if(rc < 0)//	//	{//		//	} else {//		lr_output_message("stringInUnicode ------> %s \n", lr_eval_string("{stringInUnicode}"));//	}//报文最大长度web_set_max_html_param_len("4096");// 组装报文头web_add_header("Content-Type","application/json");web_add_header("appKey","admin");web_add_header("appSecret","sunline");/*注册将与正则表达式匹配的动态数据保存到参数的请求。int web_reg_save_param_regexp(“ParamName= <输出参数名称>”,“RegExp = regular_expression”,[<属性列表>,] [<SEARCH FILTERS>,] LAST);参数说明:ParamName:要创建的参数的名称。RegExp:PERL兼容的正则表达式,包括一个用于从响应或响应中提取的带括号的子字符串。请参阅正则表达式。List of Attributes:有关每个属性的详细信息,请参阅保存参数注册函数的属性。属性值字符串(例如,“NotFound = warning”)不区分大小写。SEARCH FILTERS:搜索过滤器,指定缓冲区的部分以搜索字符串。请参阅搜索过滤器以保存参数注册函数。LAST:指示参数列表结束的标记。*/
//	web_reg_save_param_regexp(
//		"ParamName=recv_data",
//		"RegExp=",
//		"NotFound=warning",
//		"Group=0",
//		SEARCH_FILTERS,
//		"Scope=ALL",
//		"IgnoreRedirections=No",
//		LAST);// 正则表达式没用成功,改用web_reg_save_param_ex函数功能	
//	web_reg_save_param_regexp("ParamName=recv_data","RegExp=\\(*)\\","Group=0","Notfound=warning",LAST);
//	web_reg_save_param_regexp("ParamName=recv_message","RegExp=RspMsg\":\"","Group=0","Notfound=warning",LAST);
//	web_reg_save_param_regexp("ParamName=recv_code","RegExp=RspCd\":\"","Group=0","Notfound=warning",LAST);// 获取返回报文web_reg_save_param_ex("ParamName=recv_data","LB=","RB=",SEARCH_FILTERS,LAST);// 获取返回信息web_reg_save_param_ex("ParamName=recv_message","LB=RspMsg\":\"","RB=\"",SEARCH_FILTERS,LAST);// 获取响应码web_reg_save_param_ex("ParamName=recv_code","LB=RspCd\":\"","RB=\"",SEARCH_FILTERS,LAST);// 设置集合点lr_rendezvous("1240yjyd_jihe");strcpy(prcscd, "1240_yjyd");// 开启事务lr_start_transaction(prcscd);web_custom_request("untifa","URL=http://xxx.xxx.xxx.xxx:xxxx/1240","Method=POST","body={request_data}",LAST);strcpy( recv_data,lr_eval_string("{recv_data}") );strcpy( recv_message,lr_eval_string("{recv_message}") );lr_convert_string_encoding(recv_data, LR_ENC_UTF8,LR_ENC_SYSTEM_LOCALE, "recv_data_conv");lr_convert_string_encoding(recv_message, LR_ENC_UTF8,LR_ENC_SYSTEM_LOCALE, "recv_message_conv");lr_output_message("响应报文:\n %s", lr_eval_string("{recv_data_conv}"));if(strcmp(lr_eval_string("{recv_code}"),"CBS0000000000000")== 0){// 结束事务lr_end_transaction(prcscd,LR_PASS);} else {// 结束事务lr_end_transaction(prcscd,LR_FAIL);lr_error_message("返回的响应码:%s",lr_eval_string("{recv_code}"));lr_error_message("返回的错误信息是:%s",lr_eval_string("{recv_message_conv}"));}return 0;
}
*/

vuser_end

vuser_end()
{return 0;
}

globalsh.h

#ifndef _GLOBALS_H
#define _GLOBALS_H//--------------------------------------------------------------------
// Include Files
#include "lrun.h"
#include "web_api.h"
#include "lrw_custom_body.h"//--------------------------------------------------------------------
// Global Variables#endif // _GLOBALS_H

lr_replace_string.h

// ----------------------------------------------------------------------------
//
// 方法描述:
//    在一个字符串中查找并替换一个字符串。
//
// 参数说明:
//    src - 源字符串
//    from - 源字符串中需要被替换的字符串
//    to - 用于替换的字符串
//
// 返回说明:
//		返回一个指向动态内存的包含被"to"替换成"from"后的字符串。
//
// 注释:
//		不要直接使用这个脚本,除非你是一个懂得C语言和字符串处理的高级用户。
//		如想使用,请使用下方的lr_replace_string行数即可。
//
// ----------------------------------------------------------------------------
char *replaceString(const char *src, const char *from, const char *to){char *value;char *dst;char *match;int size;int fromlen;int tolen;// 分别获取源字符串,需要被替换的字符串,用于替换的字符串的长度。size = strlen(src) + 1;fromlen = strlen(from);tolen = strlen(to);// 分配第一块足够大小的原始字符串空间。value = (char *)malloc(size);//由于需要返回"value",所以这里需要做一个副本。dst = value;// 开始之前,判断内存分配是否成功。if ( value != NULL ){// 一直循环直到没有找到匹配项。for ( ;; ){// 搜索from在src中第一次出现时的字符串。match = (char *) strstr(src, from);if ( match != NULL ){// 找出有多少个字符需要复制到'match'中。size_t count = match - src;// 由于需要重新分配内存,因此需要定义一个安全的临时变量。char *temp;// 计算被字符串被替换后总的字符串长度。size += tolen - fromlen;// 为新字符串重新分配内存。// temp = realloc(value, size);temp = (char *)realloc(value, size);if ( temp == NULL ){// 如果内存分配失败,那么就释放之前分配的内存并返回NULL。free(value);return NULL;}// 如果内存分配成功,但是我们最终会返回'value',因此需要将它指向// 现在内存地址。并且不要忘记指向正确的目的地地址。dst = temp + (dst - value);value = temp;// 从src拷贝count个字符到dest。memmove(dst, src, count);src += count;dst += count;// 从to拷贝tolen个字符到dst。memmove(dst, to, tolen);src += fromlen;dst += tolen;}else{	// 如果没有匹配的字符串strcpy(dst, src);		// 复制该字符串中剩余的部分(包括终止空字符)。break;}}}return value;
}// ----------------------------------------------------------------------------
//
// 方法描述:
//		在一个LoadRunner字符串中查找并替换一个字符串。
//
// 参数说明:
//    lrparam    - LoadRunner源字符串参数名称
//    findstr    - LoadRunner源字符串中需要被替换的字符串
//    replacestr - LoadRunner用于替换的字符串
//
// 返回说明:
//		返回一个整数: 1表示成功,0表示失败。
//
// 示例说明:
//    lr_save_string( "welcome to china!", "LR_Parameter");
//    lr_replace_string( "LR_Parameter", "o", "-h-" );
//    lr_output_message( "%s", lr_eval_string("{LR_Parameter}") );
//
// ----------------------------------------------------------------------------
int lr_replace_string( const char *lrparam, char *findstr, char *replacestr ){int res = 0;char *result_str;char lrp[1024];// 格式化LoadRunner参数名称sprintf( lrp, "{%s}", lrparam);// 查找并替换字符串result_str = replaceString( lr_eval_string(lrp), findstr, replacestr );// 结果处理if (result_str != NULL ){lr_save_string( result_str, lrparam );free( result_str );res = 1;}return res;
}// ----------------------------------------------------------------------------
//
//  LoadRunner中调用DEMO
//
//  #include "lr_replace_string.h"
//
//  Action()
//  {
// 		//FilterID是loarunner的参数化数据
//		lr_save_string(lr_eval_string("{FilterID}"),"Filter_ID");
// 		lr_replace_string("Filter_ID","#","%23");
//		lr_output_message("%s", lr_eval_string("{Filter_ID}"));
//
// 		return 0;
//	}
//
// ----------------------------------------------------------------------------

编译、执行查看测试结果,测试通过。
在这里插入图片描述

4. 使用Controller创建、控制运行性能测试

使用Controller时,需要了解的一些定义

手动场景,按照自定义配置进行测试。
面向目标场景,按照需要达到什么目标去配置进行测试。

LoadRunner 脚本,即使用VUGEN来编写的脚本
系统或单元测试 dll文件、jar包等可以用来执行的

Machines(Load Generators)
进行加压的机器

Vusers
虚拟用户

Scheduling
如何加载运行

Monitors
过程监控测试

Goal-oriented
目标场景

Manual
手动场景

工作流程、工作原理
在这里插入图片描述
在这里插入图片描述

新建场景
在这里插入图片描述
在这里插入图片描述
功能依次为:启动、虚拟用户、添加测试组、删除测试组、运行设置、详细信息、查看脚本、虚拟服务
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

计划方式根据场景和组不同,全局计划也跟着改变,可以自行测试一下,很好理解。
不同组可以设置不同的任务,实现不同脚本不同的并发数。

设置好Controller后,保存文件,文件的后缀为.lrs。

运行压测场景,由于流水号随机号设置了0~100 导致有重复的流水号,所以有失败事务,后续需要改成唯一值或者将随机数的范围扩大。
在这里插入图片描述

5. 使用Analysis进行运行结果分析

通常由Controller跳转进行Analysis软件的打开

这种方式打开不加载运行结果
在这里插入图片描述

在这里插入图片描述

勾选自动加载分析后,Controller运行完毕后会自动打开分析软件。
如果没有勾选,点击下图图标可以打开分析软件
在这里插入图片描述

打开软件,查看压测结果
在这里插入图片描述
在这里插入图片描述

查看数据库压测结果,是否还有死锁交易
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt QComboBox组合框控件

文章目录 1 属性和方法1.1 文本1.2 图标1.3 插入和删除1.4 信号和槽 2 实例2.1 布局2.2 代码实现 Qt中的组合框是集按钮和下拉列表体的控件&#xff0c;&#xff0c;它占用的屏幕空间很小&#xff0c;对应的类是QComboBox 1 属性和方法 QComboBox有很多属性&#xff0c;完整的…

html代码

1、Echart各种图表示例 <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>ECharts 箱线图示例</title> <!-- 引入 ECharts 文件 --> <script src"https://cdn.jsdelivr.net/npm/ech…

CRLF漏洞靶场记录

搭建 利用 docker 搭建 vulhub 靶场 git clone https://github.com/vulhub/vulhub.git 进入 /vulhub/nginx/insecure-configuration 目录 启动前关闭现有的 8080、8081、8082 端口服务&#xff0c;避免端口占用 docker-compose up -d 进入容器 docker exec -it insecure-…

Invalid bound statement(只有调用IService接口这一层会报错的)

问题描述:controller直接调用实现类可以,但是一旦调用IService这个接口这一层就报错. 找遍了大家都说是xml没对应好,但是我确实都可以一路往下跳,真的对应好了.结果发现是 MapperScan写错了,如下才是对的. MapperScan的作用是不需要在mapper上一直写注解了,只要启动类上写好就放…

统一格式,无限创意:高效管理不同格式图片批量转换

在数字时代&#xff0c;图片格式的多样性带来了管理上的不便。为了满足不同的需求&#xff0c;我们经常需要将大量图片转换为统一的格式。那么&#xff0c;有没有一种简单、高效的方法来解决这个问题呢&#xff1f;答案是肯定的&#xff01;今天&#xff0c;我们将为您介绍一款…

档案数字化怎样快速整理资料

对于机构和组织来说&#xff0c;档案数字化是一个重要的信息管理和保护措施。要快速整理资料进行档案数字化&#xff0c;可以遵循以下步骤&#xff1a; 1. 准备工具和设备&#xff1a;确保有一台计算机、扫描仪和相关软件。 2. 分类和组织资料&#xff1a;先将资料分类&#xf…

在CentOS中,对静态HTTP服务的性能监控

在CentOS中&#xff0c;对静态HTTP服务的性能监控和日志管理是确保系统稳定运行和及时发现潜在问题的关键。以下是对这一主题的详细探讨。 性能监控 使用工具监控&#xff1a;top、htop、vmstat、iostat等工具可以用来监控CPU、内存、磁盘I/O等关键性能指标。这些工具可以实时…

8.4V升压14V4A芯片

随着手持设备如智能手机、平板电脑等电子设备的普及&#xff0c;对电池充电技术的要求也越来越高。为了满足这一需求&#xff0c;本文将介绍一款8.4V升压14V4A芯片&#xff0c;采用SOP-8 132*476I-OOO1封装&#xff0c;适用于5V-36V输入&#xff0c;外挂MOS&#xff0c;可为主流…

服务器管理平台开发(2)- 设计数据库表

数据库表设计 本篇文章主要对数据管理平台数据库表设计进行介绍&#xff0c;包括单库多表设计、SQL语句、视图构造等 1、整体设计 设备品牌、序列号、型号等使用业务主表进行记录&#xff0c;逻辑磁盘、PCI设备可能出现1对N的情况&#xff0c;分别使用PCI设备表、Mac地址表、逻…

MySQL数据管理(二)

DML语言 DML &#xff08;数据操作语&#xff09;&#xff1a;用于操作数据库对象中所包含的数据 DML包括&#xff1a; INSERT&#xff08;添加数据语句&#xff09;UPDATE&#xff08;更新数据语句&#xff09;DELETE&#xff08;删除数据语句&#xff09; 一、添加数据 …

密码输入检测 - 华为OD统一考试

OD统一考试(C卷) 分值: 100分 题解: Java / Python / C++ 题目描述 给定用户密码输入流input,输入流中字符 ‘<’ 表示退格,可以清除前一个输入的字符,请你编写程序,输出最终得到的密码字符,并判断密码是否满足如下的密码安全要求。 密码安全要求如下: 密码长度&…

生活自来水厂污水处理设备需要哪些

生活自来水厂是确保我们日常用水质量安全的重要设施。在自来水的生产过程中&#xff0c;污水处理设备是不可或缺的环节。那么&#xff0c;生活自来水厂的污水处理设备都有哪些呢&#xff1f;本文将为您详细介绍。 首先&#xff0c;生活自来水厂的污水处理设备主要包括预处理设备…