Qt6+VTK9环境配置

2024-09-03 23:28
文章标签 配置 环境 qt6 vtk9

本文主要是介绍Qt6+VTK9环境配置,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Qt6+VTK9环境配置

  • 说明
  • 1 Qt6安装
  • 2 VTK源码编译
    • 2.1 源码下载
    • 2.2 工程编译
    • 2.3 设置环境变量
  • 3 Qt+VTK项目构建
    • 3.1 使用qmake管理项目
    • 3.2 使用cmake管理项目
  • 参考资料

说明

由于想做一点新的东西,需要去探索一些工具,对于VTK之前没有了解过,在进行环境配置时,参考了其他一些博客,由于版本的问题,采了不少坑,所以,在这里做个记录整理。我所使用的工具版本如下:

QtVTK
6.5.39.3.0

友情提示: 如果您也是新手,建议和我保持一样的版本,Qt6还好,VTK相对于之前的版本(如8.x),更新非常大,有很多地方都不一样,会有很多麻烦。

1 Qt6安装

Qt的安装没什么好说的,根据官方提供的连接,下载安装即可,如果之前没有用过Qt,进行安装。

2 VTK源码编译

2.1 源码下载

由于要和Qt一起使用,官方提供的安装包和vcpkg安装的不包括Qt相关的库,所以要从源码进行编译。VTK源码地址。进入github后,选择版本,然后下载即可。
1 选择版本

2.2 工程编译

下载好后,打开cmake-gui。选择源码路径和build文件路径(在源码同级路径下新建文件夹即可),忽略文件夹版本和代码版本不对应的问题,配环境真的很头大。
在这里插入图片描述
先点击Configure,页面出现如下界面,选择visual Studio 17 2022(我的vs是2022)和x64,然后Finish进行生成编译文件。
在这里插入图片描述
结束后,勾选BUILD_SHARED_LIBS,找到CMAKE_INSTALL_PREFIX,设置一个vtk的库文件生成路径。
在这里插入图片描述
在这里插入图片描述

然后在后面找到VTK_GROUP_ENABLE_Qt,将条件值设置为WANT
在这里插入图片描述
然后重新Configure,会出现如下错误提示
在这里插入图片描述
然后将VTK_QT_VERSION的值改为‘6’,将Qt6_DIR改为自己Qt安装路径下编译套件lib文件夹下的cmake/Qt6文件夹,Qt5的路径不用管,设置完成后再Configure。
在这里插入图片描述
在这里插入图片描述
完成后检查,若Qt的各个路径只有Qt6QmlCompilerPlusPrivate_DIR-NOTFOUND,则完成,Qt6QmlCompilerPlusPrivate这个不用管,没有影响。
在这里插入图片描述
然后,点击Generate进行生成。完成后Open Project便可操作。
在这里插入图片描述
点击Open Project,在visual Studio中打开项目。打开后将项目的编译类型设置成Release,在右侧资源管理器中,右击ALL_BUILD,开始编译。
在这里插入图片描述
在这里插入图片描述
编译完成后,同样在资源管理器中找到INSTALL,右键生成进行安装,完整完成后会在之前设置的vtk库文件生成路径下生成vtk库。
在这里插入图片描述
在这里插入图片描述
到这里,vtk库编译完成。

2.3 设置环境变量

在系统环境变量里增加vtk的bin路径
在这里插入图片描述

3 Qt+VTK项目构建

完成环境配置后,构建Qt+VTK项目进行环境测试,Qt项目有两种管理方式,基于qmake和基于cmake。

3.1 使用qmake管理项目

使用Qtcreator创建一个Qt Widgets Application项目,使用qmake管理项目。
在这里插入图片描述
在这里插入图片描述
打开项目.pro文件,将内容改为如下:

