start.sh、run-server.sh、test.sh...)target/classes、target/dependency,打包後指向 lib/run-javaconfig/、lib/*.jar、target/classes、target/test-classes、target/dependency/*-Dprop=val、-cp extra.jar 可放在主類別之後RUN_JAVA_DRY=1 僅印出完整 java 指令,不執行# 專案結構
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
<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 啟動腳本的碎片化問題。它不僅是個腳本,更是一種「標準化啟動協議」:專案只需遵循目錄慣例,即可獲得開發、測試、生產環境一致的啟動體驗。建議將其納入組織內部脚手架模板,消除重複造輪子的浪費。