最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot打包后讀取JAR包同級目錄的外部文件的方法匯總

 更新時間:2026年04月07日 08:55:43   作者:用戶030480591263  
在平時的項目開發(fā)中,我們經常會遇到這樣的需求:項目中有一個 template 文件夾,我們希望在代碼中去讀取它,因此,更優(yōu)雅的做法是:將 template 文件夾放在項目根目錄,并在打包后,讓它與 JAR 包處于同級目錄,本文將手把手教你如何實現這個需求,需要的朋友可以參考下

背景與痛點

在平時的項目開發(fā)中,我們經常會遇到這樣的需求:項目中有一個 template 文件夾(比如存放 Word、Excel 模板,或者 Freemarker/HTML 模板),我們希望在代碼中去讀取它。

如果是直接放在 src/main/resources 下,打包后文件會被打進 JAR 包內部。這就帶來一個問題:如果生產環(huán)境下需要修改模板內容,就必須重新打包發(fā)布,非常不方便。

因此,更優(yōu)雅的做法是:template 文件夾放在項目根目錄,并在打包后,讓它與 JAR 包處于同級目錄。代碼去讀取這個外部文件夾。

本文將手把手教你如何實現這個需求,并避開路徑解析中的常見“坑”。

避坑指南:為什么不建議直接用./template?

很多開發(fā)者直覺上會寫出這樣的代碼:

File templateDir = new File("./template");

結論:能用,但有非常大的隱患!

在 Java 中,./ 代表的是當前工作目錄(Current Working Directory),等同于 System.getProperty("user.dir")。它的致命弱點在于:它依賴于“你在哪里敲的啟動命令”,而不是“JAR 包在哪里”。

  • 場景 1(正常):cd 到了 JAR 包所在的目錄,然后執(zhí)行 java -jar app.jar。此時 ./ 就是 JAR 包所在目錄,讀取成功。
  • 場景 2(報錯): 你的 JAR 包在 /app/my-project/ 下,但你在系統(tǒng)根目錄啟動項目:
cd /
java -jar /app/my-project/app.jar

此時,Java 認為的 ./ 是根目錄 /!程序會去尋找 /template,結果自然是找不到文件

  • 場景 3(報錯): 將 Spring Boot 配置為 Linux 的 Systemd 服務啟動時,如果沒有嚴格配置 WorkingDirectory,默認路徑也會導致找不到文件。

為了代碼的健壯性,我們需要使用絕對路徑來定位 JAR 包!

核心方案:精準定位 JAR 包所在目錄

方法 1:Spring Boot 的極簡寫法(強烈推薦)

如果你使用的是 Spring Boot 項目,Spring 官方提供了一個非常貼心的類 ApplicationHome。它可以自動判斷當前是處于 IDE 環(huán)境還是 JAR 包運行環(huán)境,并牢牢鎖定真實的根目錄。

import org.springframework.boot.system.ApplicationHome;
import java.io.File;
public class TemplateReader {
    public void readTemplates() {
        // 獲取當前程序所在的根目錄 (IDE中是項目根目錄,打包后是 jar 包所在目錄)
        ApplicationHome home = new ApplicationHome(getClass());
        File rootDir = home.getDir();
        // 拼接出 template 目錄的絕對路徑
        File templateDir = new File(rootDir, "template");
        if (templateDir.exists() && templateDir.isDirectory()) {
            System.out.println("成功找到 template 目錄: " + templateDir.getAbsolutePath());
            File[] files = templateDir.listFiles();
            if (files != null) {
                for (File file : files) {
                    System.out.println("讀取到文件: " + file.getName());
                    // 在這里處理你的文件邏輯...
                }
            }
        } else {
            System.out.println("未找到 template 目錄,請檢查路徑: " + templateDir.getAbsolutePath());
        }
    }
}

方法 2:原生 Java 通用寫法(適用于非 Spring 項目)

