当前位置: 首页 > news >正文

数据工厂-生成接口通用用例

章节目录:

    • 一、背景介绍
    • 二、前置准备
    • 三、设计思路
    • 四、代码具体实现
    • 五、执行效果
    • 六、其他说明
    • 七、结束语

一、背景介绍

有哪些用例是可以通用且固定的?

  • 针对之前提到的接口用例设计思路,拆分为三个切入点

在这里插入图片描述

  • 举个例子:
{"field": "value"
}
  • 针对这个字符串类型的入参我们可以设计:
    • 当前数据类型入参(例如:空串,空格字符,特殊字符,字符个数上下限等。)
    • 非当前数据类型入参(例如:整型、浮点类型、布尔类型等。)
    • 特殊值(0、null值等。)

二、前置准备

运行数据工厂的前提条件。

  • java 开发及运行环境。
  • maven 构建工具。
  • 使用到的依赖:
    <dependencies><!--解析 json--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency><!--操作 excel 文件--><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency></dependencies>

三、设计思路

工具类之间是如何交互的。

  • 包层级目录
+---java
|   \---com
|       \---example
|           \---myproject
|               +---boot
|               |       Launcher.java
|               |
|               +---core
|               |       DataFactory.java
|               |
|               +---pojo
|               |       WriteBackData.java
|               |
|               \---util
|                       CaseUtils.java
|                       ExcelUtils.java
|                       FileUtils.java
|                       JsonPathParser.java
|                       JsonUtils.java
|
\---resourcesrequest.jsonTestCase.xls
  • 脚本执行的主流程

在这里插入图片描述

四、代码具体实现

  • Launcher(启动类):
