根据OS自动加载不同的native库和本地jar包

发布于:2025-07-04 ⋅ 阅读:(19) ⋅ 点赞:(0)

背景

在SpringBoot项目中调用虹软SDK,来实现人脸、性别检测等功能。且此项目需要部署到不同环境,包括Windows和Linux。以Windows为例,从下图可见,需要加载本地jar包(maven的公开库找不到此依赖),和native库(Windows上为.dll文件,Linux上为.so文件)。
在这里插入图片描述

加载本地jar包

pom.xml中的本地依赖如下。当使用了 system 作用域,Maven 不会尝试从远程仓库下载这个依赖,而是直接使用指定路径的本地文件:

     <dependency>  <!--虹软 人像识别-->
         <groupId>com.arcsoft.face</groupId>
         <artifactId>arcsoft-sdk-face</artifactId>
         <version>3.0.0.0</version>
         <scope>system</scope>
         <systemPath>${pom.basedir}/libs/WIN64/arcsoft-sdk-face-3.0.0.0.jar</systemPath>
     </dependency>

另外注意需要进行以下设置,不然打jar包时,不会包含system作用域的依赖:
在这里插入图片描述

加载native库

可简单通过os.name等系统属性来自动选择不同路径。核心代码:

private static String getLibPath() {  //native库路径
     String osName = System.getProperty("os.name").toLowerCase();
     String localPath = System.getProperty("user.dir");
     String libPath = localPath + File.separator + "libs";
     if (osName.contains("win")) {
         libPath += File.separator + "WIN64";
     } else {
         libPath += File.separator + "linux";
     }
     return libPath;
 }

@PostConstruct
public void init() {
    faceEngine = new FaceEngine(getLibPath());
    。。。

从虹软的代码中可以看到,加载native库的底层关键方法是System.load等方法。

打jar包时如何处理native库

处理 native 库(如 DLL 文件) 的几种思路:

  • 方案一:手动复制DLL到JAR外部的指定目录(如应用根目录或系统库路径)

  • 方案二:将dll打进jar包,运行时再提取DLL到临时目录(感觉不如方案三,放弃)

  • 方案三(推荐):使用 Maven 在构建阶段复制 DLL 到外部 lib 目录 。和方案一一样不将native 文件打进jar包,比方案一优秀在复制动作是自动化的。

亲测有效。示例:修改 pom.xml,在<project><build><plugins>标签中加入:

<plugin>
                <artifactId>maven-antrun-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-native-libs</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <!-- 创建目标目录 -->
                                <mkdir dir="${project.build.directory}/libs"/>
                                <!-- 复制 WIN64 目录下的内容 -->
                                <copy todir="${project.build.directory}/libs/WIN64">
                                    <fileset dir="libs/WIN64"/>
                                </copy>
                            </target>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

运行mvn pacakge命令后,可以看到target目录下有了复制过来的文件:
在这里插入图片描述
原理(by通义千问):Maven 本身不提供直接复制文件的功能,但可以通过使用 maven-antrun-plugin 插件 来调用 Ant 任务实现文件复制。

根据OS自动选择、或者手动选择加载文件

包括本地jar包和native库。可在pom.xml文件中使用profile标签,亲测有效:
在这里插入图片描述
其中 <activation> <os> <family>windows</family> </os> </activation>表示当操作系统是 Windows 时,此 Profile 将被自动激活。此Profile还配置了要包含的本地依赖,和mvn package时要复制的native库,具体内容都在前面介绍过了。

构建项目时既可以自动激活Profile,也可以直接指定Profile。比如指定ID为win的profile: mvn package -Pwin
在这里插入图片描述
但要注意一点:

各Profile之间没有互斥关系

这意味着当在windows环境下运行mvn package -Plinux, 不仅Profile linux会运行,Profile win也会因为它的activation标签满足OS条件而自动运行。这时可以加一个参数!: mvn package -Plinux -P!win , 明确表示不运行Profile win