如果你使用的是普通的 Java Maven 項目,可以通過 ProtectionDomain 獲取當前類的實際運行物理路徑,然后反推根目錄:

import java.io.File;
import java.net.URLDecoder;

public class NativeTemplateReader {

    private static File getTemplateDir() {
        try {
            // 獲取當前類的代碼源路徑
            String path = NativeTemplateReader.class.getProtectionDomain().getCodeSource().getLocation().getPath();
            path = URLDecoder.decode(path, "UTF-8"); // 防止路徑中的中文或空格被 URLEncode
            File file = new File(path);

            File rootDir;
            if (file.isFile() && path.endsWith(".jar")) {
                // 環(huán)境:打包后的 jar 運行,根目錄就是 jar 包所在的父目錄
                rootDir = file.getParentFile();
            } else {
                // 環(huán)境:IDE (如 IDEA) 中運行,退回項目根目錄
                rootDir = new File(System.getProperty("user.dir")); 
            }

            return new File(rootDir, "template");

        } catch (Exception e) {
            // 兜底方案
            return new File(System.getProperty("user.dir"), "template");
        }
    }
}

工程化進階:讓 Maven 打包時自動復制文件夾

代碼寫好了,但每次執(zhí)行 mvn clean package 打包后,我們還需要手動把根目錄的 template 文件夾復制到 target 目錄下,和 jar 包放在一起,太繁瑣了!

我們可以通過配置 maven-resources-plugin 插件,讓 Maven 在打包時自動完成復制。

1. 規(guī)范的項目結構

首先確保你的項目目錄長這樣:

my-project/
 ├── src/
 │    └── main/java/...
 ├── template/          <-- 放在項目根目錄下,與 src 同級
 │    ├── test1.txt
 │    └── test2.html
 └── pom.xml

2. 修改 pom.xml

<build><plugins> 節(jié)點下添加以下配置:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>3.2.0</version>
    <executions>
        <execution>
            <id>copy-template-folder</id>
            <!-- 在打包(package)階段執(zhí)行 -->
            <phase>package</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <!-- 復制的目標位置:打包后的 target 目錄下的 template 文件夾 -->
                <outputDirectory>${project.build.directory}/template</outputDirectory>
                <resources>
                    <resource>
                        <!-- 復制的源位置:項目根目錄下的 template 文件夾 -->
                        <directory>${project.basedir}/template</directory>
                        <filtering>false</filtering>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>

最終效果驗證

  1. 開發(fā)階段:直接在 IDEA 中運行,代碼會精準讀取項目根目錄下的 template 文件夾。
  2. 打包階段:執(zhí)行 mvn clean package。你會發(fā)現 target 目錄下不僅有 xxx.jar,旁邊還自動多出了一個 template 文件夾。
  3. 部署階段:把 target 目錄下的 jar 包和 template 文件夾一起丟到服務器上。無論你用什么姿勢(跨目錄、寫腳本、systemd)啟動項目,代碼都能穩(wěn)穩(wěn)地讀取到外部的模板文件。
  4. 后期運維:需要改模板?直接替換服務器上 template 里的文件即可,無需重啟!無需重新打包!

總結

  • 讀取外部同級文件,不要直接用 ./,容易因為啟動目錄不同而產生 BUG。
  • Spring Boot 項目無腦使用 ApplicationHome。
  • 結合 Maven maven-resources-plugin 插件,可以實現絲滑的自動化打包體驗。

以上就是SpringBoot打包后讀取JAR包同級目錄的外部文件的方法匯總的詳細內容,更多關于SpringBoot打包后讀取JAR包外部文件的資料請關注腳本之家其它相關文章!

