springboot本地调试没问题,打包运行报错原因及分析
springboot本地调试没问题,打包运行报错原因分析
如果引用了本地jar包或者so库
.dll库等文件,需要在打包的时候都加载进去。
如下图:本地正常,打包的时候谨记,需要打包进去,怎么验证是否打包成功呢?我们继续看打包后的图片。
把jar包后缀改成zip 格式的,打开压缩文件,框内路径,查看libs下的包是否在里面可以找到。
如果可以找到就是打包进去了,找不到的话,就是没打包进去,稍后我们再说怎么打包进去。
动态库也打包进去了。
动态库打包进去方式如下
import org.opencv.core.Core; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author Arthur.yu * @date 2021/12/8 0008 */ @Configuration public class NativeConfig { static { } @Bean public void loadLib() { //根据操作系统判断,如果是linux系统则加载c++方法库 String systemType = System.getProperty("os.name"); String ext = (systemType.toLowerCase().indexOf("win") != -1) ? ".dll" : ".so"; // if (ext.equals(".so")) { try { NativeLoader.loader("native"); } catch (Exception e) { System.out.println("加载so库失败"); } // }else { // System.out.println("load --- dll === sucess"); // } System.out.println("loaded"); } }
import java.io.*; import java.net.JarURLConnection; import java.net.URL; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; /** * @author Arthur.yu * @date 2021/12/8 0008 */ public class NativeLoader { /** * 加载项目下的native文件,DLL或SO * * @param dirPath 需要扫描的文件路径,项目下的相对路径 * @throws IOException * @throws ClassNotFoundException */ public synchronized static void loader(String dirPath) throws IOException, ClassNotFoundException { Enumeration<URL> dir = Thread.currentThread().getContextClassLoader().getResources(dirPath); // 获取操作系统类型 String systemType = System.getProperty("os.name"); //String systemArch = System.getProperty("os.arch"); // 获取动态链接库后缀名 String ext = (systemType.toLowerCase().indexOf("win") != -1) ? ".dll" : ".so"; while (dir.hasMoreElements()) { URL url = dir.nextElement(); String protocol = url.getProtocol(); if ("jar".equals(protocol)) { JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection(); JarFile jarFile = jarURLConnection.getJarFile(); // 遍历Jar包 Enumeration<JarEntry> entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry jarEntry = entries.nextElement(); String entityName = jarEntry.getName(); if (jarEntry.isDirectory() || !entityName.startsWith(dirPath)) { continue; } if (entityName.endsWith(ext)) { loadJarNative(jarEntry); } } } else if ("file".equals(protocol)) { File file = new File(url.getPath()); loadFileNative(file, ext); } } } private static void loadFileNative(File file, String ext) { if (null == file) { return; } if (file.isDirectory()) { File[] files = file.listFiles(); if (null != files) { for (File f : files) { loadFileNative(f, ext); } } } if (file.canRead() && file.getName().endsWith(ext)) { try { System.load(file.getPath()); System.out.println("加载native文件 :" + file + "成功!!"); } catch (UnsatisfiedLinkError e) { System.out.println("加载native文件 :" + file + "失败!!请确认操作系统是X86还是X64!!!"); } } } /** * @throws IOException * @throws ClassNotFoundException * @Title: scanJ * @Description 扫描Jar包下所有class */ /** * 创建动态链接库缓存文件,然后加载资源文件 * * @param jarEntry * @throws IOException * @throws ClassNotFoundException */ private static void loadJarNative(JarEntry jarEntry) throws IOException, ClassNotFoundException { File path = new File("."); //将所有动态链接库dll/so文件都放在一个临时文件夹下,然后进行加载 //这是应为项目为可执行jar文件的时候不能很方便的扫描里面文件 //此目录放置在与项目同目录下的natives文件夹下 String rootOutputPath = path.getAbsoluteFile().getParent() + File.separator; String entityName = jarEntry.getName(); String fileName = entityName.substring(entityName.lastIndexOf("/") + 1); System.out.println(entityName); System.out.println(fileName); File tempFile = new File(rootOutputPath + File.separator + entityName); // 如果缓存文件路径不存在,则创建路径 if (!tempFile.getParentFile().exists()) { tempFile.getParentFile().mkdirs(); } // 如果缓存文件存在,则删除 if (tempFile.exists()) { tempFile.delete(); } InputStream in = null; BufferedInputStream reader = null; FileOutputStream writer = null; try { //读取文件形成输入流 in = NativeLoader.class.getResourceAsStream(entityName); if (in == null) { in = NativeLoader.class.getResourceAsStream("/" + entityName); if (null == in) { return; } } NativeLoader.class.getResource(fileName); reader = new BufferedInputStream(in); writer = new FileOutputStream(tempFile); byte[] buffer = new byte[1024]; while (reader.read(buffer) > 0) { writer.write(buffer); buffer = new byte[1024]; } } catch (IOException e) { e.printStackTrace(); } try { if (in != null) { in.close(); } if (writer != null) { writer.close(); } } catch (IOException e) { e.printStackTrace(); } try { System.out.println("path :" + tempFile.getPath()); System.load(tempFile.getPath()); System.out.println("加载native文件 :" + tempFile + "成功!!"); } catch (UnsatisfiedLinkError e) { System.out.println("加载native文件 :" + tempFile + "失败!!请确认操作系统是X86还是X64!!!"); } } }
运行的时候,会在jar包所在目录生成一个native文件夹,里面放的就是动态库
下面我们看一下本地jar包怎么打进去
jar包存放路径
pom 文件引用一下
<dependency> <groupId>org.opencv</groupId> <artifactId>opencv</artifactId> <version>0.0.1</version> <scope>system</scope> <systemPath>${project.basedir}/libs/opencv-343.jar</systemPath> </dependency>
pom打包配置
<build> <plugins> <!--参考文章:https://blog.csdn.net/liupeifeng3514/article/details/80236077--> <plugin> <!-- 指定maven编译的jdk版本,如果不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <!-- 源代码使用的JDK版本 --> <source>1.8</source> <!-- 需要生成的目标class文件的编译版本 --> <target>1.8</target> <!-- 字符集编码 --> <encoding>UTF-8</encoding> <!-- 跳过测试 --> <skip>true</skip> <compilerArguments> <extdirs>${project.basedir}/libs</extdirs> </compilerArguments> </configuration> </plugin> </plugins> <resources> <resource> <directory>${project.basedir}/libs/</directory> <targetPath>BOOT-INF\lib</targetPath> <includes> <include>**/*.jar</include> </includes> </resource> <resource> <directory>${project.basedir}/libs</directory> </resource> </resources> </build>
好了。动态库跟jar包都打包进去了。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
Java语言实现简单FTP软件 FTP软件效果图预览之下载功能(2)
这篇文章主要为大家详细介绍了Java语言实现简单FTP软件,FTP软件效果图预览之下载功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2017-03-03java开发web前端cookie session及token会话机制详解
如果把人体比作一个web系统的话,cookie、session和token就好像人体的经络和血管一样,而web系统中的数据,就好像人体的血液一样。血液依靠着血管在人体内流动,就如数据根据cookie和session机制在web系统中流动一样2021-10-10详解Spring整合mybatis--Spring中的事务管理(xml形式)
这篇文章主要介绍了Spring整合mybatis--Spring中的事务管理(xml形式),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2023-11-11IntelliJ IDEA 刷题利器 LeetCode 插件详解
这篇文章主要介绍了IntelliJ IDEA 刷题利器 LeetCode 插件,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2020-08-08基于Java的度分秒坐标转纯经纬度坐标的漂亮国基地信息管理的方法
本文以java语言为例,详细介绍如何管理漂亮国的基地信息,为下一步全球的空间可视化打下坚实的基础,首先介绍如何对数据进行去重处理,然后介绍在java当中如何进行度分秒位置的转换,最后结合实现原型进行详细的说明,感兴趣的朋友跟随小编一起看看吧2024-06-06
最新评论