QT       += core gui openglwidgets   #openglwidgets必不可少,不然会报opengl相关的错误greaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++17# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0# Assign include header path
INCLUDEPATH += path/VTK/include
# Assign lib search path
QMAKE_LIBDIR += path/VTK/lib# Set link lib
LIBS +=vtkcgns-9.3.lib\vtkChartsCore-9.3.lib\vtkCommonColor-9.3.lib\vtkCommonComputationalGeometry-9.3.lib\vtkCommonCore-9.3.lib\vtkCommonDataModel-9.3.lib\vtkCommonExecutionModel-9.3.lib\vtkCommonMath-9.3.lib\vtkCommonMisc-9.3.lib\vtkCommonSystem-9.3.lib\vtkCommonTransforms-9.3.lib\vtkDICOMParser-9.3.lib\vtkDomainsChemistry-9.3.lib\vtkDomainsChemistryOpenGL2-9.3.lib\vtkdoubleconversion-9.3.lib\vtkexodusII-9.3.lib\vtkexpat-9.3.lib\vtkFiltersAMR-9.3.lib\vtkFiltersCellGrid-9.3.lib\vtkFiltersCore-9.3.lib\vtkFiltersExtraction-9.3.lib\vtkFiltersFlowPaths-9.3.lib\vtkFiltersGeneral-9.3.lib\vtkFiltersGeneric-9.3.lib\vtkFiltersGeometry-9.3.lib\vtkFiltersGeometryPreview-9.3.lib\vtkFiltersHybrid-9.3.lib\vtkFiltersHyperTree-9.3.lib\vtkFiltersImaging-9.3.lib\vtkFiltersModeling-9.3.lib\vtkFiltersParallel-9.3.lib\vtkFiltersParallelImaging-9.3.lib\vtkFiltersPoints-9.3.lib\vtkFiltersProgrammable-9.3.lib\vtkFiltersReduction-9.3.lib\vtkFiltersSelection-9.3.lib\vtkFiltersSMP-9.3.lib\vtkFiltersSources-9.3.lib\vtkFiltersStatistics-9.3.lib\vtkFiltersTemporal-9.3.lib\vtkFiltersTensor-9.3.lib\vtkFiltersTexture-9.3.lib\vtkFiltersTopology-9.3.lib\vtkFiltersVerdict-9.3.lib\vtkfmt-9.3.lib\vtkfreetype-9.3.lib\vtkGeovisCore-9.3.lib\vtkgl2ps-9.3.lib\vtkglew-9.3.lib\vtkGUISupportQt-9.3.lib\vtkGUISupportQtQuick-9.3.lib\vtkGUISupportQtSQL-9.3.lib\vtkhdf5-9.3.lib\vtkhdf5_hl-9.3.lib\vtkImagingColor-9.3.lib\vtkImagingCore-9.3.lib\vtkImagingFourier-9.3.lib\vtkImagingGeneral-9.3.lib\vtkImagingHybrid-9.3.lib\vtkImagingMath-9.3.lib\vtkImagingMorphological-9.3.lib\vtkImagingSources-9.3.lib\vtkImagingStatistics-9.3.lib\vtkImagingStencil-9.3.lib\vtkInfovisCore-9.3.lib\vtkInfovisLayout-9.3.lib\vtkInteractionImage-9.3.lib\vtkInteractionStyle-9.3.lib\vtkInteractionWidgets-9.3.lib\vtkIOAMR-9.3.lib\vtkIOAsynchronous-9.3.lib\vtkIOCellGrid-9.3.lib\vtkIOCesium3DTiles-9.3.lib\vtkIOCGNSReader-9.3.lib\vtkIOChemistry-9.3.lib\vtkIOCityGML-9.3.lib\vtkIOCONVERGECFD-9.3.lib\vtkIOCore-9.3.lib\vtkIOEngys-9.3.lib\vtkIOEnSight-9.3.lib\vtkIOERF-9.3.lib\vtkIOExodus-9.3.lib\vtkIOExport-9.3.lib\vtkIOExportGL2PS-9.3.lib\vtkIOExportPDF-9.3.lib\vtkIOFDS-9.3.lib\vtkIOFLUENTCFF-9.3.lib\vtkIOGeometry-9.3.lib\vtkIOHDF-9.3.lib\vtkIOImage-9.3.lib\vtkIOImport-9.3.lib\vtkIOInfovis-9.3.lib\vtkIOIOSS-9.3.lib\vtkIOLegacy-9.3.lib\vtkIOLSDyna-9.3.lib\vtkIOMINC-9.3.lib\vtkIOMotionFX-9.3.lib\vtkIOMovie-9.3.lib\vtkIONetCDF-9.3.lib\vtkIOOggTheora-9.3.lib\vtkIOParallel-9.3.lib\vtkIOParallelXML-9.3.lib\vtkIOPLY-9.3.lib\vtkIOSegY-9.3.lib\vtkIOSQL-9.3.lib\vtkioss-9.3.lib\vtkIOTecplotTable-9.3.lib\vtkIOVeraOut-9.3.lib\vtkIOVideo-9.3.lib\vtkIOXML-9.3.lib\vtkIOXMLParser-9.3.lib\vtkjpeg-9.3.lib\vtkjsoncpp-9.3.lib\vtkkissfft-9.3.lib\vtklibharu-9.3.lib\vtklibproj-9.3.lib\vtklibxml2-9.3.lib\vtkloguru-9.3.lib\vtklz4-9.3.lib\vtklzma-9.3.lib\vtkmetaio-9.3.lib\vtknetcdf-9.3.lib\vtkogg-9.3.lib\vtkParallelCore-9.3.lib\vtkParallelDIY-9.3.lib\vtkpng-9.3.lib\vtkpugixml-9.3.lib\vtkRenderingAnnotation-9.3.lib\vtkRenderingCellGrid-9.3.lib\vtkRenderingContext2D-9.3.lib\vtkRenderingContextOpenGL2-9.3.lib\vtkRenderingCore-9.3.lib\vtkRenderingFreeType-9.3.lib\vtkRenderingGL2PSOpenGL2-9.3.lib\vtkRenderingHyperTreeGrid-9.3.lib\vtkRenderingImage-9.3.lib\vtkRenderingLabel-9.3.lib\vtkRenderingLICOpenGL2-9.3.lib\vtkRenderingLOD-9.3.lib\vtkRenderingOpenGL2-9.3.lib\vtkRenderingQt-9.3.lib\vtkRenderingSceneGraph-9.3.lib\vtkRenderingUI-9.3.lib\vtkRenderingVolume-9.3.lib\vtkRenderingVolumeOpenGL2-9.3.lib\vtkRenderingVtkJS-9.3.lib\vtksqlite-9.3.lib\vtksys-9.3.lib\vtkTestingCore-9.3.lib\vtkTestingRendering-9.3.lib\vtktheora-9.3.lib\vtktiff-9.3.lib\vtktoken-9.3.lib\vtkverdict-9.3.lib\vtkViewsContext2D-9.3.lib\vtkViewsCore-9.3.lib\vtkViewsInfovis-9.3.lib\vtkViewsQt-9.3.lib\vtkWrappingTools-9.3.lib\vtkzlib-9.3.libSOURCES += \main.cpp \mainwindow.cppHEADERS += \mainwindow.hFORMS += \mainwindow.ui# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