package com.example.myproject.boot;import com.alibaba.fastjson.JSONObject;
import com.example.myproject.core.DataFactory;/*** 执行入口。** @author Jan* @date 2023/08*/
public class Launcher {public static void main(String[] args) throws Exception {// 这里支持传入自定义的用例拓展字段 -> new JSONObject() 。DataFactory.runAndCreateTestCases(null);}
}
  • DataFactory(核心类):
package com.example.myproject.core;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import com.example.myproject.pojo.WriteBackData;
import com.example.myproject.util.*;import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;/*** 数据工厂。** @author Jan* @date 2023/08*/
public class DataFactory {private DataFactory() {}/*** 回写数据的集合。*/private static final List<WriteBackData> WRITE_BACK_DATA = new ArrayList<>();/*** 运行和创建测试用例。** @param ext ext 额外的拓展参数。* @throws Exception 异常。*/public static void runAndCreateTestCases(JSONObject ext) throws Exception {// 获取请求示例。String jsonStr = FileUtils.readSampleRequest();// 解析json的字段数据类型及jsonPath。Set<String> jsonPaths = JsonPathParser.getJsonPaths(jsonStr);for (String jsonPath : jsonPaths) {// 字段数据类型。String filedDataType = JSONPath.read(jsonStr, jsonPath).getClass().getSimpleName();// 跳过复合类型。if ("JSONObject".equals(filedDataType)) {continue;}// 字段名。String[] split = jsonPath.split("\\.");String filedName = split[split.length - 1];// 通过反射生成对应数据类型的测试用例。List<Object> caseValues = DataFactory.getObjectArrayFromReflectType(CaseUtils.class, filedDataType);Map<String, String> caseNameAndRequestValueMap = new HashMap<>();for (Object value : caseValues) {String caseName = CaseUtils.createSpecifyCaseNameByCaseValue(filedName, value);// 修改字段值。JSONObject jsonObject = JsonUtils.checkAndSetJsonPathValue(jsonStr, jsonPath, value);caseNameAndRequestValueMap.put(caseName, jsonObject.toJSONString());}for (Map.Entry<String, String> entry : caseNameAndRequestValueMap.entrySet()) {String caseName = entry.getKey();String requestValue = "";if (null != ext) {// 额外参数。ext.put("title", caseName);ext.put("case", JSON.parseObject(entry.getValue()));requestValue = ext.toJSONString();} else {requestValue = entry.getValue();}WRITE_BACK_DATA.add(new WriteBackData(caseName, requestValue));}}System.out.println("组装完成的用例数为 = " + WRITE_BACK_DATA.size());//开始回写ExcelUtils.initFileAndWriteDataToExcel(WRITE_BACK_DATA);}/*** 通过反射获取用例集合。** @param clazz clazz* @param type  类型* @return {@link List}<{@link Object}>* @throws NoSuchMethodException     没有这样方法异常。* @throws InvocationTargetException 调用目标异常。* @throws InstantiationException    实例化异常。* @throws IllegalAccessException    非法访问异常。*/private static List<Object> getObjectArrayFromReflectType(Class<? extends CaseUtils> clazz, String type) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Object obj = clazz.getConstructor().newInstance();String methodName = "get" + type + "TypeCases";Method method = clazz.getDeclaredMethod(methodName);Object invoke = method.invoke(obj);int length = Array.getLength(invoke);List<Object> caseValues = new ArrayList<>();for (int i = 0; i < length; i++) {caseValues.add(Array.get(invoke, i));}return caseValues;}
}
  • WriteBackData(封装回写信息):
package com.example.myproject.pojo;/*** 回写对象。** @author Jan* @date 2023/08*/
public class WriteBackData {/*** 用例名称。*/private String caseName;/*** 操作步骤。(即用例报文)*/private String step;public WriteBackData(String caseName, String step) {this.caseName = caseName;this.step = step;}public String getCaseName() {return caseName;}public void setCaseName(String caseName) {this.caseName = caseName;}public String getStep() {return step;}public void setStep(String step) {this.step = step;}
}
  • CaseUtils(静态存放用例设计):
package com.example.myproject.util;import java.util.Arrays;
import java.util.Collections;/*** 测试用例。** @author Jan* @date 2023/08*/
public class CaseUtils {private static final String STRING = "string";private static final String INTERFACE = "[接口名]";/*** 字符串类型用例。* 空串、空格字符、特殊字符、整型、精度类型、null值。** @return {@link Object[]}*/public static Object[] getStringTypeCases() {return new Object[]{"", " ", "@", -1, -1.1, "null"};}/*** 整数类型用例。* 字符串类型、特殊值0、负数值、整型较大值、整型边界值、精度类型、null值。** @return {@link Object[]}*/public static Object[] getIntegerTypeCases() {return new Object[]{STRING, 0, -1, 2147483647, 2147483648L, -1.1, "null"};}/*** 长整型用例。* 字符串类型、特殊值0、负数值、精度类型、null值、长整型边界值。** @return {@link Object[]}*/public static Object[] getLongTypeCases() {return new Object[]{STRING, 0, -1, -1.1, "null", 9223372036854775807L};}/*** 浮点类型用例。* 字符串类型、负精度值、负整数值、null值、三位小数。** @return {@link Object[]}*/public static Object[] getBigDecimalTypeCases() {return new Object[]{STRING, -1.1, -1, 0, "null", 999.999D};}/*** 布尔类型用例。* 字符串类型、负精度值、负整数值、特殊值0、null值、真布尔、假布尔。** @return {@link Object[]}*/public static Object[] getBooleanTypeCases() {return new Object[]{STRING, -1, -1.1, 0, "null", true, false};}/*** 集合类型用例。* 字符串类型、负精度值、null值、负整数值、空集合、混合类型。** @return {@link Object[]}*/public static Object[] getJSONArrayTypeCases() {return new Object[]{Collections.singletonList(STRING),Collections.singletonList(-1.1),Collections.singletonList(null),Collections.singletonList(-1),Collections.emptyList(),Arrays.asList(STRING, -1, -1.1)};}/*** 创建指定用例名。** @param baseName 基本名称。* @param value    值。* @return {@link String}*/public static String createSpecifyCaseNameByCaseValue(String baseName, Object value) {String caseName = "";if ("".equals(value)) {caseName = INTERFACE + baseName + "-传空 ".trim();} else if (" ".equals(value)) {caseName = INTERFACE + baseName + "-传空格 ".trim();} else if ("@".equals(value)) {caseName = INTERFACE + baseName + "-传特殊符号\"@\" ".trim();} else if ("null".equals(value)) {caseName = INTERFACE + baseName + "-特殊值null ".trim();} else if (STRING.equals(value)) {caseName = INTERFACE + baseName + "-传字符类型\"string\" ".trim();} else if ("[string]".equals(value)) {caseName = INTERFACE + baseName + "-传字符串值类型集合 ".trim();} else if ("[-1.1]".equals(value)) {caseName = INTERFACE + baseName + "-传精度值类型集合 ".trim();} else if ("[null]".equals(value)) {caseName = INTERFACE + baseName + "-传null值集合 ".trim();} else if ("[-1]".equals(value)) {caseName = INTERFACE + baseName + "-传整型值类型集合 ".trim();} else if ("[]".equals(value)) {caseName = INTERFACE + baseName + "-传空集合 ".trim();} else if ("[string, -1, -1.1]".equals(value)) {caseName = INTERFACE + baseName + "-传混合数据类型集合 ".trim();} else {caseName = INTERFACE + baseName + "-传" + value + " ".trim();}return caseName;}}
  • ExcelUtils(excel 操作):
package com.example.myproject.util;import com.example.myproject.pojo.WriteBackData;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;/*** Excel 操作。** @author Jan* @date 2023/08*/
public class ExcelUtils {private ExcelUtils() {}/*** 写出路径。*/private static final String OUT_PATH = "src/main/resources";/*** 工作表名。*/private static final String SHEET_NAME = "testCase";/*** 用例写入resource目录。** @param writeBackDataList 回写数据列表。*/public static void initFileAndWriteDataToExcel(List<WriteBackData> writeBackDataList) {File filePath = new File(OUT_PATH);FileUtils.initTestCaseFile(filePath);String testCaseFilePath = filePath + File.separator + FileUtils.getFileName();ExcelUtils.writeExcel(writeBackDataList, testCaseFilePath);System.out.println("            ===> 用例写入完成");}/*** 写入。** @param dataList 数据列表。* @param filePath 文件路径。*/private static void writeExcel(List<WriteBackData> dataList, String filePath) {try (XSSFWorkbook workbook = new XSSFWorkbook();OutputStream out = new FileOutputStream(filePath)) {XSSFSheet sheet = workbook.createSheet(SHEET_NAME);// 第一行表头。XSSFRow firstRow = sheet.createRow(0);XSSFCell[] cells = new XSSFCell[3];String[] titles = new String[]{"用例名称","用例编号","操作步骤(生成用例后,记得将\"null\"替换为null,9223372036854775807替换为9223372036854775808)"};// 循环设置表头信息。for (int i = 0; i < 3; i++) {cells[0] = firstRow.createCell(i);cells[0].setCellValue(titles[i]);}// 遍历数据集合,将数据写入 Excel 中。for (int i = 0; i < dataList.size(); i++) {XSSFRow row = sheet.createRow(i + 1);WriteBackData writeBackData = dataList.get(i);//第一列 用例名XSSFCell cell = row.createCell(0);cell.setCellValue(writeBackData.getCaseName());//第二列 用例编号cell = row.createCell(1);cell.setCellValue(i + 1);//第三列 操作步骤cell = row.createCell(2);cell.setCellValue(writeBackData.getStep());}workbook.write(out);} catch (Exception e) {e.printStackTrace();}}
}
  • FileUtils(用例文件操作):
package com.example.myproject.util;import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;/*** 文件操作。** @author Jan* @date 2023/08*/
public class FileUtils {private FileUtils() {}/*** 生成的用例文件名。*/private static final String FILE_NAME = "TestCase.xls";/*** 读取文件流。** @param inputStream 输入流。* @return {@link String}*/public static String readFileStream(InputStream inputStream) {StringBuilder sb = new StringBuilder();try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {String line;while (null != (line = reader.readLine())) {sb.append(line);}} catch (IOException e) {e.printStackTrace();}return sb.toString();}/*** 读取请求示例。** @return {@link String}*/public static String readSampleRequest() {InputStream is = FileUtils.class.getClassLoader().getResourceAsStream("request.json");return FileUtils.readFileStream(is);}/*** 用例文件名称。** @return {@link String}*/public static String getFileName() {return FILE_NAME;}/*** 初始化测试用例文件。** @param filePath 文件路径。*/public static void initTestCaseFile(File filePath) {Path testFilePath = filePath.toPath().resolve(getFileName());try {boolean deleted = Files.deleteIfExists(testFilePath);System.out.println(deleted ? "初始化开始 ===> 旧用例删除成功" : "用例初始化开始 ===> 旧用例删除失败");} catch (NoSuchFileException e) {System.err.println("文件未找到:" + filePath);} catch (IOException e) {System.err.println("删除文件失败:" + e.getMessage());}try {Files.createFile(testFilePath);System.out.println("用例初始化结束 ===> 新用例创建成功");} catch (IOException e) {System.err.println("新用例创建失败:" + e.getMessage());}}
}
  • JsonPathParser(递归解析得到叶子节点的 jsonPath):
package com.example.myproject.util;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.ParserConfig;import java.util.HashSet;
import java.util.Map;
import java.util.Set;/*** 解析 json 得到具体字段的 jsonPath。** @author Jan* @date 2023/08*/
public class JsonPathParser {static {// 设置全局白名单,解析 pb3 中的 @type 类型。ParserConfig.getGlobalInstance().setAutoTypeSupport(true);}private JsonPathParser() {}/*** 得到json路径。** @param jsonStr json str* @return {@link Set}<{@link String}>*/public static Set<String> getJsonPaths(String jsonStr) {// 解析JSON字符串为JSON对象。JSONObject jsonObj = JSON.parseObject(jsonStr);// 存储JSONPath路径的集合。Set<String> jsonPaths = new HashSet<>();// 递归遍历JSON对象的所有字段,并提取出JSONPath路径。parseJsonObj(jsonObj, "$", jsonPaths);return jsonPaths;}/*** 解析 json 对象。** @param jsonObj    json obj。* @param parentPath 父路径。* @param jsonPaths  json路径。*/private static void parseJsonObj(JSONObject jsonObj, String parentPath, Set<String> jsonPaths) {for (Map.Entry<String, Object> entry : jsonObj.entrySet()) {String key = entry.getKey();// 跳过PBv3的类型标识。if (key.contains("@type")) {continue;}Object value = jsonObj.get(key);String currPath = parentPath + "." + key;// 将当前字段的JSONPath路径添加到集合中。jsonPaths.add(currPath);if (value instanceof JSONObject) {// 递归处理嵌套的JSON对象。parseJsonObj((JSONObject) value, currPath, jsonPaths);} else if (value instanceof JSONArray) {// 递归处理嵌套的JSON数组。parseJsonArray((JSONArray) value, currPath, jsonPaths);}}}/*** 解析 json 数组。** @param jsonArray  json数组。* @param parentPath 父路径。* @param jsonPaths  json路径。*/private static void parseJsonArray(JSONArray jsonArray, String parentPath, Set<String> jsonPaths) {for (int i = 0; i < jsonArray.size(); i++) {// 只取集合中第一个元素的字段。if (0 < i) {continue;}Object value = jsonArray.get(i);String currPath = parentPath + "[" + i + "]";if (value instanceof JSONObject) {// 递归处理嵌套的JSON对象。parseJsonObj((JSONObject) value, currPath, jsonPaths);} else if (value instanceof JSONArray) {// 递归处理嵌套的JSON数组。parseJsonArray((JSONArray) value, currPath, jsonPaths);}}}
}
  • JsonUtils(设置用例值):
package com.example.myproject.util;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;/*** 替换字段值。** @author Jan* @date 2023/08*/
public class JsonUtils {private JsonUtils() {}/*** 检查并设置json路径值。** @param json          json。* @param jsonPath      json路径。* @param testCaseValue 测试用例价值。* @return {@link JSONObject}*/public static JSONObject checkAndSetJsonPathValue(String json, String jsonPath, Object testCaseValue) {JSONObject jsonObject = null;try {jsonObject = JSON.parseObject(json);// 还原直接替换值 testCaseValue。JSONPath.set(jsonObject, jsonPath, testCaseValue);} catch (Exception e) {System.err.println("error case:" + jsonPath);}return jsonObject;}
}

五、执行效果

测试一下。

