1.問題發現
? ? ? ?項目中有個common包資源文件,然后springboot項目引用了common,那么我們要怎么讀取這個資源了。這里需要考慮三個場景,idea運行時、common jar獨立運行時、springboot引用common后運行時。
2.問題解決
2.1.idea運行時
ProtectionDomain protectionDomain = LibPaths.class.getProtectionDomain();CodeSource codeSource = protectionDomain.getCodeSource();if (codeSource != null) {String jarPath = codeSource.getLocation().getPath();jarPath = jarPath.replaceFirst("^nested:", "");if(!jarPath.endsWith(".jar")){System.out.println("idea運行時classes路徑");}
2.2.common jar運行時?
public static String getUrl(){ProtectionDomain protectionDomain = LibPaths.class.getProtectionDomain();CodeSource codeSource = protectionDomain.getCodeSource();if (codeSource != null) {String jarPath = codeSource.getLocation().getPath();jarPath = jarPath.replaceFirst("^nested:", "");System.out.println("JAR 文件路徑: " + jarPath);if(jarPath != null){int index = jarPath.indexOf(".jar");String destDir = jarPath;if(index != -1){destDir = new File(jarPath.substring(0, index+4)).getParent();}if(jarPath.endsWith(".jar")){copyJarCuToOut(jarPath,destDir)}else{System.out.println("idea運行時classes路徑");}}
}public static void copyJarCuToOut(String jarPath,String destDir) throws IOException {File file = new File(destDir + File.separator + "test");if(!file.exists()){file.mkdirs();copyResourcesFromJar(jarPath,destDir, true);}else{System.out.println(file.getPath() + "已存在");}
}/*** 將 JAR 中指定路徑下的所有文件復制到目標目錄** @param jarFilePath JAR 文件的路徑* @param resourcePath JAR 中的資源路徑(例如 "resources/")* @param destDir 目標輸出目錄* @throws IOException 如果復制過程中出現錯誤*/
public static void copyResourcesFromJar(String jarFilePath, String resourcePath, String destDir) throws IOException {try (JarFile jarFile = new JarFile(jarFilePath)) {Enumeration<JarEntry> entries = jarFile.entries();while (entries.hasMoreElements()) {JarEntry entry = entries.nextElement();if (entry.getName().startsWith(resourcePath) && !entry.isDirectory() && ( entry.getName().endsWith(".cu") || entry.getName().endsWith(".cu.h"))) {// 構建目標路徑Path destPath = Paths.get(destDir + File.separator + entry.getName().substring(resourcePath.length()));// 復制文件try (InputStream is = jarFile.getInputStream(entry);OutputStream os = Files.newOutputStream(destPath)) {byte[] buffer = new byte[1024];int len;while ((len = is.read(buffer)) > 0) {os.write(buffer, 0, len);}}System.out.println("已復制: " + entry.getName() + " 到 " + destPath);}}}
}
2.3.springboot jar運行時??
public static String getUrl(){ProtectionDomain protectionDomain = LibPaths.class.getProtectionDomain();CodeSource codeSource = protectionDomain.getCodeSource();if (codeSource != null) {String jarPath = codeSource.getLocation().getPath();jarPath = jarPath.replaceFirst("^nested:", "");System.out.println("JAR 文件路徑: " + jarPath);if(jarPath != null){int index = jarPath.indexOf(".jar");String destDir = jarPath;if(index != -1){destDir = new File(jarPath.substring(0, index+4)).getParent();}if(jarPath.endsWith(".jar")){copyJarCuToOut(jarPath,destDir)}else{System.out.println("idea運行時classes路徑");}}
}public static void copyJarCuToOut(String jarPath,String destDir) throws IOException {File file = new File(destDir + File.separator + "test");if(!file.exists()){file.mkdirs();copyResourcesFromMultipleJar(jarPath,destDir, true);}else{System.out.println(file.getPath() + "已存在");}
}/*** 將 JAR 中指定路徑下的所有文件復制到目標目錄** @param jarFilePath JAR 文件的路徑* @param resourcePath JAR 中的資源路徑(例如 "resources/")* @param destDir 目標輸出目錄* @throws IOException 如果復制過程中出現錯誤*/
public static void copyResourcesFromMultipleJar(String jarFilePath, String resourcePath, String destDir) throws IOException {// 1. 分離路徑部分String[] parts = jarFilePath.split("/!");if (parts.length < 2) {throw new IllegalArgumentException("無效的嵌套 JAR 路徑格式");}// 2. 解析外層 JAR 路徑(去掉開頭的 / 和 !/)String outerJarPath = parts[0];String innerJarEntry = parts[1].replace("!/", "");System.out.println("###################" + outerJarPath);// 3. 打開外層 JARtry (JarFile outerJar = new JarFile(outerJarPath)) {// 4. 獲取內層 JAR 的 EntryJarEntry innerEntry = outerJar.getJarEntry(innerJarEntry);if (innerEntry == null) {throw new FileNotFoundException("內層 JAR 不存在: " + innerJarEntry);}System.out.println("innerJarEntry###################" + innerJarEntry);try (InputStream innerIs = outerJar.getInputStream(innerEntry); JarInputStream innerJar = new JarInputStream(innerIs)) {JarEntry entry;while ((entry = innerJar.getNextJarEntry()) != null) {if (entry.getName().startsWith(resourcePath) && !entry.isDirectory()) {// 構建目標路徑Path destPath = Paths.get(destDir + File.separator + entry.getName().substring(resourcePath.length()));// 復制文件try (OutputStream os = Files.newOutputStream(destPath)) {byte[] buffer = new byte[1024];int len;while ((len = innerJar.read(buffer)) > 0) {os.write(buffer, 0, len);}}System.out.println("已復制: " + entry.getName() + " 到 " + destPath);}}}}}
2.4.完整代碼
package com.omega.common.lib;import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;public class LibPaths {static {try {// 獲取 ProtectionDomain 和 CodeSourceProtectionDomain protectionDomain = LibPaths.class.getProtectionDomain();CodeSource codeSource = protectionDomain.getCodeSource();if (codeSource != null) {String jarPath = codeSource.getLocation().getPath();jarPath = jarPath.replaceFirst("^nested:", "");System.out.println("JAR 文件路徑: " + jarPath);if(jarPath != null){int index = jarPath.indexOf(".jar");String destDir = jarPath;if(index != -1){destDir = new File(jarPath.substring(0, index+4)).getParent();}if(jarPath.endsWith(".jar")){copyJarCuToOut(jarPath,destDir, false);}else if(jarPath.endsWith(".jar!/")){copyJarCuToOut(jarPath,destDir, true);}LIB_PATH = destDir + File.separator + "test";}else{System.out.println("JAR 文件路徑為空");}} else {System.out.println("無法獲取 JAR 路徑(可能來自系統類加載器)");}} catch (IOException e) {e.printStackTrace();}}public static void copyJarCuToOut(String jarPath,String destDir, boolean multiple) throws IOException {File file = new File(destDir + File.separator + "test");if(!file.exists()){file.mkdirs();if(multiple){copyResourcesFromMultipleJar(jarPath, "test", file.getPath());}else{copyResourcesFromJar(jarPath, "test", file.getPath());}}else{System.out.println(file.getPath() + "已存在");}}/*** 將 JAR 中指定路徑下的所有文件復制到目標目錄** @param jarFilePath JAR 文件的路徑* @param resourcePath JAR 中的資源路徑(例如 "resources/")* @param destDir 目標輸出目錄* @throws IOException 如果復制過程中出現錯誤*/public static void copyResourcesFromJar(String jarFilePath, String resourcePath, String destDir) throws IOException {try (JarFile jarFile = new JarFile(jarFilePath)) {Enumeration<JarEntry> entries = jarFile.entries();while (entries.hasMoreElements()) {JarEntry entry = entries.nextElement();if (entry.getName().startsWith(resourcePath) && !entry.isDirectory() && ( entry.getName().endsWith(".cu") || entry.getName().endsWith(".cu.h"))) {// 構建目標路徑Path destPath = Paths.get(destDir + File.separator + entry.getName().substring(resourcePath.length()));// 復制文件try (InputStream is = jarFile.getInputStream(entry);OutputStream os = Files.newOutputStream(destPath)) {byte[] buffer = new byte[1024];int len;while ((len = is.read(buffer)) > 0) {os.write(buffer, 0, len);}}System.out.println("已復制: " + entry.getName() + " 到 " + destPath);}}}}/*** 將 JAR 中指定路徑下的所有文件復制到目標目錄** @param jarFilePath JAR 文件的路徑* @param resourcePath JAR 中的資源路徑(例如 "resources/")* @param destDir 目標輸出目錄* @throws IOException 如果復制過程中出現錯誤*/public static void copyResourcesFromMultipleJar(String jarFilePath, String resourcePath, String destDir) throws IOException {// 1. 分離路徑部分String[] parts = jarFilePath.split("/!");if (parts.length < 2) {throw new IllegalArgumentException("無效的嵌套 JAR 路徑格式");}// 2. 解析外層 JAR 路徑(去掉開頭的 / 和 !/)String outerJarPath = parts[0];String innerJarEntry = parts[1].replace("!/", "");System.out.println("###################" + outerJarPath);// 3. 打開外層 JARtry (JarFile outerJar = new JarFile(outerJarPath)) {// 4. 獲取內層 JAR 的 EntryJarEntry innerEntry = outerJar.getJarEntry(innerJarEntry);if (innerEntry == null) {throw new FileNotFoundException("內層 JAR 不存在: " + innerJarEntry);}System.out.println("innerJarEntry###################" + innerJarEntry);try (InputStream innerIs = outerJar.getInputStream(innerEntry); JarInputStream innerJar = new JarInputStream(innerIs)) {JarEntry entry;while ((entry = innerJar.getNextJarEntry()) != null) {if (entry.getName().startsWith(resourcePath) && !entry.isDirectory()) {// 構建目標路徑Path destPath = Paths.get(destDir + File.separator + entry.getName().substring(resourcePath.length()));// 復制文件try (OutputStream os = Files.newOutputStream(destPath)) {byte[] buffer = new byte[1024];int len;while ((len = innerJar.read(buffer)) > 0) {os.write(buffer, 0, len);}}System.out.println("已復制: " + entry.getName() + " 到 " + destPath);}}}}}}