區域 ID
REGION_ID 是 Google 根據您在建立應用程式時選取的地區所指派的縮寫代碼。此代碼不對應至國家/地區或省份,即使部分區域 ID 可能與常用的國家/地區和省份代碼相似。如果是 2020 年 2 月後建立的應用程式,App Engine 網址會包含 REGION_ID.r。如果是這段時間前建立的現有應用程式,網址可選擇是否包含地區 ID。
進一步瞭解區域 ID。
Java 網路應用程式使用部署作業描述元檔案,就能判斷網址對應 Servlet 的方式、需要驗證的網址,以及其他資訊。此檔案的名稱為 web.xml,屬於網路應用程式的 Servlet 規格。如要進一步瞭解 web.xml 部署描述元,請參閱Servlet 規格。
如果您要從 Java 8 遷移,並使用最新支援的 Java 版本搭配舊版套裝服務,請務必在 web.xml 檔案中新增 <app-engine-apis> 元素,並將其設為 true:
<app-engine-apis>true</app-engine-apis>
部署作業描述元
網路應用程式的部署作業描述元將描述應用程式的類別、資源和設定,以及網頁伺服器如何使用它們提供網路要求。當網頁伺服器收到對應用程式的要求時,伺服器將使用部署作業描述元,將要求的網址對應至負責處理該要求的程式碼。
部署作業描述元是名為 web.xml 的檔案,存放在 WEB-INF/ 目錄下應用程式的 WAR 中。該檔案是 XML 檔案,其根元素為 <web-app>。
以下 web.xml 範例會將所有網址路徑 (/*) 對應至 Servlet 類別 mysite.server.ComingSoonServlet,適用於 EE10 (預設) 的 21 以上版本、EE8 的 21 以上版本,以及 17 以下版本。如要在預設設定中使用最新支援版本,您必須更新應用程式 Servlet 和依附元件,加入 Jakarta 命名空間。如要進一步瞭解設定選項,請參閱「升級現有應用程式」。
Java 25 (EE 11)
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0">
<runtime>java25</runtime>
<system-properties>
<property name="appengine.use.EE11" value="true"/>
</system-properties>
<servlet>
<servlet-name>comingsoon</servlet-name>
<servlet-class>mysite.server.ComingSoonServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>comingsoon</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Java 21 (EE 10)
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<runtime>java21</runtime>
<system-properties>
<property name="appengine.use.EE10" value="true"/>
</system-properties>
<servlet>
<servlet-name>comingsoon</servlet-name>
<servlet-class>mysite.server.ComingSoonServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>comingsoon</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Java 17 (EE 8)
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<runtime>java17</runtime>
<system-properties>
<property name="appengine.use.EE8" value="true"/>
</system-properties>
<servlet>
<servlet-name>comingsoon</servlet-name>
<servlet-class>mysite.server.ComingSoonServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>comingsoon</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
如將您的應用程式分解成服務,每項服務都會有各自的設定參數。
Servlet 和網址路徑
web.xml 定義網址路徑與 Servlet 之間的對應,其中 Servlet 可處理具有這些路徑的要求。網路伺服器會利用這項設定,指定什麼樣的要求應交給哪一個 Servlet 處理,並呼叫與要求方法對應的類別方法。例如:HTTP GET 要求的 doGet() 方法。
如要將網址對應至 Servlet,您要使用 <servlet> 元素宣告 Servlet,然後使用 <servlet-mapping> 元素定義從網址路徑到 Servlet 宣告的對應。
<servlet> 元素可宣告 Servlet,包括檔案中的其他元素用來參照 Servlet 的名稱、用於 Servlet 的類別,以及初始化參數。您可以使用擁有不同初始化參數 (Initialization Parameter) 的相同類別,宣告多個 Servlet。在所有部署作業描述元中,每個 Servlet 的名稱不得重複。
<servlet> <servlet-name>redteam</servlet-name> <servlet-class>mysite.server.TeamServlet</servlet-class> <init-param> <param-name>teamColor</param-name> <param-value>red</param-value> </init-param> <init-param> <param-name>bgColor</param-name> <param-value>#CC0000</param-value> </init-param> </servlet> <servlet> <servlet-name>blueteam</servlet-name> <servlet-class>mysite.server.TeamServlet</servlet-class> <init-param> <param-name>teamColor</param-name> <param-value>blue</param-value> </init-param> <init-param> <param-name>bgColor</param-name> <param-value>#0000CC</param-value> </init-param> </servlet>
<servlet-mapping> 元素可指定網址模式與所宣告 Servlet 的名稱,且該名稱將用於網址符合模式的要求。網址格式可以在格式的開頭或結尾處使用星號 (*),藉此表示零個或多個任何字元。網址模式不支援在字串中間使用萬用字元,也不允許在單一模式中使用多個萬用字元。這個格式符合完整的網址路徑,而且此網址路徑在網域名稱的開頭和結尾均使用斜線 (/)。網址路徑的開頭不能為句點 (.)。
<servlet-mapping> <servlet-name>redteam</servlet-name> <url-pattern>/red/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>blueteam</servlet-name> <url-pattern>/blue/*</url-pattern> </servlet-mapping>
在這個範例中,網址 http://www.example.com/blue/teamProfile 的要求是由 TeamServlet 類別處理,其中 teamColor 參數等於 blue,而 bgColor 參數等於 #0000CC。Servlet 可以使用 ServletRequest 物件的 getPathInfo() 方法,取得與萬用字元相符的網址路徑部分。
Servlet 可以存取其初始化參數,方法是使用自己的 getServletConfig() 方法取得 Servlet 設定,然後使用參數名稱做為引數,針對設定物件呼叫 getInitParameter() 方法。
String teamColor = getServletConfig().getInitParameter("teamColor");
JSP
應用程式可以使用 JavaServer Page (JSP) 實作網頁。JSP 是透過靜態內容 (例如 HTML),搭配 Java 程式碼所定義的 Servlet。
App Engine 支援 JSP 的自動編譯與網址對應。在應用程式的 WAR 中 (在 WEB-INF/ 之外),檔名結尾是 .jsp 的 JSP 檔案將自動編譯為 Servlet 類別,並對應至網址路徑,此路徑相當於 JSP 檔案至 WAR 根目錄的路徑。舉例來說,假設應用程式在 WAR 的 register/ 子目錄中,有一個名稱是 start.jsp 的 JSP 檔案,App Engine 將編譯該檔案並將其對應至網址路徑 /register/start.jsp。
如要進一步控管將 JSP 對應至網址的方式,可以透過在部署作業描述元中使用 <servlet> 元素宣告的方式明確指定對應。您可以使用 JSP 檔案至 WAR 根目錄的路徑指定 <jsp-file> 元素,而不是 <servlet-class> 元素。JSP 的 <servlet> 元素可以包含初始化參數。
<servlet> <servlet-name>register</servlet-name> <jsp-file>/register/start.jsp</jsp-file> </servlet> <servlet-mapping> <servlet-name>register</servlet-name> <url-pattern>/register/*</url-pattern> </servlet-mapping>
您可以使用 <taglib> 元素安裝 JSP 標記程式庫。標記程式庫中包含 JSP 標記程式庫描述元 (TLD) 檔案的路徑 (<taglib-location>),以及 JSP 用來選取要載入程式庫的 URI (<taglib-uri>)。請注意,App Engine 會提供 JavaServer Pages 標準標記程式庫 (JSTL),您不需要再安裝。
<taglib> <taglib-uri>/escape</taglib-uri> <taglib-location>/WEB-INF/escape-tags.tld</taglib-location> </taglib>
安全性和驗證
App Engine 可以使用「Google 帳戶」驗證使用者。應用程式可以透過 Google Accounts API 偵測使用者是否已登入、取得目前登入使用者電子郵件地址,並產生登入和登出網址。應用程式也可以透過部署作業描述元,指定以 Google 帳戶為主網址路徑的存取限制。
<security-constraint> 元素定義與模式相符網址的安全限制。如果使用者存取設有安全限制的網址路徑,卻尚未登入,App Engine 將使用者重新導向至 Google 帳戶登入頁面。Google 帳戶將在使用者成功登入或註冊新帳戶之後,將使用者重新導向至應用程式網址。應用程式不需要執行任何其他步驟,即可確保只有登入使用者才能存取網址。
安全限制包括一項驗證限制,當中將指定可以存取路徑的 Google 帳戶使用者。如果授權限制指定的使用者角色為 *,則任何透過 Google 帳戶登入的使用者都可以存取該網址。如果限制指定的使用者角色為 admin,則只有應用程式的註冊開發人員可以存取該網址。您可以使用 admin 角色,輕鬆建構網站的管理員專屬區域。
<security-constraint> <web-resource-collection> <web-resource-name>profile</web-resource-name> <url-pattern>/profile/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>*</role-name> </auth-constraint> </security-constraint> <security-constraint> <web-resource-collection> <web-resource-name>admin</web-resource-name> <url-pattern>/admin/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>admin</role-name> </auth-constraint> </security-constraint>
App Engine 在部署作業描述元中不支援自訂安全性角色 (<security-role>) 或替代驗證機制 (<login-config>)。
安全限制將套用至靜態檔案和 Servlet。
安全網址
App Engine 針對使用 REGION_ID.r.appspot.com 網域的網址,支援透過 HTTPS 的安全連線。透過 HTTPS 要求存取網址,且該網址設定為在 web.xml 檔案中使用 HTTPS,要求資料和回應資料都會在傳輸之前經過寄件人加密,並且在收件人收到資料後解密。安全連線對於保護顧客資料 (例如聯絡資訊、密碼以及私人訊息) 十分有用。
如要宣告必須在某網址使用 HTTPS,請在部署作業描述元中 (如安全與驗證一節所述) 設定安全限制,將 <user-data-constraint> 下的 <transport-guarantee> 設為 CONFIDENTIAL。例如:
<security-constraint> <web-resource-collection> <web-resource-name>profile</web-resource-name> <url-pattern>/profile/*</url-pattern> </web-resource-collection> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint>
使用 HTTP (不安全) 要求傳輸保證為 CONFIDENTIAL 的網址時,要求會自動重新導向使用 HTTPS 的相同網址。
任何網址都能使用 CONFIDENTIAL 傳輸保證,包括 JSP 和靜態檔案。
開發網路伺服器不支援 HTTPS 連線。這類伺服器會忽略傳輸保證,因此可使用開發網路伺服器的一般 HTTP 連線來測試要搭配 HTTPS 使用的路徑。
使用版本化 appspot.com 網址測試應用程式的 HTTPS 處理常式時,例如 https://1.latest.your_app_id.REGION_ID.r.appspot.com/,瀏覽器會警告您,HTTPS 憑證並不是針對該指定網域路徑所簽署。如果您接受該網域的憑證,將成功載入網頁。使用者存取 https://your_app_id.REGION_ID.r.appspot.com/ 時將不會看到憑證警告。
您也可以使用已編列版本的 appspot.com 網址替代形式,這網址專為避免上述問題所設計,只要將分隔網址子網域部分的點改成「-dot-」字串即可。例如,先前的範例可以用 https://VERSION_ID-dot-default-dot-PROJECT_ID.REGION_ID.r.appspot.com 存取,不會出現憑證警告。
Google 帳戶的登入和登出作業一律使用安全連線執行,與應用程式的網址設定方式並無關聯。
如上所述,安全限制將套用至靜態檔案和 Servlet。這包括傳輸保證。
附註:Google 建議
使用 HTTPS 通訊協定將要求傳送至應用程式。Google 不會核發安全資料傳輸層 (SSL) 憑證給託管在 appspot.com 的雙萬用字元網域。因此,HTTPS 分隔子網域時必須使用「-dot-」字串而非「.」,如下方範例所示。您可以使用簡單的「.」搭配自訂網域或 HTTP 位址。
歡迎檔案清單
當您網站的網址代表 WAR 的靜態檔案路徑或 JSP 路徑時,建議您讓目錄的路徑發揮一些作用。為取得帳戶密碼相關資訊而造訪網址路徑 /help/accounts/password.jsp 的使用者,可能會嘗試造訪 /help/accounts/,尋找介紹帳戶系統說明文件的頁面。使用者存取代表 WAR 子目錄的路徑 (尚未明確對應至 Servlet) 時,部署作業描述元可以指定伺服器應該嘗試的檔案名稱清單。Servlet 規格將此稱為 welcome file list。
舉例來說,如果使用者存取網址路徑 /help/accounts/,部署作業描述元中的下列 <welcome-file-list> 元素會讓伺服器檢查 help/accounts/index.jsp 和 help/accounts/index.html,然後報告網址不存在:
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
</welcome-file-list>篩選器
「篩選器」是一種類別,它跟 Servlet 一樣會根據要求來採取行動,但能允許其他篩選器或 Servlet 繼續處理同一個要求。篩選條件可以執行輔助作業,例如記錄、執行特殊驗證檢查,或在呼叫 Servlet 之前註解要求或回應物件。篩選條件可讓您從部署作業描述元,編寫要求處理工作。
下列篩選器實作範例會記錄訊息,並沿著鏈結往下傳送控制項,其中可能包括其他篩選器或 Servlet,如 EE10 (預設) 21 以上版本、EE8 21 版本,以及 17 以下版本的部署作業描述元所述。如要在預設設定中使用最新支援版本,您必須更新應用程式 Servlet 和依附元件,加入 Jakarta 命名空間。如要進一步瞭解設定選項,請參閱「升級現有應用程式」。
v21 以上版本 (EE10)
這個篩選器類別會透過 doFilter() 方法實作 jakarta.servlet.Filter 介面。
package mysite.server;
import java.io.IOException;
import java.util.logging.Logger;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
public class LogFilterImpl implements Filter {
private FilterConfig filterConfig;
private static final Logger log = Logger.getLogger(LogFilterImpl.class.getName());
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
log.warning("Log filter processed a " + getFilterConfig().getInitParameter("logType")
+ " request");
filterChain.doFilter(request, response);
}
public FilterConfig getFilterConfig() {
return filterConfig;
}
public void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
public void destroy() {}
}
v21 (EE8)
這個篩選器類別會透過 doFilter() 方法實作 javax.servlet.Filter 介面。
package mysite.server;
import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class LogFilterImpl implements Filter {
private FilterConfig filterConfig;
private static final Logger log = Logger.getLogger(LogFilterImpl.class.getName());
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
log.warning("Log filter processed a " + getFilterConfig().getInitParameter("logType")
+ " request");
filterChain.doFilter(request, response);
}
public FilterConfig getFilterConfig() {
return filterConfig;
}
public void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
public void destroy() {}
}
v17 以下版本
這個篩選器類別會透過 doFilter() 方法實作 javax.servlet.Filter 介面。
package mysite.server;
import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class LogFilterImpl implements Filter {
private FilterConfig filterConfig;
private static final Logger log = Logger.getLogger(LogFilterImpl.class.getName());
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
log.warning("Log filter processed a " + getFilterConfig().getInitParameter("logType")
+ " request");
filterChain.doFilter(request, response);
}
public FilterConfig getFilterConfig() {
return filterConfig;
}
public void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
public void destroy() {}
}
與 Servlet 類似,您可以使用 <filter> 元素宣告篩選條件,然後使用 <filter-mapping> 元素將其對應至網址模式,藉此在部署作業描述元中設定篩選條件。您也可以將篩選條件直接對應至其他的 Servlet。
<filter> 元素包含 <filter-name>、<filter-class> 和選用的 <init-param> 元素。
<filter> <filter-name>logSpecial</filter-name> <filter-class>mysite.server.LogFilterImpl</filter-class> <init-param> <param-name>logType</param-name> <param-value>special</param-value> </init-param> </filter>
<filter-mapping> 元素包含與所宣告篩選器名稱相符的 <filter-name>,以及用於將篩選器套用至網址的 <url-pattern> 元素,或與所宣告 Servlet 名稱相符的 <servlet-name> 元素,以便在呼叫 Servlet 時套用篩選器。
<!-- Log for all URLs ending in ".special" --> <filter-mapping> <filter-name>logSpecial</filter-name> <url-pattern>*.special</url-pattern> </filter-mapping> <!-- Log for all URLs that use the "comingsoon" servlet --> <filter-mapping> <filter-name>logSpecial</filter-name> <servlet-name>comingsoon</servlet-name> </filter-mapping>
錯誤處理常式
您可以使用部署作業描述元,自訂伺服器在發生錯誤時要傳送給使用者的訊息。伺服器在即將傳送特定的 HTTP 狀態碼時,或在 Servlet 引發特定的 Java 例外狀況時,可以顯示替代頁面位置。
<error-page> 元素包含 <error-code> 元素,其擁有 HTTP 錯誤代碼值 (例如 500);或包含 <exception-type> 元素,其擁有預期例外狀況的類別名稱 (例如 java.io.IOException)。亦包含 <location> 元素,在發生錯誤時顯示其擁有的資源網址路徑。
<error-page> <error-code>500</error-code> <location>/errors/servererror.jsp</location> </error-page>
您無法針對下列錯誤狀況設定自訂錯誤處理常式:
- 網址沒有定義的 Servlet 對應時,您無法自訂 HTTP
404回應頁面。 403配額錯誤頁面- App Engine 內部錯誤而導致的
500伺服器錯誤頁面。
不支援的 web.xml 功能
App Engine 並未支援下列 web.xml 功能:
- App Engine 支援用於 Servlet 宣告的
<load-on-startup>元素。不過,必須等到網路伺服器執行個體處理第一個要求期間 (而非之前),才會實際發生載入。 - 某些部署作業描述元的元素可以接受使用者可理解的顯示名稱、說明和圖示,以在 IDE 中使用。App Engine 不使用這些元素,且會予以忽略。
- App Engine 不支援 JNDI 環境變數 (
<env-entry>)。 - App Engine 不支援 EJB 資源 (
<resource-ref>)。 - 系統無法在刪除 Servlet、Servlet 結構定義或篩選器時發出通知。
- 系統會忽略
<distributable>元素。 - 系統不支援使用
<run-at>的 Servlet 排程。