  • 被测 json 串
{"String":"str","Int":1,"Float":0.1,"Long":622337203685477500,"Bool":true,"test":{"Array":[]}
}
  • 运行测试

在这里插入图片描述

  • 生成的最终用例

在这里插入图片描述

六、其他说明

  • 支持 protobuf v3 转换的 json (@type 类型)。
  • 脚本用例生成的优点:
    • 高效率,减少冗余操作。
    • 避免编写出因人为失误导致的错误用例。
    • 方便后期用例迭代。
  • 综上所述,在 json 字段较多的情况下,提效尤为明显。
  • 源码地址:https://gitee.com/Jan7/datafactory

七、结束语


“-------怕什么真理无穷,进一寸有一寸的欢喜。”

微信公众号搜索:饺子泡牛奶

相关文章:

数据工厂-生成接口通用用例

章节目录&#xff1a; 一、背景介绍二、前置准备三、设计思路四、代码具体实现五、执行效果六、其他说明七、结束语 一、背景介绍 有哪些用例是可以通用且固定的&#xff1f; 针对之前提到的接口用例设计思路&#xff0c;拆分为三个切入点&#xff1a; 举个例子&#xff1a; {…...

N 字形变换

N 字形变换 题目: 将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。比如输入字符串为 "PAYPALISHIRING" 行数为 3 时&#xff0c;排列如下&#xff1a;P A H N A P L S I I G Y I R 之后&#xff0c;你的输…...

STM32+RTThread配置以太网无法ping通,无法获取动态ip的问题

记录一个非常蠢的问题&#xff0c;今天在移植rtthread的以太网驱动的时候出现无法获取动态ip的问题&#xff0c;问题如下&#xff1a; 设置为动态ip时不管是连接路由器还是电脑主机都无法ping通&#xff0c;也无法获取dns地址。 设置为静态ip时无法ping通主机。 使用wireshark…...

python编写MQTT订阅程序

Download | Eclipse Mosquitto 1、下载&#xff1a; https://mosquitto.org/files/binary/win64/mosquitto-2.0.17-install-windows-x64.exe 2、安装&#xff1a; 3、conf配置 1)使用notepad打开“C:\Program Files\mosquitto\mosquitto.conf”另存为c:\myapp\msquitto\mo…...

mysql 中 cast 函数用法

在 MySQL 中&#xff0c;CAST() 函数用于将一个表达式转换为指定的数据类型。它可以用于多种场景&#xff0c;例如将字符串转换为数字&#xff0c;或者将日期时间转换为特定格式。 以下是 CAST() 函数的基本语法&#xff1a; CAST(expression AS datatype) 其中&#xff0c…...

MongoDB 的简介

MongoDB 趋势 对于 MongoDB 的认识 Q&A QA什么是 MongoDB&#xff1f; 一个以 JSON 为数据模型的文档数据库一个以 JSON 为数据模型的文档数据库文档来自于“JSON Document”&#xff0c;并非我们一般理解的 PDF&#xff0c;WORD谁开发 MongDB&#xff1f; 上市公司 MongoD…...

是否在业务中使用大语言模型?

ChatGPT取得了巨大的成功&#xff0c;在短短一个月内就获得了1亿用户&#xff0c;并激发了企业和专业人士对如何在他们的组织中利用这一工具的兴趣和好奇心。 但LLM究竟是什么&#xff0c;它们如何使你的企业受益?它只是一种炒作&#xff0c;还是会长期存在? 在这篇文章中我…...

37. 交换字符(第三期模拟笔试)

题目&#xff1a; 给定一个01串&#xff08;仅由字符0和字符1构成的字符串&#xff09;。每次操作可以交换两个相邻的字符。 例如&#xff1a;对于字符串"001110"来说&#xff0c; 可以交换第二个字符0和第三个字符1&#xff0c;交换之后的字符串变成了"0101…...

git 查看当前分支最近一次提交的commit SHA

获取当前分支最近一次commit SHA &#xff08;长度为40个16进制数字的字符&#xff09;命令如下&#xff1a; git rev-parse HEAD 获取简写&#xff08;短&#xff09; commit SHA git rev-parse --short HEAD...

LuatOS 开发指南

NDK 开发 官方教程 官方例程 API 下载软件 下载官方NDK例程压缩包到本地&#xff0c;并解压。可以看到目录如下&#xff1a; doc: 文档教程 env: 编译环境 example: NDK示例 platform: 需要编译的平台&#xff08;air72x/air8xx&#xff09; tools: 其他辅助软件 VSCode 使…...

maven推包The environment variable JAVA_HOME is not correctly set

解决办法&#xff1a; 打开idea查看jdk安装位置 1.在/etc下面创建&#xff08;如果存在就是更新&#xff09;launchd.conf。里面添加一行&#xff1a; setenv JAVA_HOME /Library/Java/JavaVirtualMachines/jdk1.8.0_351.jdk/Contents/Home #JAVA_HOME后面是我的java安装路径…...

Python VScode 配置

在上一章节中我们已经安装了 Python 的环境&#xff0c;本章节我们将介绍 Python VScode 的配置。 准备工作&#xff1a; 安装 VS Code安装 VS Code Python 扩展安装 Python 3 安装 VS Code VSCode&#xff08;全称&#xff1a;Visual Studio Code&#xff09;是一款由微软…...

【vue2第九章】组件化开发和根组件以及style上的scoped作用

组件化开发和根组件 什么是组件化开发&#xff1f; 一个页面可以拆分为多个组件&#xff0c;每个组件有自己的样式&#xff0c;结构&#xff0c;行为&#xff0c;组件化开发的好处就是&#xff0c;便于维护&#xff0c;利于重复利用&#xff0c;提升开发的效率。 便于维护&…...

从零开始的Hadoop学习(五)| HDFS概述、shell操作、API操作

1. HDFS 概述 1.1 HDFS 产出背景及定义 1&#xff09;HDFS 产生背景 随着数据量越来越大&#xff0c;在一个操作系统存不下所有的数据&#xff0c;那么就分配到更多的操作系统管理的磁盘中&#xff0c;但是不方便管理和维护&#xff0c;迫切 需要一种系统来管理多台机器上的…...

【spark】序列化和反序列化,transient关键字的使用

序列化 Spark是基于JVM运行的进行&#xff0c;其序列化必然遵守Java的序列化规则。 序列化就是指将一个对象转化为二进制的byte流&#xff08;注意&#xff0c;不是bit流&#xff09;&#xff0c;然后以文件的方式进行保存或通过网络传输&#xff0c;等待被反序列化读取出来。…...

2.4 Vector<T> 动态数组(随机访问迭代器)

C自学精简教程 目录(必读) 该 Vector 版本特点 这里的版本主要是使用模板实现、支持随机访问迭代器&#xff0c;支持std::sort等所有STL算法。(本文对随机迭代器的支持参考了 复旦大学 大一公共基础课C语言的一次作业) 随机访问迭代器的实现主要是继承std::iterator<std:…...

Ubuntu下运行QEMU模拟riscv64跑Debian

1.安装QEMU 下载地址&#xff1a; https://www.qemu.org/download/ 建议选择稳定版本&#xff0c;下载后解压&#xff0c;然后make wget https://download.qemu.org/qemu-8.0.3.tar.xz tar xjvf qemu-8.0.3.tar.xz cd qemu-8.0.3 ./configure --enable-kvm --enable-virtfs …...

移动基站ip的工作原理

原理介绍 Basic Principle 先说一下概念&#xff0c;大家在不使用 WIFI 网络的时候&#xff0c;使用手机通过运营商提供的网络进行上网的时候&#xff0c;目前都是在用户端使用私有IP&#xff0c;然后对外做 NAT 转换&#xff0c;这样的情况就导致大家统一使用一些 IP 段进行访…...

Kubernetes技术--使用kubeadm搭建高可用的K8s集群(贴近实际环境)

1.高可用k8s集群架构(多master) 2.安装硬件要求 一台或多台机器,操作系统 CentOS7.x-86_x64 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多 注: 这里属于教学环境,所以使用三台虚拟机模拟实现。 3.部署规划 4.部署前准备 (1).关闭防火墙 systemctl stop fi…...

【Linux】文件

Linux 文件 什么叫文件C语言视角下文件的操作文件的打开与关闭文件的写操作文件的读操作 & cat命令模拟实现 文件操作的系统接口open & closewriteread 文件描述符进程与文件的关系重定向问题Linux下一切皆文件的认识文件缓冲区缓冲区的刷新策略 stuout & stderr 什…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)

前言&#xff1a; 最近在做行为检测相关的模型&#xff0c;用的是时空图卷积网络&#xff08;STGCN&#xff09;&#xff0c;但原有kinetic-400数据集数据质量较低&#xff0c;需要进行细粒度的标注&#xff0c;同时粗略搜了下已有开源工具基本都集中于图像分割这块&#xff0c…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...