在〈第一個 Servlet〉中曾簡介過 Web 應用程式目錄架構,這邊再作個詳細的說明。
一個 Web 應用程式基本上會由以下項目所組成:
- 靜態資源(HTML、圖片、聲音等)
- Servlet
- JSP
- 自定義類別
- 工具類別
- 部署描述檔(web.xml等)、設定資訊(Annotation等)
Web 應用程式存在既定的目錄結構。舉例來說,如果一個應用程式的環境路徑(Context path)是 /openhome,則所有的資源項目必須以 /openhome 為根目錄依一定的結構擺放。基本上根目錄中的資源可以直接下載,例如若 index.html 位在 /openhome 下,則可以直接以 /openhome/index.html 來取得。
Web 應用程式存在一個特殊的 /WEB-INF 目錄,此目錄中存在的 資源項目不會被列入應用程式根目錄中可直接存取的項目,也就是說,客戶端(例如瀏覽器)不可以直接請求 /WEB-INF 中的資源(直接在網址上指明存取 /WEB-INF),否則就是 404 Not Found 的錯誤結果。
WEB-INF中的資源項目有著一定的名稱與結構。例如:
- /WEB-INF/web.xml 是部署描述檔
- /WEB-INF/classes 用來放置應用程式所用到的自定義類別(.class),必須包括套件(Package)結構
- /WEB-INF/lib 用來放置應用程式所用到的 JAR(Java ARchive)檔案
Web 應用程式所用到的JAR檔案,當中可以放置 Servlet、JSP、自定義類別、工具類別、部署描述檔等,應用程式的類別載入器可以從 JAR 中載入對應的資源。
你可以在 JAR 檔案的 /META-INF/resources 目錄中放置靜態資源或 JSP 等,例如若在 /META-INF/resources 中放個 index.html,若請求的 URL 中包括 /openhome/index.html,但實際上 /openhome 根目錄底下不存在 index.html,則 JAR 中的 /META- INF/resources/index.html 會被使用。
如果你要到用到某個類別,則 Web 應用程式會到 /WEB-INF/classes 中試著載入類別,若無,再試著從 /WEB-INF/lib 的 JAR 檔案中尋找類別檔案(若還沒有找到,則會到容器實作本身存放類別或 JAR 的目錄中尋找,但位置視實作廠商而有所不同)。
客戶端不可以直接請求 /WEB-INF 中的資源,但你可以透過程式面的控管,讓程式來取得 /WEB-INF 中的資源,像是使用 ServletContext
的 getResource()
與 getResourceAsStream()
,或是透過 RequestDispatcher
請求調派。
如果對 Web 應用程式的 URL 最後是以 /
結尾,而且確實存在該目錄,則 Web 容器必須傳回該目錄下的歡迎頁面, 你可以在部署描述檔 web.xml 中包括以下的定義,指出可用的歡迎頁面名稱為何,Web 容器會依序看看是否有對應的檔案存在,如果有則傳回給客戶端:
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
如果找不到以上的檔案,則會嘗試至 JAR 的 /META-INF/resources 中尋找已置放的資源頁面。如果 URL 最後是以 /
結尾,但不存在該目錄,則會使用預設 Servlet(如果有定義的話,參考〈URL 模式〉中的說明)。
整個 Web 應用程式可以被封裝為一個 WAR(Web ARchive)檔案,例如 openhome.war,以便部署至 Web 容器。