然后打开ui文件,在页面中添加一个widget,然后点击右键选择提升为输入QVTKOpenGLNativeWidget,其提升为QVTKOpenGLNativeWidget,然后进行编译。
在这里插入图片描述
修改mainwindow.cpp文件,添加测试代码

#include "mainwindow.h"
#include "ui_mainwindow.h"#include <vtkCylinderSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkNamedColors.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
#include <vtkGenericOpenGLRenderWindow.h>#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);
VTK_MODULE_INIT(vtkRenderingFreeType);MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());vtkSmartPointer<vtkNamedColors> colors = vtkSmartPointer<vtkNamedColors>::New();vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();vtkSmartPointer<vtkPolyDataMapper> sphereMapper = vtkSmartPointer<vtkPolyDataMapper>::New();sphereMapper->SetInputConnection(sphereSource->GetOutputPort());vtkSmartPointer<vtkActor> sphereActor = vtkSmartPointer<vtkActor>::New();sphereActor->SetMapper(sphereMapper);//sphereActor->GetProperty()->SetColor(colors->GetColor4d("Tomato").GetData());vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();renderer->AddActor(sphereActor);renderer->SetBackground(colors->GetColor3d("SteelBlue").GetData());vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();renderWindow->AddRenderer(renderer);renderWindow->SetWindowName("RenderWindowNoUIFile");renderWindow->AddRenderer(renderer);renderWindow->SetWindowName("RenderWindowNoUIFile");auto renW=ui->widget;renW->setRenderWindow(renderWindow);}MainWindow::~MainWindow()
{delete ui;
}

