デプロイ記述子: web.xml

リージョン ID

REGION_ID は、アプリの作成時に選択したリージョンに基づいて Google が割り当てる省略形のコードです。一部のリージョン ID は、一般的に使用されている国や州のコードと類似しているように見える場合がありますが、このコードは国または州に対応するものではありません。2020 年 2 月以降に作成されたアプリの場合、REGION_ID.r は App Engine の URL に含まれています。この日付より前に作成されたアプリの場合、URL のリージョン ID は省略可能です。

詳しくは、リージョン ID をご覧ください。

Java ウェブ アプリケーションでは、デプロイ記述子ファイルを使用して、URL からサーブレットへのマッピング、認証が必要な URL などの情報を決定します。このファイルの名前は web.xml で、ウェブ アプリケーションのサーブレット仕様の一部です。web.xml デプロイ記述子の詳細については、サーブレット仕様をご覧ください。

Java 8 から移行し、サポートされている最新の Java バージョンで以前のバンドル サービスを使用する必要がある場合は、web.xml ファイルに <app-engine-apis> 要素を追加して true に設定する必要があります。

<app-engine-apis>true</app-engine-apis>

デプロイ記述子

ウェブ アプリケーションのデプロイ記述子では、アプリケーションのクラス、リソース、構成のほか、ウェブサーバーがこれらを使用してウェブ リクエストを処理する方法を記述します。ウェブサーバーは、アプリケーションからのリクエストを受信すると、デプロイ記述子を使用して、リクエストを処理するコードにリクエストの URL をマッピングします。

デプロイ記述子のファイル名は web.xml です。これは、アプリの WAR の WEB-INF/ ディレクトリにあります。これはルート要素が <web-app> の XML ファイルです。

