Google Code 提供下列語言介面: English - Español - 日本語 - 한국어 - Português - Pусский - 中文(简体) - 中文(繁體)
如果您使用的不是 Eclipse (英文網頁) 和 「Eclipse 專用的 Google 外掛程式」,建議您使用其他方法來管理「應用服務引擎」應用程式的建立與測試程序。Apache Ant (英文網頁) 可以讓您輕鬆透過命令列或其他可以配合 Ant 的 IDE 來管理專案。Java SDK 包括一組 Ant 巨集,可執行一般的「應用服務引擎」開發工作,包括啟動開發伺服器以及上傳應用程式至「應用服務引擎」。
本篇文章將介紹一個 Ant 建置檔案,該檔案適用於絕大多數的專案。如要略過介紹,並直接前往提供複製的完整檔案,請參閱「完整建置檔案」。
如果您尚未在系統上安裝 Ant,請至 Apache Ant 網站下載並安裝。
安裝 Ant 之後,您的命令路徑會出現 ant 命令;您可以執行下列命令,以確定 Ant 可以正常運作,並查看您所安裝的版本。
ant -version
如「入門指南」所述,您的「應用服務引擎」專案必須使用 Java 網路應用程式的 WAR 標準配置,產生一個目錄結構。(SDK 尚未支援 WAR 封存檔案)。
如需詳細說明,我們會將專案相關的所有檔案放在 Guestbook/ 目錄 (專門存放「入門指南」描述的訪客留言板專案),當中的 src/ 子目錄專門存放 Java 原始程式碼,而 war/ 子目錄則專門存放完成的應用程式檔案。建置過程會編譯原始程式碼,再將編譯的 Java 位元組碼放到 war/ 底下的適當位置。之後建立的其他 WAR 檔案,應直接建立在 war/ 目錄中。
完整的專案目錄的結構如下:
Guestbook/
src/
...Java source code...
META-INF/
...other configuration...
war/
...JSPs, images, data files...
WEB-INF/
...app configuration...
classes/
...compiled classes...
lib/
...JARs for libraries...
如要透過命令提示建立這個目錄結構,請使用下列命令。如果您使用的是 Windows,請將這些路徑中的斜線 / 改為反斜線 \。(在 Ant 檔案中,使用斜線 / 的路徑適用於所有作業系統)。
mkdir Guestbook cd Guestbook mkdir -p src/META-INF mkdir -p war/WEB-INF/classes mkdir -p war/WEB-INF/lib
在 Guestbook/ 目錄中,建立名稱為 build.xml 的檔案,其內容如下:
<project>
<property name="sdk.dir" location="../appengine-java-sdk" />
<import file="${sdk.dir}/config/user/ant-macros.xml" />
</project>
這個建置檔案還不會執行任何動作,因為缺少一個提供工作執行指示的「目標」。檔案會定義兩個 Ant 屬性;之後我們定義目標與路徑時,將用到這兩個屬性。
sdk.dir 屬性是「應用服務引擎 Java SDK」的路徑,也就是解開 SDK 壓縮檔時所建立的 appengine-java-sdk 目錄。"../appengine-java-sdk" 會假設這個目錄是在專案目錄上一層的父目錄中。請視需求調整這個值。(路徑與 build.xml 檔案的位置是相對的)。
<import> 元素會載入一組「應用服務引擎 Java SDK」裡的 Ant 巨集,用於開發「應用服務引擎」。未來我們會用到其中數個巨集。
當您編譯類別時,Java 類別路徑必須包含「應用服務引擎 API」的 JAR,以及之前新增至專案 war/WEB-INF/lib/ 目錄的所有 JAR (例如 DataNucleus JDO/JPA JAR)。應用程式可以從這個目錄新增的 JAR 存取類別。此外,SDK lib/shared/ 目錄的 JAR 會出現在類別路徑中。
編輯 build.xml,再將下列字串加到結尾的 </project> 標記上方,即可定義包含這些 JAR 的類別路徑。
<path id="project.classpath">
<pathelement path="war/WEB-INF/classes" />
<fileset dir="war/WEB-INF/lib">
<include name="**/*.jar" />
</fileset>
<fileset dir="${sdk.dir}/lib">
<include name="shared/**/*.jar" />
</fileset>
</path>
您的應用程式必須在 war/WEB-INF/lib/ 目錄中包括 appengine-api-*.jar (其中 * 代表 API 和 SDK 的版本號碼),這是 SDK 所包含的一個 JAR。「應用服務引擎」會從這個 JAR 檢查類別,以判斷應用程式目前使用的 API 版本。如果您的應用程式使用 JDO 或 JPA 介面進入「應用服務引擎」資料存放區,則應用程式必須將 JDO/JPA 實作納入 war/WEB-INF/lib/。這些 JAR 全部包括在 SDK 的 lib/user/ 目錄中。
您可以手動將這些 JAR 複製到 WAR,但是建議您將複製 JAR 的工作納入建置過程。這可以確保應用程式使用的介面版本與 SDK 所包括的介面版本相同,即使之後升級 SDK 也不會有所差異。
所有 JAR 必須放在 war/WEB-INF/lib/ 目錄中,不可以出現在子目錄裡。這個 Ant 目標會使用 copy 工作的 flatten="true" 屬性 (attribute),從 ${sdk.dir}/lib/user/ 循環複製 JAR,因此所有 JAR 最終都會出現在相同目錄裡。
編輯 build.xml,再將下列字串加到結尾的 </project> 標記上方:
<target name="copyjars"
description="Copies the App Engine JARs to the WAR.">
<copy
todir="war/WEB-INF/lib"
flatten="true">
<fileset dir="${sdk.dir}/lib/user">
<include name="**/*.jar" />
</fileset>
</copy>
</target>
這會建立一個名稱為 "copyjars" 的建置目標,這個目標可以將 JAR 複製到適當的位置。如要測試這個目標,請確定目前的工作目錄是專案目錄 (Guestbook/),然後執行下列命令:
ant copyjars
檢查 war/WEB-INF/lib/ 的內容,以確認 JAR 確實在其中。
編輯 build.xml,再將下列字串加到結尾的 </project> 標記上方:
<target name="compile" depends="copyjars"
description="Compiles Java source and copies other source files to the WAR.">
<mkdir dir="war/WEB-INF/classes" />
<copy todir="war/WEB-INF/classes">
<fileset dir="src">
<exclude name="**/*.java" />
</fileset>
</copy>
<javac
srcdir="src"
destdir="war/WEB-INF/classes"
classpathref="project.classpath"
debug="on" />
</target>
這會定義一個名稱為 "compile" 的建置目標,這個目標可以編譯 src/ 目錄中的所有 Java 來源檔案,再將編譯的類別儲存在 war/WEB-INF/classes/ 當中。src/ 中的其他檔案 (例如 META-INF/ 目錄) 會逐一複製到 war/WEB-INF/classes/。這個目標需要依賴 "copyjars",因此需要時會建立這兩個目標。
如要編譯專案的來源檔案,請執行下列命令:
ant compile
本章節說明如何透過資料存放區的 Java Data Object (JDO) 介面支援,使用 Ant 建置自己的專案。如果您的專案沒有使用 JDO 介面,請前往下一章節。
如同「入門指南」以及資料存放區文件所述,JDO 介面可以讓您將類別的執行個體儲存到資料存放區,往後再以物件形式擷取。您必須透過類別定義中的 Java 註解,描述執行個體的儲存與擷取方式。
為使 JDO 看見註解,在您的資料類別經過編譯之後,您必須使用 DataNucleus Access Platform (與「應用服務引擎」一同發佈的 JDO 實作) 所包括的工具,處理資料類別的位元組碼。DataNucleus 形容這個程序為「強化」類別。
「應用服務引擎 SDK」包括 Ant 巨集,可用於強化 JDO 資料類別。<enhance_war> 巨集會透過專案的正確類別路徑,強化專案中的每個 JDO 資料類別。如需更精確的控制,請使用 <enhance> 巨集。
編輯 build.xml,再將下列字串加到結尾的 </project> 標記上方:
<target name="datanucleusenhance" depends="compile"
description="Performs JDO enhancement on compiled data classes.">
<enhance_war war="war" />
</target>
這個目標需要依賴 "compile",因此這個目標的建置可以在執行強化工作之前,確保類別是已經完成編譯的最新類別。
您可以使用 Ant 巨集執行開發網頁伺服器。您可以透過一個簡單的命令,建立自己的專案並啟動伺服器,只要使這個目標依賴 "datanucleusenhance"目標 (如未使用 DataNucleus 時,則是 "compile" 目標) 即可。
編輯 build.xml,再將下列字串加到結尾的 </project> 標記上方:
<target name="runserver" depends="datanucleusenhance"
description="Starts the development server.">
<dev_appserver war="war" />
</target>
您可以使用屬性 (attribute) 以及 <options> 元素設定開發伺服器的引數。例如,下列目標會使用 8888 連接埠啟動伺服器,並在 9999 連接埠啟用遠端 Java 偵錯:
<target name="runserver" depends="datanucleusenhance"
description="Starts the development server.">
<dev_appserver war="war" port="8888" >
<options>
<arg value="--jvm_flag=-Xdebug"/>
<arg value="--jvm_flag=-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=9999"/>
</options>
</dev_appserver>
</target>
如要建置專案並執行伺服器,請使用下列命令:
ant runserver
如要停止伺服器,請按下 Ctrl-C。
您可以定義 Ant 工作,將應用程式上傳至「應用服務引擎」,並執行 AppCfg 提供的其他動作。
<appcfg> 巨集會將動作的名稱視為 action 屬性 (attribute) ,並將專案的 WAR 路徑視為 war 屬性 (attribute) 。這個元素可以選用 <options> 和 <args> 元素。
編輯 build.xml,然後加上下列字串:
<target name="update" depends="datanucleusenhance"
description="Uploads the application to App Engine.">
<appcfg action="update" war="war" />
</target>
<target name="update_indexes" depends="datanucleusenhance"
description="Uploads just the datastore index configuration to App Engine.">
<appcfg action="update_indexes" war="war" />
</target>
<target name="rollback" depends="datanucleusenhance"
description="Rolls back an interrupted application update.">
<appcfg action="rollback" war="war" />
</target>
<target name="request_logs"
description="Downloads log data from App Engine for the application.">
<appcfg action="request_logs" war="war">
<options>
<arg value="--num_days=5"/>
</options>
<args>
<arg value="logs.txt"/>
</args>
</appcfg>
</target>
此處為上述說明所提及的完整 build.xml 檔案:
<project>
<property name="sdk.dir" location="../appengine-java-sdk" />
<import file="${sdk.dir}/config/user/ant-macros.xml" />
<path id="project.classpath">
<pathelement path="war/WEB-INF/classes" />
<fileset dir="war/WEB-INF/lib">
<include name="**/*.jar" />
</fileset>
<fileset dir="${sdk.dir}/lib">
<include name="shared/**/*.jar" />
</fileset>
</path>
<target name="copyjars"
description="Copies the App Engine JARs to the WAR.">
<copy
todir="war/WEB-INF/lib"
flatten="true">
<fileset dir="${sdk.dir}/lib/user">
<include name="**/*.jar" />
</fileset>
</copy>
</target>
<target name="compile" depends="copyjars"
description="Compiles Java source and copies other source files to the WAR.">
<mkdir dir="war/WEB-INF/classes" />
<copy todir="war/WEB-INF/classes">
<fileset dir="src">
<exclude name="**/*.java" />
</fileset>
</copy>
<javac
srcdir="src"
destdir="war/WEB-INF/classes"
classpathref="project.classpath"
debug="on" />
</target>
<target name="datanucleusenhance" depends="compile"
description="Performs JDO enhancement on compiled data classes.">
<enhance_war war="war" />
</target>
<target name="runserver" depends="datanucleusenhance"
description="Starts the development server.">
<dev_appserver war="war" />
</target>
<target name="update" depends="datanucleusenhance"
description="Uploads the application to App Engine.">
<appcfg action="update" war="war" />
</target>
<target name="update_indexes" depends="datanucleusenhance"
description="Uploads just the datastore index configuration to App Engine.">
<appcfg action="update_indexes" war="war" />
</target>
<target name="rollback" depends="datanucleusenhance"
description="Rolls back an interrupted application update.">
<appcfg action="rollback" war="war" />
</target>
<target name="request_logs"
description="Downloads log data from App Engine for the application.">
<appcfg action="request_logs" war="war">
<options>
<arg value="--num_days=5"/>
</options>
<args>
<arg value="logs.txt"/>
</args>
</appcfg>
</target>
</project>