运行,出现如下结果。
在这里插入图片描述

3.2 使用cmake管理项目

操作同上,创建新项目,选择cmake管理,然后修改cmake文件如下:

cmake_minimum_required(VERSION 3.16)project(vtk_cmake VERSION 0.1 LANGUAGES CXX)set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)#find package vtk
set(VTK_DIR "path/VTK/lib/cmake/vtk-9.3")
find_package(VTK 9.3 REQUIRED)set(PROJECT_SOURCESmain.cppmainwindow.cppmainwindow.hmainwindow.ui
)if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)qt_add_executable(vtk_cmakeMANUAL_FINALIZATION${PROJECT_SOURCES})
# Define target properties for Android with Qt 6 as:
#    set_property(TARGET vtk_cmake APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
#                 ${CMAKE_CURRENT_SOURCE_DIR}/android)
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
else()if(ANDROID)add_library(vtk_cmake SHARED${PROJECT_SOURCES})
# Define properties for Android with Qt 5 after find_package() calls as:
#    set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")else()add_executable(vtk_cmake${PROJECT_SOURCES})endif()
endif()target_link_libraries(vtk_cmake PRIVATE Qt${QT_VERSION_MAJOR}::WidgetsQt${QT_VERSION_MAJOR}::OpenGL${VTK_LIBRARIES})vtk_module_autoinit(TARGETS vtk_cmake MODULES ${VTK_LIBRARIES})# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
# If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though.
if(${QT_VERSION} VERSION_LESS 6.1.0)set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.vtk_cmake)
endif()
set_target_properties(vtk_cmake PROPERTIES${BUNDLE_ID_OPTION}MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}MACOSX_BUNDLE TRUEWIN32_EXECUTABLE TRUE
)include(GNUInstallDirs)
install(TARGETS vtk_cmakeBUNDLE DESTINATION .LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)if(QT_VERSION_MAJOR EQUAL 6)qt_finalize_executable(vtk_cmake)
endif()

和上述一样,在ui文件中添加widget并将其提示为QVTKOpenGLNativeWidget。然后修改mainwindow.cpp,添加测试代码。

#include "mainwindow.h"
#include "./ui_mainwindow.h"#include <vtkCylinderSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkNamedColors.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
#include <vtkGenericOpenGLRenderWindow.h>#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);
VTK_MODULE_INIT(vtkRenderingFreeType);MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());vtkSmartPointer<vtkNamedColors> colors = vtkSmartPointer<vtkNamedColors>::New();vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();vtkSmartPointer<vtkPolyDataMapper> sphereMapper = vtkSmartPointer<vtkPolyDataMapper>::New();sphereMapper->SetInputConnection(sphereSource->GetOutputPort());vtkSmartPointer<vtkActor> sphereActor = vtkSmartPointer<vtkActor>::New();sphereActor->SetMapper(sphereMapper);//sphereActor->GetProperty()->SetColor(colors->GetColor4d("Tomato").GetData());vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();renderer->AddActor(sphereActor);renderer->SetBackground(colors->GetColor3d("SteelBlue").GetData());vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();renderWindow->AddRenderer(renderer);renderWindow->SetWindowName("RenderWindowNoUIFile");renderWindow->AddRenderer(renderer);renderWindow->SetWindowName("RenderWindowNoUIFile");auto renW=ui->widget;renW->setRenderWindow(renderWindow);
}MainWindow::~MainWindow()
{delete ui;
}