次の web.xml の例は、EE10 のバージョン 21 以降(デフォルト)、EE8 のバージョン 21、バージョン 17 以前で、すべての URL パス(/*)をサーブレット クラス mysite.server.ComingSoonServlet にマッピングする方法を示しています。サポートされている最新のバージョンをデフォルト構成で使用するには、アプリケーション サーブレットと依存関係を更新して、Jakarta 名前空間を含める必要があります。構成オプションの詳細については、既存のアプリケーションをアップグレードするをご覧ください。

v21 以降(EE10)

<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>java21</runtime> <!-- or another supported version -->
    <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>

v21(EE8)

<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> <!-- run your apps on EE8  -->
      <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>

v17 以前

  <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>
      <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>

アプリケーションをサービスに分割している場合は、各サービスに独自の構成パラメータが存在します。

サーブレットと URL パス

web.xml では、URL パスと、そのパスでリクエストを処理するサーブレットのマッピングを定義します。ウェブサーバーは、この設定を使用して、指定されたリクエストを処理するサーブレットを特定し、リクエストのメソッドに対応するクラスメソッドを呼び出します。たとえば、HTTP GET リクエストの doGet() メソッドです。

URL をサーブレットにマッピングするには、<servlet> 要素を使用してサーブレットを宣言してから、<servlet-mapping> 要素を使用して URL パスからサーブレット宣言へのマッピングを定義します。

<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> 要素では、URL パターンと、そのパターンと一致する URL のリクエストで使用する宣言済みのサーブレットの名前を指定します。URL パターンでは、パターンの先頭と末尾にアスタリスク(*)を使用できます。アスタリスクは、0 個以上の任意の文字を表します。URL パターンでは、文字列の途中でワイルドカードを使用することや、1 つのパターン内で複数のワイルドカードを使用することはできせん。パターンは URL の完全なパスと照合されるので、スラッシュ(/)で開始し、ドメイン名の後にスラッシュを含めます。URL のパスはピリオド(.)で開始できません。

    <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>

この例では、URL http://www.example.com/blue/teamProfile のリクエストは、TeamServlet クラスで処理され、teamColor パラメータは bluebgColor パラメータは #0000CC に設定しています。サーブレットは、ワイルドカードに一致した URL パスの部分を ServletRequest オブジェクトの getPathInfo() メソッドを使用して取得できます。

サーブレットが初期化パラメータにアクセスするには、サーブレット自体の getServletConfig() メソッドを使用してサーブレットの構成を取得してから、その構成オブジェクトに対して、パラメータ名を引数として、getInitParameter() メソッドを呼び出します。

String teamColor = getServletConfig().getInitParameter("teamColor");

JSP

アプリケーションは、JavaServer Pages(JSP)を使用して、ウェブページを実装できます。JSP とは、静的コンテンツ(HTML など)と Java コードを組み合わせて定義されるサーブレットです。

App Engine は、JSP の自動コンパイルと URL マッピングをサポートしています。アプリケーションの WAR 内(WEB-INF/ の外)にある JSP ファイルで、ファイル名が .jsp で終わるものは自動的にサーブレット クラスにコンパイルされ、WAR のルートから JSP ファイルへのパスと同じ URL パスにマッピングされます。たとえば、アプリの WAR の register/ というサブディレクトリに start.jsp という JSP ファイルが含まれている場合、App Engine はそのファイルをコンパイルし、URL パス /register/start.jsp にマッピングします。

JSP の URL へのマッピングを詳細に制御する必要がある場合は、デプロイ記述子で <servlet> 要素を使用して宣言することで、マッピングを明示的に指定できます。<servlet-class> 要素の代わりに、<jsp-file> 要素に、WAR ルートから JSP ファイルへのパスを指定します。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 を使用して、ユーザーがログインしているかどうかを検知し、現在ログインしているユーザーのメールアドレスを取得し、ログイン URL とログアウト URL を生成することができます。デプロイ記述子を使用し、Google アカウントに基づいて、URL パスへのアクセス制限を指定することもできます

<security-constraint> 要素では、パターンに一致する URL へのセキュリティ制限を定義します。ログインしていないユーザーがセキュリティで制限された URL にアクセスした場合、App Engine は、ユーザーを Google アカウントのログインページにリダイレクトします。ログインまたは新しいアカウントの登録が完了すると、ユーザーはアプリケーションの URL にまたリダイレクトされます。アプリケーションで何もしなくても、ログインしたユーザーだけが URL にアクセスできるように制限できます。

セキュリティ制限には、パスにアクセスできる Google アカウント ユーザーを指定する認証制限もあります。認証制限に * のユーザーロールを指定すると、Google アカウントにログインしているユーザーであれば誰でもその URL にアクセスできます。制限に admin のユーザーロールを指定すると、そのアプリケーションの登録済みのデベロッパーのみがその URL にアクセスできます。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>)はサポートされていません。

セキュリティ制限は静的ファイルとサーブレットの両方に適用されます。

保護された URL

App Engine は、REGION_ID.r.appspot.com ドメインを使用する URL に対する接続を HTTPS で保護しています。URL にアクセスするリクエストが HTTPS を使用していて、その URL が HTTPS を使用するように web.xml ファイルで構成されている場合、リクエスト データとレスポンス データの両方が送信側によって送信前に暗号化され、受信側によって受信後に復号されます。保護された接続は、連絡先情報、パスワード、プライベート メッセージなどの顧客データを保護するために役立ちます。

ある URL で 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>

転送保証が CONFIDENTIAL の URL に HTTP を使用して(保護されていない)リクエストを行うと、HTTPS を使用する同じ URL に自動的にリダイレクトされます。

JSP と静的ファイルを含むすべての URL で CONFIDENTIAL の転送保証を使用できます。

開発用ウェブサーバーでは HTTPS 接続はサポートされていません。開発用サーバーでは転送保証が無視されるので、開発用ウェブサーバーに通常の HTTP 接続を使用して、HTTPS 用のパスをテストできます。

バージョン管理された appspot.com の URL(https://1.latest.your_app_id.REGION_ID.r.appspot.com/ など)を使用してアプリの HTTPS ハンドラをテストすると、その特定のドメインパスは HTTPS 証明書で署名されていないという警告がブラウザで表示されます。そのドメインの証明書を受け入れると、ページは正常に読み込まれます。ユーザーが https://your_app_id.REGION_ID.r.appspot.com/ にアクセスするときは、証明書の警告は表示されません。

バージョン管理された appspot.com の URL に対して、この問題を回避するように設計された代替形式を使用することもできます。それには、サブドメイン コンポーネントを区切るピリオドを文字列「-dot-」に置き換えます。たとえば、上記の例で https://VERSION_ID-dot-default-dot-PROJECT_ID.REGION_ID.r.appspot.com にアクセスすると、証明書の警告は表示されません。

Google アカウントのログインとログアウトでは、常に保護された接続を使用します。アプリケーションの URL の構成方法とは関係ありません。

前述のとおり、セキュリティ制限は静的ファイルとサーブレットの両方に適用されます。これには転送保証も含まれます。

注: リクエストは HTTPS プロトコルを使用してアプリに送信することをおすすめしますappspot.com でホストされるドメインで、ワイルドカードが 2 つ以上含まれるものには SSL 証明書が発行されません。そのため、下記の例に示すように、HTTPS ではサブドメインの区切りに「.」の代わりに「-dot-」という文字列を使用する必要があります。独自のカスタム ドメインや HTTP アドレスには「.」を使用できます。

ウェルカム ファイル リスト

サイトの URL が WAR 内の静的ファイルまたは JSP へのパスを表している場合、ディレクトリへのパスにも工夫をすることをおすすめします。たとえば、ユーザーがアカウントのパスワードについての情報を取得するために URL パス /help/accounts/password.jsp にアクセスするときに、/help/accounts/ にアクセスしてアカウント システムのドキュメント紹介ページを検索する場合があります。サーブレットに明示的にマッピングされていない WAR サブディレクトリを表すパスにユーザーがアクセスしようとしたときに、サーバーがアクセスを試みるファイル名のリストを、デプロイ記述子に指定することができます。サーブレット仕様では、これを welcome file list と呼んでいます。

たとえば、ユーザーが URL パス /help/accounts/ にアクセスすると、サーバーは URL が見つからないと報告する前に、デプロイ記述子内の次の <welcome-file-list> 要素に基づき help/accounts/index.jsphelp/accounts/index.html を探します。

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

フィルタ

「フィルタ」はリクエストに対しサーブレットのように動作するクラスですが、リクエストの処理を他のフィルタやサーブレットが引き継ぐことができます。フィルタは、ロギング、特別な認証チェック、リクエスト オブジェクトやレスポンス オブジェクトのアノテーションなどの補助的なタスクを、サーブレットを呼び出す前に実行できます。フィルタを使用して、デプロイ記述子からリクエスト処理タスクを作成できます。

次のフィルタの実装例では、メッセージをログに記録してから制御を連鎖的に渡します。これには、EE10 のバージョン 21 以降(デフォルト)、EE8 のバージョン 21、バージョン 17 以前のデプロイ記述子で説明しているように、他のフィルタやサーブレットを含めることができます。サポートされている最新のバージョンをデフォルト構成で使用するには、アプリケーション サーブレットと依存関係を更新して、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() {}

}

デプロイ記述子でフィルタを構成するには、サーブレットと同様に、<filter> 要素を使用してフィルタを宣言し、<filter-mapping> 要素を使用して URL パターンにマッピングします。フィルタを他のサーブレットに直接マッピングすることもできます。

<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> 要素(URL にフィルタを適用します)または宣言したサーブレットの名前に一致する <servlet-name> 要素(サーブレットが呼び出されたときにフィルタを適用します)のいずれかを指定します。

    <!-- 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 ステータス コードを送信するときや、サーブレットが特定の Java 例外を送出するときに、サーバーで代替ページの場所を表示することができます。

<error-page> 要素には、HTTP エラーコード値(500 など)を含む <error-code> 要素を指定するか、想定される例外のクラス名(java.io.IOException など)を含む <exception-type> 要素を指定します。また、エラーが発生したときに表示するリソースの URL パスを含む <location> 要素も指定します。

    <error-page>
        <error-code>500</error-code>
        <location>/errors/servererror.jsp</location>
    </error-page>

次のエラー条件にはカスタム エラーハンドラを構成できません。

  • URL にサーブレット マッピングが定義されていない場合の 404 レスポンス ページ。
  • 403 の割り当てエラーページ
  • App Engine の内部エラーの後に表示される 500 サーバーエラー ページ。

サポートされていない web.xml 機能

次の web.xml 機能は App Engine ではサポートされていません。

  • App Engine では、サーブレットの宣言で <load-on-startup> 要素がサポートされています。しかし実際には、最初のリクエストの前ではなく、ウェブサーバー インスタンスによって最初のリクエストが処理されるときに読み込みが行われます。
  • デプロイ記述子の一部の要素では、統合開発環境(IDE)で使用するために、人間が認識可能な表示名、説明、アイコンを使用できますが、App Engine ではこれらは使用されず、無視されます。
  • App Engine では JNDI 環境変数(<env-entry>)はサポートされていません。
  • App Engine では EJB リソース(<resource-ref>)はサポートされていません。
  • サーブレットやサーブレット コンテキスト、フィルタの破棄の通知はサポートされていません。
  • <distributable> 要素は無視されます。
  • <run-at> を使用したサーブレットのスケジューリングはサポートされていません。