相關文章

  • Spring-webflux?響應式編程的實例詳解

    Spring-webflux?響應式編程的實例詳解

    Spring 提供了兩個并行堆棧,一種是基于帶有 Spring MVC 和 Spring Data 結構的 Servlet API,另一個是完全反應式堆棧,它利用了 Spring WebFlux 和 Spring Data 的反應式存儲庫,這篇文章主要介紹了Spring-webflux?響應式編程,需要的朋友可以參考下
    2022-09-09
  • java開發(fā)RocketMQ生產者高可用示例詳解

    java開發(fā)RocketMQ生產者高可用示例詳解

    這篇文章主要為大家介紹了java開發(fā)RocketMQ生產者高可用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • SpringBoot多模塊依賴沖突排查與架構優(yōu)化實戰(zhàn)

    SpringBoot多模塊依賴沖突排查與架構優(yōu)化實戰(zhàn)

    本文詳細記錄了在SpringBoot多模塊項目開發(fā)中遇到的依賴版本沖突、模塊依賴設計不合理等問題的排查和解決方案的過程,主要重點關注了父模塊依賴管理、模塊化拆分、按需依賴等等,需要的朋友可以參考下
    2026-04-04
  • springMVC實現前臺帶進度條文件上傳的示例代碼

    springMVC實現前臺帶進度條文件上傳的示例代碼

    本篇文章主要介紹了springMVC實現前臺帶進度條文件上傳的示例代碼,具有一定的參考價值,有興趣的可以了解一下。
    2017-01-01
  • Java五子棋簡單實現代碼舉例

    Java五子棋簡單實現代碼舉例

    Java五子棋游戲是一種經典的兩人對戰(zhàn)棋類游戲,它基于簡單的規(guī)則,即任何一方的棋子在棋盤上形成連續(xù)的五個,無論是橫、豎還是斜線,都將獲勝,這篇文章主要介紹了Java五子棋實現的相關資料,需要的朋友可以參考下
    2024-10-10
  • Java中定時任務的全方位場景實現思路分析

    Java中定時任務的全方位場景實現思路分析

    在開發(fā)過程中,根據需求和業(yè)務的不同經常會有很多場景需要用到不同特性的定時任務,本文將針對這些場景,提供不同的一個實現思路,感興趣的小伙伴快跟隨小編一起學習一下吧
    2023-12-12
  • mybatis-plus多表關聯查詢功能的實現

    mybatis-plus多表關聯查詢功能的實現

    本文給大家介紹mybatis-plus多表關聯查詢功能的實現代碼,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-11-11
  • Java數據結構之循環(huán)隊列簡單定義與用法示例

    Java數據結構之循環(huán)隊列簡單定義與用法示例

    這篇文章主要介紹了Java數據結構之循環(huán)隊列簡單定義與用法,簡要描述了循環(huán)隊列的概念、原理,并結合實例形式分析了java循環(huán)隊列的定義與使用方法,需要的朋友可以參考下
    2017-10-10
  • java使用udp實現簡單多人聊天功能

    java使用udp實現簡單多人聊天功能

    這篇文章主要為大家詳細介紹了java使用udp實現簡單多人聊天功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Hadoop?MapReduce實現單詞計數(Word?Count)

    Hadoop?MapReduce實現單詞計數(Word?Count)

    這篇文章主要為大家詳細介紹了如何利用Hadoop實現單詞計數(Word?Count)的MapReduce,文中的示例代碼講解詳細,感興趣的可以跟隨小編一起學習一下
    2023-05-05

最新評論

建湖县| 博爱县| 正宁县| 宜章县| 富民县| 清流县| 赤峰市| 荃湾区| 自治县| 甘洛县| 台北市| 东山县| 安顺市| 红河县| 盈江县| 荣昌县| 观塘区| 明光市| 奉新县| 建水县| 济源市| 繁昌县| 呼玛县| 察哈| 杭州市| 盘山县| 屏东县| 麟游县| 韶关市| 漠河县| 麻江县| 博湖县| 正宁县| 阜宁县| 红河县| 富锦市| 色达县| 科技| 潍坊市| 延长县| 无极县|