运行,出现如下结果。
在这里插入图片描述

参考资料

1.https://blog.csdn.net/caoshangpa/article/details/135420524?ops_request_misc=%257B%2522request%255Fid%2522%253A%25223F73871A-85DF-4616-9606-7A4C8ABEE5DA%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=3F73871A-85DF-4616-9606-7A4C8ABEE5DA&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-135420524-null-null.142v100pc_search_result_base3&utm_term=qt6%E5%AE%89%E8%A3%85&spm=1018.2226.3001.4187
2.https://blog.csdn.net/weixin_43470971/article/details/127352193
3.https://blog.csdn.net/u014170067/article/details/141529399

这篇关于Qt6+VTK9环境配置的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1134346

相关文章

Zookeeper安装和配置说明

一、Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪集群模式。 ■ 单机模式:Zookeeper只运行在一台服务器上,适合测试环境; ■ 伪集群模式:就是在一台物理机上运行多个Zookeeper 实例; ■ 集群模式:Zookeeper运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble) Zookeeper通过复制来实现

CentOS7安装配置mysql5.7 tar免安装版

一、CentOS7.4系统自带mariadb # 查看系统自带的Mariadb[root@localhost~]# rpm -qa|grep mariadbmariadb-libs-5.5.44-2.el7.centos.x86_64# 卸载系统自带的Mariadb[root@localhost ~]# rpm -e --nodeps mariadb-libs-5.5.44-2.el7

hadoop开启回收站配置

开启回收站功能,可以将删除的文件在不超时的情况下,恢复原数据,起到防止误删除、备份等作用。 开启回收站功能参数说明 (1)默认值fs.trash.interval = 0,0表示禁用回收站;其他值表示设置文件的存活时间。 (2)默认值fs.trash.checkpoint.interval = 0,检查回收站的间隔时间。如果该值为0,则该值设置和fs.trash.interval的参数值相等。

NameNode内存生产配置

Hadoop2.x 系列,配置 NameNode 内存 NameNode 内存默认 2000m ,如果服务器内存 4G , NameNode 内存可以配置 3g 。在 hadoop-env.sh 文件中配置如下。 HADOOP_NAMENODE_OPTS=-Xmx3072m Hadoop3.x 系列,配置 Nam

wolfSSL参数设置或配置项解释

1. wolfCrypt Only 解释:wolfCrypt是一个开源的、轻量级的、可移植的加密库,支持多种加密算法和协议。选择“wolfCrypt Only”意味着系统或应用将仅使用wolfCrypt库进行加密操作,而不依赖其他加密库。 2. DTLS Support 解释:DTLS(Datagram Transport Layer Security)是一种基于UDP的安全协议,提供类似于

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

安装nodejs环境

本文介绍了如何通过nvm(NodeVersionManager)安装和管理Node.js及npm的不同版本,包括下载安装脚本、检查版本并安装特定版本的方法。 1、安装nvm curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash 2、查看nvm版本 nvm --version 3、安装

【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联

高并发环境中保持幂等性

在高并发环境中保持幂等性是一项重要的挑战。幂等性指的是无论操作执行多少次,其效果都是相同的。确保操作的幂等性可以避免重复执行带来的副作用。以下是一些保持幂等性的常用方法: 唯一标识符: 请求唯一标识:在每次请求中引入唯一标识符(如 UUID 或者生成的唯一 ID),在处理请求时,系统可以检查这个标识符是否已经处理过,如果是,则忽略重复请求。幂等键(Idempotency Key):客户端在每次