首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

run-java:通用 Java 啟動腳本封裝最佳實踐,解決 Classpath、參數傳遞、跨平台難題

     編輯:Java 相關知識

痛點:為什麼需要 run-java?

  • 手寫啟動腳本易出錯:Classpath 拼接、引號轉義、Windows/Linux 路徑分隔符差異
  • 專案常產生大量冗餘腳本(start.sh、run-server.sh、test.sh...)
  • Maven 專案開發期需指向 target/classes、target/dependency,打包後指向 lib/

run-java 設計哲學

  1. 單一入口:所有啟動腳本皆委派給 run-java
  2. 自動偵測 Classpath:掃描 config/、lib/*.jar、target/classes、target/test-classes、target/dependency/*
  3. 支援標準 Java 選項:-Dprop=val、-cp extra.jar 可放在主類別之後
  4. Dry-run 模式:RUN_JAVA_DRY=1 僅印出完整 java 指令,不執行
  5. 跨平台:Linux/macOS/Cygwin 通用,自動處理路徑轉換

使用範例

# 專案結構
myapp/
├── bin/run-java
├── lib/*.jar
├── config/
└── target/{classes,test-classes,dependency/*}  (開發期)

# 直接啟動主類別
bin/run-java com.myapp.Main

# 傳遞系統屬性與額外 classpath
bin/run-java -Denv=prod -cp "/opt/extra/*" com.myapp.Main

# 僅印出完整指令(除錯用)
RUN_JAVA_DRY=1 bin/run-java com.myapp.Main

# Maven 開發期一鍵啟動
mvn compile dependency:copy-dependencies
bin/run-java com.myapp.Main  # 自動掃描 target/dependency 等

核心邏輯解析(腳本精簡版)

#!/usr/bin/env bash
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
APP_DIR=$(cd "$SCRIPT_DIR/.." && pwd)

# 預設參數(可被環境變數覆蓋)
JAVA_HOME=${JAVA_HOME:=/apps/jdk}
RUN_JAVA_CP=${RUN_JAVA_CP:=$CLASSPATH}
RUN_JAVA_OPTS=${RUN_JAVA_OPTS:=}
RUN_JAVA_DRY=${RUN_JAVA_DRY:=}

# 自動組裝 Classpath(若未設定 RUN_JAVA_NO_AUTOCP)
if [ -z "$RUN_JAVA_NO_AUTOCP" ]; then
    # 掃描標準目錄,存在才加入
    for d in config target/test-classes target/classes target/dependency lib; do
        if [ -d "$APP_DIR/$d" ]; then
            RUN_JAVA_CP="$RUN_JAVA_CP:$APP_DIR/$d"  # Cygwin 下自動轉換為 ;
        fi
    done
    # dependency 目錄下所有 jar 用 *
    [ -d "$APP_DIR/target/dependency" ] && RUN_JAVA_CP="$RUN_JAVA_CP:$APP_DIR/target/dependency/*"
    [ -d "$APP_DIR/lib" ] && RUN_JAVA_CP="$RUN_JAVA_CP:$APP_DIR/lib/*"
fi

# 解析主類別後的 -cp 與 -D 選項(支援放在最後)
if [ -z "$RUN_JAVA_NO_PARSE" ]; then
    NEW_ARGS=()
    FOUND_CP=
    for arg in "$@"; do
        if [ -n "$FOUND_CP" ]; then
            RUN_JAVA_CP="$RUN_JAVA_CP:$arg"; FOUND_CP=
        else
            case $arg in
                -cp) FOUND_CP=1 ;;
                -D*) RUN_JAVA_OPTS="$RUN_JAVA_OPTS $arg" ;;
                *) NEW_ARGS+=("$arg") ;;
            esac
        fi
    done
    set -- "${NEW_ARGS[@]}"
fi

# 執行或 Dry-run
JAVA_CMD="$JAVA_HOME/bin/java"
if [ -n "$RUN_JAVA_DRY" ] || [ -n "$RUN_JAVA_DEBUG" ]; then
    echo "$JAVA_CMD $RUN_JAVA_OPTS -cp \"$RUN_JAVA_CP\" \"$@\""
fi
if [ -z "$RUN_JAVA_DRY" ]; then
    exec "$JAVA_CMD" $RUN_JAVA_OPTS -cp "$RUN_JAVA_CP" "$@"
fi

整合到 Maven 專案

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <configuration>
    <descriptors>
      <descriptor>src/assembly/bin.xml</descriptor>  <!-- 包含 run-java -->
    </descriptors>
  </configuration>
</plugin>

打包時自動將 run-java 放入 bin/,dependency:copy-dependencies 輸出至 target/dependency,開發與生產環境零差異啟動。

結語

run-java 以 約定優於配置 解決 Java 啟動腳本的碎片化問題。它不僅是個腳本,更是一種「標準化啟動協議」:專案只需遵循目錄慣例,即可獲得開發、測試、生產環境一致的啟動體驗。建議將其納入組織內部脚手架模板,消除重複造輪子的浪費。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved