windows和linux编写jni相关库,并使用动态调用来加载动态库

news/2025/11/20 14:52:33/文章来源:https://www.cnblogs.com/zeromi/p/19247110

windows和linux编写jni相关库,并使用动态调用来加载动态库

1. 编写java代码

注意使用jni的代码,修改包名时,需要重新生成头文件并同步修改dll库相关代码,否则会导致无法链接错误


package org.example.testjni;import java.io.File;/*** 注意: 使用jni的代码,修改包名时,需要重新生成头文件并同步修改dll库相关代码,否则会导致无法链接错误*/
public class Decoder {private static String dllPath = null;private static long handle = 0L;private static Decoder decoder = null;public native String version();public String encode(String serial, int synctime) {return this.encode(handle, serial, synctime);}public String decode(String data) {return this.decode(handle, data);}private native long init(String dllPath);private native void kill(long handle);private native String encode(long handle, String serial, int synctime);private native String decode(long handle, String data);private Decoder() {}public void close() {if (handle != 0L) {decoder.kill(handle);handle = 0L;}decoder = null;}public static Decoder getDecoder() {if (decoder == null) {synchronized(Decoder.class) {decoder = new Decoder();handle = decoder.init(dllPath);}}return decoder;}/**** @param proxyDllPath 代理dll的目录地址,要求两个dll放置在同一目录*/public static void loadDll(String proxyDllPath) {String systemType = System.getProperties().getProperty("os.name");System.err.println("加载lib之前打点");String proxyFullPath = null;if (systemType.indexOf("Windows") != -1) {Decoder.dllPath = proxyDllPath + File.separator + "testdll.dll";proxyFullPath = proxyDllPath + File.separator + "testjni.dll";} else {Decoder.dllPath = proxyDllPath + File.separator + "testdll.so";proxyFullPath = proxyDllPath + File.separator + "testjni.so";}System.load(proxyFullPath);}public static void main(String[] args) {
//        String property = System.getProperty("java.library.path");
//        System.setProperty("java.library.path", property + File.pathSeparator + "E:\\test\\lib");
//        System.err.println(System.getProperty("java.library.path"));String systemType = System.getProperties().getProperty("os.name");System.err.println("加载lib之前打点");String proxyDllPath = null;if (systemType.indexOf("Windows") != -1) {proxyDllPath = "E:\\codes\\testjni\\temp";} else {proxyDllPath = "/root/code/cpp/testjni";}Decoder.loadDll(proxyDllPath);Decoder d = getDecoder();System.out.println("testdll version: " + d.version());String s = "encode_testdata";System.out.println(d.decode(s));s = "encode_testdata_2";System.out.println(d.decode(s));System.out.println(d.encode("testdata", 0));System.out.println(d.encode("testdata", 1));}}

2. windows下编译jni动态库

在vs向导页面创建一个dll库项目,并按如下设置,附加包含目录里面的目录路径是头文件路径
clip

此外要注意这个不使用预编译头,如果你使用了windows相关的api,但是没有正确的引用pch.h, 会报错,这个时候就需要设置不使用预编译头
clip_1

2.1. 目录结构

"jdk8_jni_heade"就是jdk根目录的include文件夹复制过来的,其实可以不用复制,直接在选项中指定目录位置就可以了

|--- include
|   |--- org_example_testjni_Decoder.h
|   |--- jdk8_jni_header(省略此文件夹内容,)
|--- testjni.h
|--- testjni.cpp

2.2. 本地库代码

org_example_testjni_Decoder.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_example_testjni_Decoder */#ifndef _Included_org_example_testjni_Decoder
#define _Included_org_example_testjni_Decoder
#ifdef __cplusplus
extern "C" {
#endif/** Class:     org_example_testjni_Decoder* Method:    version* Signature: ()Ljava/lang/String;*/JNIEXPORT jstring JNICALL Java_org_example_testjni_Decoder_version(JNIEnv*, jobject);/** Class:     org_example_testjni_Decoder* Method:    init* Signature: (Ljava/lang/String;)J*/JNIEXPORT jlong JNICALL Java_org_example_testjni_Decoder_init(JNIEnv*, jobject, jstring);/** Class:     org_example_testjni_Decoder* Method:    kill* Signature: (J)V*/JNIEXPORT void JNICALL Java_org_example_testjni_Decoder_kill(JNIEnv*, jobject, jlong);/** Class:     org_example_testjni_Decoder* Method:    encode* Signature: (JLjava/lang/String;I)Ljava/lang/String;*/JNIEXPORT jstring JNICALL Java_org_example_testjni_Decoder_encode(JNIEnv*, jobject, jlong, jstring, jint);/** Class:     org_example_testjni_Decoder* Method:    decode* Signature: (JLjava/lang/String;)Ljava/lang/String;*/JNIEXPORT jstring JNICALL Java_org_example_testjni_Decoder_decode(JNIEnv*, jobject, jlong, jstring);#ifdef __cplusplus
}
#endif
#endif

testjni.h

#pragma once
#ifndef TESTJNI_H
#define TESTJNI_H#include "include/org_example_testjni_Decoder.h"#include <windows.h>#include <string>#endif //TESTJNI_H

testjni.cpp

#include "testjni.h"namespace {// 只能在本 .cpp 文件中访问static HMODULE hDll = NULL;using Version = jstring(*)(JNIEnv*, jobject); // 定义函数指针类型static Version version = NULL;using Init = jlong(*)(JNIEnv*, jobject); // 定义函数指针类型static Init init = NULL;using Kill = void(*)(JNIEnv*, jobject, jlong); // 定义函数指针类型static Kill kill = NULL;using Encode = jstring(*)(JNIEnv*, jobject, jlong, jstring, jint); // 定义函数指针类型static Encode encode = NULL;using Decode = jstring(*)(JNIEnv*, jobject, jlong, jstring); // 定义函数指针类型static Decode decode = NULL;/** 释放加载的dll*/void free_dll() {FreeLibrary(hDll);init = NULL;kill = NULL;version = NULL;encode = NULL;decode = NULL;hDll = NULL;}
}/** Class:     org_example_testjni_Decoder* Method:    version* Signature: ()Ljava/lang/String;*/
JNIEXPORT jstring JNICALL Java_org_example_testjni_Decoder_version
(JNIEnv* j_env, jobject j_obj) {if (version != NULL) {return version(j_env, j_obj);}// 获取异常类jclass cls_run_excep = j_env->FindClass("java/lang/RuntimeException");j_env->ThrowNew(cls_run_excep, "version method is null!");return NULL;
}/** Class:     org_example_testjni_Decoder* Method:    init* Signature: ()J*/
JNIEXPORT jlong JNICALL Java_org_example_testjni_Decoder_init
(JNIEnv* j_env, jobject j_obj, jstring j_dll_full_path) {// 获取异常类jclass cls_run_excep = j_env->FindClass("java/lang/RuntimeException");if (hDll == NULL) {// 获取java字符串const char* dll_full_path = j_env->GetStringUTFChars(j_dll_full_path, nullptr);// 不使用绝对路径的直接使用testdll.dll,则会从系统库路径加载,比如项目根目录hDll = GetModuleHandleA(dll_full_path);if (NULL == hDll) {hDll = LoadLibraryA(dll_full_path);}// 释放字符串j_env->ReleaseStringUTFChars(j_dll_full_path, dll_full_path);if (NULL == hDll) {j_env->ThrowNew(cls_run_excep, "load testdll.dll fail!");// 错误处理return NULL;}}if (version == NULL) {version = (Version)GetProcAddress(hDll, "Java_org_example_testdll_Decoder_version");if (!version) {free_dll();j_env->ThrowNew(cls_run_excep, "Java_org_example_testdll_Decoder_version is not found!");return NULL;}}if (init == NULL) {init = (Init)GetProcAddress(hDll, "Java_org_example_testdll_Decoder_init");if (!init) {free_dll();j_env->ThrowNew(cls_run_excep, "Java_org_example_testdll_Decoder_init is not found!");return NULL;}}if (kill == NULL) {kill = (Kill)GetProcAddress(hDll, "Java_org_example_testdll_Decoder_kill");if (!kill) {free_dll();j_env->ThrowNew(cls_run_excep, "Java_org_example_testdll_Decoder_kill is not found!");return NULL;}}if (encode == NULL) {encode = (Encode)GetProcAddress(hDll, "Java_org_example_testdll_Decoder_encode");if (!kill) {free_dll();j_env->ThrowNew(cls_run_excep, "Java_org_example_testdll_Decoder_encode is not found!");return NULL;}}if (decode == NULL) {decode = (Decode)GetProcAddress(hDll, "Java_org_example_testdll_Decoder_decode");if (!decode) {free_dll();j_env->ThrowNew(cls_run_excep, "Java_org_example_testdll_Decoder_decode is not found!");return NULL;}}return init(j_env, j_obj);
}/** Class:     org_example_testjni_Decoder* Method:    kill* Signature: (J)V*/
JNIEXPORT void JNICALL Java_org_example_testjni_Decoder_kill
(JNIEnv* j_env, jobject j_obj, jlong j_handle) {if (kill != NULL) {kill(j_env, j_obj, j_handle);free_dll();}// 获取异常类jclass cls_run_excep = j_env->FindClass("java/lang/RuntimeException");j_env->ThrowNew(cls_run_excep, "kill method is null!");
}/** Class:     org_example_testjni_Decoder* Method:    encode* Signature: (JLjava/lang/String;I)Ljava/lang/String;*/
JNIEXPORT jstring JNICALL Java_org_example_testjni_Decoder_encode
(JNIEnv* j_env, jobject j_obj, jlong j_handle, jstring j_serial, jint j_synctime) {if (encode != NULL) {return encode(j_env, j_obj, j_handle, j_serial, j_synctime);}// 获取异常类jclass cls_run_excep = j_env->FindClass("java/lang/RuntimeException");j_env->ThrowNew(cls_run_excep, "encode method is null!");return NULL;
}/** Class:     org_example_testjni_Decoder* Method:    decode* Signature: (JLjava/lang/String;)Ljava/lang/String;*/
JNIEXPORT jstring JNICALL Java_org_example_testjni_Decoder_decode
(JNIEnv* j_env, jobject j_obj, jlong j_handle, jstring j_data) {if (decode != NULL) {return decode(j_env, j_obj, j_handle, j_data);}// 获取异常类jclass cls_run_excep = j_env->FindClass("java/lang/RuntimeException");j_env->ThrowNew(cls_run_excep, "decode method is null!");return NULL;
}

2.3 编译生成dll文件

直接点生成解决方案,就可以在项目根目录的相关目录找到

3. linux下编译jni动态库

3.2. 目录结构

"jdk8_jni_heade"就是jdk根目录的include文件夹复制过来的,其实可以不用复制,直接在选项中指定目录位置就可以了

|--- include
|   |--- org_example_testjni_Decoder.h
|   |--- jdk8_jni_header(省略此文件夹内容,)
|--- testjni.h
|--- testjni.cpp

3.2. 本地库代码

org_example_testjni_Decoder.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_example_testjni_Decoder */#ifndef _Included_org_example_testjni_Decoder
#define _Included_org_example_testjni_Decoder
#ifdef __cplusplus
extern "C" {
#endif
/** Class:     org_example_testjni_Decoder* Method:    version* Signature: ()Ljava/lang/String;*/
JNIEXPORT jstring JNICALL Java_org_example_testjni_Decoder_version(JNIEnv *, jobject);/** Class:     org_example_testjni_Decoder* Method:    init* Signature: (Ljava/lang/String;)J*/
JNIEXPORT jlong JNICALL Java_org_example_testjni_Decoder_init(JNIEnv *, jobject, jstring);/** Class:     org_example_testjni_Decoder* Method:    kill* Signature: (J)V*/
JNIEXPORT void JNICALL Java_org_example_testjni_Decoder_kill(JNIEnv *, jobject, jlong);/** Class:     org_example_testjni_Decoder* Method:    encode* Signature: (JLjava/lang/String;I)Ljava/lang/String;*/
JNIEXPORT jstring JNICALL Java_org_example_testjni_Decoder_encode(JNIEnv *, jobject, jlong, jstring, jint);/** Class:     org_example_testjni_Decoder* Method:    decode* Signature: (JLjava/lang/String;)Ljava/lang/String;*/
JNIEXPORT jstring JNICALL Java_org_example_testjni_Decoder_decode(JNIEnv *, jobject, jlong, jstring);#ifdef __cplusplus
}
#endif
#endif

testjni.h

#ifndef TESTJNI_H
#define TESTJNI_H#include "include/org_example_testjni_Decoder.h"#include <dlfcn.h>#include <string>#endif //TESTJNI_H

testjni.cpp

#include "testjni.h"// 匿名命名空间
namespace {// 只能在本 .cpp 文件中访问static void* hDll = NULL;using Version = jstring(*)(JNIEnv*, jobject); // 定义函数指针类型static Version version = NULL;using Init = jlong(*)(JNIEnv*, jobject); // 定义函数指针类型static Init init = NULL;using Kill = void(*)(JNIEnv*, jobject, jlong); // 定义函数指针类型static Kill kill = NULL;using Encode = jstring(*)(JNIEnv*, jobject, jlong, jstring, jint); // 定义函数指针类型static Encode encode = NULL;using Decode = jstring(*)(JNIEnv*, jobject, jlong, jstring); // 定义函数指针类型static Decode decode = NULL;/** 释放加载的dll*/void free_dll() {dlclose(hDll);init = NULL;kill = NULL;version = NULL;encode = NULL;decode = NULL;hDll = NULL;}
}/** Class:     org_example_testjni_Decoder* Method:    version* Signature: ()Ljava/lang/String;*/
JNIEXPORT jstring JNICALL Java_org_example_testjni_Decoder_version
(JNIEnv* j_env, jobject j_obj) {if (version != NULL) {return version(j_env, j_obj);}// 获取异常类jclass cls_run_excep = j_env->FindClass("java/lang/RuntimeException");j_env->ThrowNew(cls_run_excep, "version method is null!");return NULL;
}/** Class:     org_example_testjni_Decoder* Method:    init* Signature: ()J*/
JNIEXPORT jlong JNICALL Java_org_example_testjni_Decoder_init
(JNIEnv* j_env, jobject j_obj, jstring j_dll_full_path) {// 获取异常类jclass cls_run_excep = j_env->FindClass("java/lang/RuntimeException");if (hDll == NULL) {// 获取java字符串const char* dll_full_path = j_env->GetStringUTFChars(j_dll_full_path, nullptr);// testdll.dllhDll = dlopen(dll_full_path,RTLD_LAZY);// 释放字符串j_env->ReleaseStringUTFChars(j_dll_full_path, dll_full_path);if (NULL == hDll) {fprintf(stderr,"%s ", dlerror());j_env->ThrowNew(cls_run_excep, "load testdll.so fail!");// 错误处理return 0;}}if (version == NULL) {version = (Version)dlsym(hDll, "Java_org_example_testdll_Decoder_version");if (!version) {free_dll();j_env->ThrowNew(cls_run_excep, "Java_org_example_testdll_Decoder_version is not found!");return 0;}}if (init == NULL) {init = (Init)dlsym(hDll, "Java_org_example_testdll_Decoder_init");if (!init) {free_dll();j_env->ThrowNew(cls_run_excep, "Java_org_example_testdll_Decoder_init is not found!");return 0;}}if (kill == NULL) {kill = (Kill)dlsym(hDll, "Java_org_example_testdll_Decoder_kill");if (!kill) {free_dll();j_env->ThrowNew(cls_run_excep, "Java_org_example_testdll_Decoder_kill is not found!");return 0;}}if (encode == NULL) {encode = (Encode)dlsym(hDll, "Java_org_example_testdll_Decoder_encode");if (!kill) {free_dll();j_env->ThrowNew(cls_run_excep, "Java_org_example_testdll_Decoder_encode is not found!");return 0;}}if (decode == NULL) {decode = (Decode)dlsym(hDll, "Java_org_example_testdll_Decoder_decode");if (!decode) {free_dll();j_env->ThrowNew(cls_run_excep, "Java_org_example_testdll_Decoder_decode is not found!");return 0;}}return init(j_env, j_obj);
}/** Class:     org_example_testjni_Decoder* Method:    kill* Signature: (J)V*/
JNIEXPORT void JNICALL Java_org_example_testjni_Decoder_kill
(JNIEnv* j_env, jobject j_obj, jlong j_handle) {if (kill != NULL) {kill(j_env, j_obj, j_handle);free_dll();}// 获取异常类jclass cls_run_excep = j_env->FindClass("java/lang/RuntimeException");j_env->ThrowNew(cls_run_excep, "kill method is null!");
}/** Class:     org_example_testjni_Decoder* Method:    encode* Signature: (JLjava/lang/String;I)Ljava/lang/String;*/
JNIEXPORT jstring JNICALL Java_org_example_testjni_Decoder_encode
(JNIEnv* j_env, jobject j_obj, jlong j_handle, jstring j_serial, jint j_synctime) {if (encode != NULL) {return encode(j_env, j_obj, j_handle, j_serial, j_synctime);}// 获取异常类jclass cls_run_excep = j_env->FindClass("java/lang/RuntimeException");j_env->ThrowNew(cls_run_excep, "encode method is null!");return NULL;
}/** Class:     org_example_testjni_Decoder* Method:    decode* Signature: (JLjava/lang/String;)Ljava/lang/String;*/
JNIEXPORT jstring JNICALL Java_org_example_testjni_Decoder_decode
(JNIEnv* j_env, jobject j_obj, jlong j_handle, jstring j_data) {if (decode != NULL) {return decode(j_env, j_obj, j_handle, j_data);}// 获取异常类jclass cls_run_excep = j_env->FindClass("java/lang/RuntimeException");j_env->ThrowNew(cls_run_excep, "decode method is null!");return NULL;
}

3.3. 使用g++编译

g++ testjni.cpp -std=c++14 -I ./include -I ./include/jdk8_jni_header/ -I ./include/jdk8_jni_header/linux/ -fPIC -shared -o testjni.so

4.总结linux和windows下的动态库的动态加载差异

功能 windows linux 附加说明
动态库后缀名 以.dll作为后缀,是PE文件格式 以lib开头,以.so作为后缀 存在差异
定义函数指针 using Kill = void()(JNIEnv, jobject, jlong); using Kill = void()(JNIEnv, jobject, jlong); 完全一样
使用函数指针 kill(j_env, j_obj, j_handle) kill(j_env, j_obj, j_handle) 完全一样
加载动态库api HMODULE hDll= GetModuleHandleA(dll_full_path);/HMODULE hDll= LoadLibraryA(dll_full_path); void* hDll = dlopen(dll_full_path,RTLD_LAZY); 存在差异
加载动态库函数api decode = (Decode)GetProcAddress(hDll, "Java_org_example_testdll_Decoder_decode"); decode = (Decode)dlsym(hDll, "Java_org_example_testdll_Decoder_decode"); 存在差异
释放动态库函数api FreeLibrary(hDll); dlclose(hDll); 存在差异

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

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

相关文章

2025年移动方舱订做厂家权威推荐榜单:集装箱房/军用方舱/宿营方舱源头厂家精选

在应急保障与特种作业需求日益多元的今天,三家各具特色的移动方舱订制厂家正以专业能力赢得市场认可。 移动方舱作为模块化建筑的重要分支,因其快速部署、灵活适配的特性,在应急指挥、医疗救援、环卫作业等领域发挥…

第十一章 泛型算法

11.1 概述 11.1.1 标准算法独立于类型需要某种遍历集合的方式:能够从一个元素向前移到下一个元素; 必须能够知道是否达到了集合的末尾; 必须能够对容器中的每一个元素与被查找的元素进行比较; 需要一个类型来指出元…

P2511 [HAOI2008] 木棍分割

解题思路 这个问题分为两个部分: 第一部分:求最大段长度的最小值(二分答案)使用二分查找确定最小的最大段长度对于每个候选值mid,用贪心检查是否能分成最多m+1段(切m刀)检查时尽量把木棍合并,直到超过mid就开新…

国标GB28181算法算力平台EasyGBS:构建“智慧消防”可视化管理与预警新模式

引言:智慧消防的紧迫性与传统消防的困境 随着城市化进程加快,高层建筑、大型综合体、化工园区日益增多,火灾风险与防控压力与日俱增。传统消防模式高度依赖“人防+物防”,面临着诸多痛点:预警滞后:火灾发现往往依…

MySQL高级运维核心技术:事务处理、安全管理与性能优化

MySQL高级运维核心技术:事务处理、安全管理与性能优化MySQL作为主流的关系型数据库管理系统,在实际生产环境中,事务一致性、数据安全性、系统稳定性及性能表现直接决定业务可用性。 一、事务处理:保障数据一致性的…

实用指南:链表-双向链表【node3】

实用指南:链表-双向链表【node3】pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&…

Vue中,list集合中包含实体(对象)的列表,存在某个特定的值在实体类属性是否存在常见的方法:

1、vue中代码// 假设你有一个对象列表 data() {return {items: [{ id: 1, name: Item 1 },{ id: 2, name: Item 2 },{ id: 3, name: Item 3 }]}; }, methods: {isItemPresent(id) {return this.items.some(item => …

2025年复合涤纶布优质厂家权威推荐榜单:涂层涤纶布/阻燃涤纶布/防水涤纶布源头厂家精选

复合涤纶布作为一种多功能复合材料,广泛应用于户外装备、防护服装、家居装饰和产业用纺织品等领域。其市场规模在全球化纤产业升级的推动下持续增长,预计到2031年全球涤纶复合丝市场将保持稳定增长态势。面对市场上众…

List相关知识点

数组(Array) ​ 是一种用连续的内存空间存储相同数据类型数据的线性数据结构,指向首地址​ 在根据数组索引获取元素的时候,会用索引和寻址公式来计算内存所对应的元素数据,寻址公式是:数组的首地址+索引乘以存储…

图文矩阵系统厂家综合测评推荐榜,抖音短视频矩阵/ai排名/短视频矩阵/ai排行榜/ai数字人矩阵/图文矩阵厂家推荐

行业背景分析 随着数字营销进入深度发展期,图文矩阵作为企业内容营销的重要载体,正经历从单一内容输出到多元化矩阵布局的转型。据最新行业数据显示,2024年图文矩阵服务市场规模已达千亿级别,年复合增长率保持在25…

【山东省物联网协会主办,IEEE出版】2025年智慧物联与电子信息工程国际学术会议(IoTEIE 2025)

【山东省物联网协会主办,IEEE出版】2025年智慧物联与电子信息工程国际学术会议(IoTEIE 2025)2025年智慧物联与电子信息工程国际学术会议(IoTEIE 2025) 2025年12月5-7日 中国-青岛 截稿时间:多轮截稿,官网为准 组织单…

ubuntu22.04 安装OpenSSH-server 支持vscode 远程

在 Ubuntu 22.04 上安装 OpenSSH 服务器(openssh-server)的步骤如下: 1. 更新软件包列表 在安装前,建议先更新系统的软件包列表以确保获取最新的软件信息: bashCopy Code sudo apt update 2. 安装 OpenSSH 服务器…

2025年工业溶氧仪实力厂家权威推荐榜单:溶氧分析仪/溶解氧分析仪/在线溶解氧分析仪源头厂家精选

在工业环保要求持续提升与智能监测技术快速发展的背景下,工业溶氧仪作为水质监测的核心设备,其测量精度、稳定性和智能化水平已成为水务管理、污染治理和工业生产过程控制的关键考量。据行业报告显示,全球水质分析仪…

2025年氮气增压泵源头厂家权威推荐榜单:气动增压泵/氦气增压泵/氦气增压泵源头厂家精选

在工业自动化与新能源技术快速发展的背景下,氮气增压泵作为关键流体压力转换设备,其输出压力范围、稳定性与介质兼容性直接影响氢能源、石油化工、航空航天等高端领域的生产安全与效率。据行业报告预测,2025年中国气…

ps2025永久免费破解版下载安装教程(附安装包)ps2025

一.Photoshop2025 下载 在开始安装前,请确保已下载Photoshop2025 安装包,同时,确认计算机满足软件的最低系统要求,以保证安装和运行的流畅性。 Photoshop2025下载链接:https://pan.quark.cn/s/ac9117573682 二.Ph…

vxe-table 如何实现拖拽行数据排序,并对拖拽后进行提示框二次确认是否允许拖拽

vxe-table 如何实现拖拽行数据排序,并对拖拽后进行提示框二次确认是否允许拖拽,通过 row-drag-config.dragStartMethod 可以自定义处理拖拽开始时的拖动 查看官网:https://vxetable.cn gitbub:https://github.com/…

nacos单机版安装

环境:OS:Centos 7nacos:2.5.2 mysql:5.7jdk:21.0.41.下载地址地址https://github.com/alibaba/nacos/releases/tag/2.5.2下载介质nacos-server-2.5.2.tar.gz2.解压安装每个机器都要执行如下操作[root@master soft]# ta…

linux top命令配置重置还原

ubuntu24.04lts top命令修改配置后还原: top命令配置所在 /home/你的用户名/.config/procps/toprc,删除此文件即可还原初始配置。

Linux中: 通过 iostat 怎么判断硬盘是否存在I/O瓶颈

Linux中: "通过 iostat 怎么判断硬盘是否存在I/O瓶颈"硬盘 I/O 指的是对硬盘的读和写操作,使用 IOPS 来衡量硬盘的 IO 能力,假设某块硬盘每秒最多能处理100和写请求,如果单位时间内的写请求数接近这个数…

2025 年便携式 VOC 气体检测仪、气体检测仪厂家十大品牌推荐:精准监测筑牢安全防线,智能传感赋能行业发展

在工业生产、环境监测、市政安全等领域,气体检测设备是守护人员生命安全、保障生产稳定、维护生态环境的核心工具。其中,便携式 VOC 气体检测仪凭借灵活便捷、响应迅速的特点,成为化工园区巡检、燃气泄漏排查、应急…