当前位置: 首页 > 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 什…...

Android OTA 相关工具(六) 使用 lpmake 打包生成 super.img

我在 《Android 动态分区详解(二) 核心模块和相关工具介绍》 介绍过 lpmake 工具&#xff0c;这款工具用于将多个分区镜像打包生成一个 Android 专用的动态分区镜像&#xff0c;一般称为 super.img。Android 编译时&#xff0c;系统会自动调用 lpmake 并传入相关参数来生成 sup…...

信创环境 Phytium S2500 虚拟机最大内存规格测试

在 ARM 架构中,"IPA" 通常指的是 "Instruction Set Architecture"(指令集架构),arm环境的虚拟机支持的最大内存规格与母机上内存多少无关,由arm本身的ipa size决定,ipa size 可以理解为虚拟机的物理地址空间,kernel5.4.32中ipa默认是44bits(16T si…...

新建工程——第一个S32DS工程

之前的"测试开发板"章节 测试开发板——第一个AutoSAR程序,使用了一个 demo 工程,不管是裸机程序还是 AutoSAR 程序,那都是别人已经创建好的工程。本节来介绍如何来创建自己的工程,本节介绍如何创建一个 S32DS 的工程,点亮开发板上的 LED 我们从官方提供的例程…...

基于Open3D的点云处理16-特征点匹配

点云配准 将点云数据统一到一个世界坐标系的过程称之为点云配准或者点云拼接。&#xff08;registration/align&#xff09; 点云配准的过程其实就是找到同名点对&#xff1b;即找到在点云中处在真实世界同一位置的点。 常见的点云配准算法: ICP、Color ICP、Trimed-ICP 算法…...

设计模式—简单工厂

目录 一、前言 二、简单工厂模式 1、计算器例子 2、优化后版本 3、结合面向对象进行优化&#xff08;封装&#xff09; 3.1、Operation运算类 3.2、客户端 4、利用面向对象三大特性&#xff08;继承和多态&#xff09; 4.1、Operation类 4.2、加法类 4.3、减法类 4…...

真机安装Linux Centos7

准备工具&#xff1a; 8G左右U盘最新版UltraISOCentOS7光盘镜像 操作步骤 下载镜像 地址&#xff1a;http://isoredirect.centos.org/centos/7/isos/x86_64/ 安装刻录工具UltraISO&#xff0c;刻录镜像到U盘 ① 选择ISO镜像文件 ② 写入磁盘镜像&#xff0c;在这里选择你的U盘…...

ceph peering机制-状态机

本章介绍ceph中比较复杂的模块&#xff1a; Peering机制。该过程保障PG内各个副本之间数据的一致性&#xff0c;并实现PG的各种状态的维护和转换。本章首先介绍boost库的statechart状态机基本知识&#xff0c;Ceph使用它来管理PG的状态转换。其次介绍PG的创建过程以及相应的状…...

Java | File类

目录&#xff1a; File类File类中常用的方法&#xff1a;boolean exists( ) &#xff1a;判断此 文件/目录 是否存在boolean createNewFile( ) &#xff1a;创建一个文件boolean mkdir( ) &#xff1a;创建 “单层” 目录/文件夹boolean mkdirs( ) &#xff1a;创建 “多层” 目…...

数学建模之灰色预测

灰色预测&#xff08;Grey Forecasting&#xff09;是一种用于时间序列数据分析和预测的方法&#xff0c;通常用于处理具有较少历史数据的情况或者数据不够充分的情况。它是一种非常简单但有效的方法&#xff0c;基于灰色系统理论&#xff0c;用来估计未来的趋势。 以下是灰色…...

03_nodejd_npm install报错

npm install报错 npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: 5kcrm11.0.0 npm ERR! Found: vue2.5.17 npm ERR! node_modules/vue npm ERR! vue"2.5.17" from the root project npm ERR! np…...

易语言跳到指定网站怎么做/武汉排名seo公司

由于键盘的通知是系统自动的&#xff0c;因此可以不用创建通知&#xff0c;只需要注册一个监听器监听即可&#xff0c;当收到相应的通知去执行方法。 键盘状态改变的时候,系统会发出一些特定的通知 UIKeyboardWillShowNotification // 键盘即将显示 UIKeyboardDidShowNotif…...

如何建一个免费网站/百度站长平台官网登录入口

本文参考自《剑指offer》一书&#xff0c;代码采用Java语言。题目请实现一个函数用来匹配包含.和*的正则表达式。模式中的字符.表示任意一个字符&#xff0c;而*表示它前面的字符可以出现任意次(含0次)。在本题中&#xff0c;匹配是指字符串的所有字符匹配整个模式。例如&#…...

做结构图用什么网站/百度网络营销app

这个分页插件是基于mybatis-3.25.jar commons-lang3-3.32.jar 以及mybatis-spring-1.2.0.jar。 下面是继承了Interceptor的插件类 package dwz.common.mybatis;import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.…...

交互式网站开发技术有哪些/苏州排名搜索优化

3.为什么蛇没有脚都能走路?么蛇没有脚都能走路?蛇的身上有很多鳞片,这是它们身上最外面的一层盔甲.鳞片不但用来保护 身体,还可以是它们的"脚" .蛇向前爬行时,身体会呈 S 形.而每一片在 S 形外边的鳞片,都会翘起来,帮助蛇前进时抓住不平的路面.这些鳞片跟蛇的肌肉互…...

政府门户网站建设中标/成人零基础学电脑培训班

通过 Groovy 进行循环 同大多数脚本语言一样&#xff0c;Groovy 经常被宣传为生产力更高 的 Java 语言替代品。 更好、更短的循环 下面这种方法可以更好地感受 Groovy 缺乏类型的好处&#xff1a;首先&#xff0c;用与创建 HelloWorld 相同的方式创建一个 Groovy 类&#xf…...

专注苏州网站建设/重庆人力资源和社会保障网官网

Afinal是一个orm、ioc框架&#xff0c;遵循约定大于配置原则&#xff0c;无需任何配置即可完成所有工作&#xff0c;但也可以通过配置达到个人的个性化需求。Afinal提倡代码快速简洁&#xff0c;尽量一行代码完成的事情不会用两行。Afinal里面目前包含了四大组件&#xff1a;Fi…...