springboot本地調(diào)試沒問題,打包運(yùn)行報(bào)錯(cuò)原因及分析
springboot本地調(diào)試沒問題,打包運(yùn)行報(bào)錯(cuò)原因分析
如果引用了本地jar包或者so庫
.dll庫等文件,需要在打包的時(shí)候都加載進(jìn)去。
如下圖:本地正常,打包的時(shí)候謹(jǐn)記,需要打包進(jìn)去,怎么驗(yàn)證是否打包成功呢?我們繼續(xù)看打包后的圖片。
把jar包后綴改成zip 格式的,打開壓縮文件,框內(nèi)路徑,查看libs下的包是否在里面可以找到。
如果可以找到就是打包進(jìn)去了,找不到的話,就是沒打包進(jìn)去,稍后我們?cè)僬f怎么打包進(jìn)去。
動(dòng)態(tài)庫也打包進(jìn)去了。
動(dòng)態(tài)庫打包進(jìn)去方式如下
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() { //根據(jù)操作系統(tǒng)判斷,如果是linux系統(tǒng)則加載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 { /** * 加載項(xiàng)目下的native文件,DLL或SO * * @param dirPath 需要掃描的文件路徑,項(xiàng)目下的相對(duì)路徑 * @throws IOException * @throws ClassNotFoundException */ public synchronized static void loader(String dirPath) throws IOException, ClassNotFoundException { Enumeration<URL> dir = Thread.currentThread().getContextClassLoader().getResources(dirPath); // 獲取操作系統(tǒng)類型 String systemType = System.getProperty("os.name"); //String systemArch = System.getProperty("os.arch"); // 獲取動(dòng)態(tài)鏈接庫后綴名 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 + "失敗!!請(qǐng)確認(rèn)操作系統(tǒng)是X86還是X64!!!"); } } } /** * @throws IOException * @throws ClassNotFoundException * @Title: scanJ * @Description 掃描Jar包下所有class */ /** * 創(chuàng)建動(dòng)態(tài)鏈接庫緩存文件,然后加載資源文件 * * @param jarEntry * @throws IOException * @throws ClassNotFoundException */ private static void loadJarNative(JarEntry jarEntry) throws IOException, ClassNotFoundException { File path = new File("."); //將所有動(dòng)態(tài)鏈接庫dll/so文件都放在一個(gè)臨時(shí)文件夾下,然后進(jìn)行加載 //這是應(yīng)為項(xiàng)目為可執(zhí)行jar文件的時(shí)候不能很方便的掃描里面文件 //此目錄放置在與項(xiàng)目同目錄下的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); // 如果緩存文件路徑不存在,則創(chuàng)建路徑 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 + "失敗!!請(qǐng)確認(rèn)操作系統(tǒng)是X86還是X64!!!"); } } }
運(yùn)行的時(shí)候,會(huì)在jar包所在目錄生成一個(gè)native文件夾,里面放的就是動(dòng)態(tài)庫
下面我們看一下本地jar包怎么打進(jìn)去
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默認(rèn)用jdk 1.5 maven2默認(rèn)用jdk1.3 --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <!-- 源代碼使用的JDK版本 --> <source>1.8</source> <!-- 需要生成的目標(biāo)class文件的編譯版本 --> <target>1.8</target> <!-- 字符集編碼 --> <encoding>UTF-8</encoding> <!-- 跳過測(cè)試 --> <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>
好了。動(dòng)態(tài)庫跟jar包都打包進(jìn)去了。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java 判斷兩個(gè)對(duì)象是否為同一個(gè)對(duì)象實(shí)例代碼
這篇文章主要介紹了java 判斷兩個(gè)對(duì)象是否為同一個(gè)對(duì)象實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-12-12在IDEA中實(shí)現(xiàn)生成Maven依賴關(guān)系圖
這篇文章主要介紹了在IDEA中實(shí)現(xiàn)生成Maven依賴關(guān)系圖方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07Java連接MySQL數(shù)據(jù)庫實(shí)例
這篇文章介紹了Java連接MySQL數(shù)據(jù)庫實(shí)例的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04如何在JDK 9中更簡(jiǎn)潔使用 try-with-resources 語句
本文詳細(xì)介紹了自 JDK 7 引入的 try-with-resources 語句的原理和用法,以及介紹了 JDK 9 對(duì) try-with-resources 的改進(jìn),使得用戶可以更加方便、簡(jiǎn)潔的使用 try-with-resources 語句。,需要的朋友可以參考下2019-06-06