Deployment descriptor: web.xml

ID region

REGION_ID adalah kode singkat yang ditetapkan Google berdasarkan region yang Anda pilih saat membuat aplikasi. Kode ini tidak sesuai dengan negara atau provinsi, meskipun beberapa ID region mungkin tampak mirip dengan kode negara dan provinsi yang umum digunakan. Untuk aplikasi yang dibuat setelah Februari 2020, REGION_ID.r disertakan dalam URL App Engine. Untuk aplikasi lama yang dibuat sebelum tanggal tersebut, ID region bersifat opsional dalam URL.

Pelajari ID region lebih lanjut.

Aplikasi web Java menggunakan file deployment descriptor untuk menentukan cara URL dipetakan ke servlet, URL mana yang memerlukan autentikasi, dan informasi lainnya. File ini bernama web.xml, dan merupakan bagian dari spesifikasi servlet untuk aplikasi web. Untuk mengetahui informasi selengkapnya tentang deskripsi deployment web.xml, lihat spesifikasi servlet.

Jika bermigrasi dari Java 8 dan perlu menggunakan layanan paket lama dengan versi Java terbaru yang didukung, Anda harus menambahkan elemen <app-engine-apis> dan menetapkannya ke true di file web.xml:

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

Deployment descriptor

Deployment descriptor aplikasi web menjelaskan class, resource, dan konfigurasi aplikasi serta cara server web menggunakannya untuk melayani permintaan web. Saat menerima permintaan untuk aplikasi, server web akan menggunakan deployment descriptor untuk memetakan URL permintaan tersebut ke kode yang seharusnya menangani permintaan tersebut.

Deployment descriptor adalah file bernama web.xml. File ini berada di WAR aplikasi dalam direktori WEB-INF/. Filenya adalah file XML yang elemen root-nya adalah <web-app>.

Contoh web.xml berikut memetakan semua jalur URL (/*) ke class servlet mysite.server.ComingSoonServlet untuk versi 21 dan yang lebih baru di EE10 (default), versi 21 di EE8, dan versi 17 dan yang lebih lama. Untuk menggunakan versi terbaru yang didukung pada konfigurasi default, Anda harus mengupdate servlet dan dependensi aplikasi untuk menyertakan namespace Jakarta. Untuk mempelajari opsi konfigurasi lebih lanjut, lihat Mengupgrade aplikasi yang ada.

v21 dan yang lebih baru (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 dan yang lebih lama

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

Jika Anda mempertimbangkan aplikasi untuk layanan, setiap layanan memiliki parameter konfigurasinya sendiri.

Servlet dan jalur URL

web.xml menentukan pemetaan antara jalur URL dan servlet yang menangani permintaan dengan jalur tersebut. Server web menggunakan konfigurasi ini untuk mengidentifikasi servlet guna menangani permintaan tertentu dan memanggil metode class yang sesuai dengan metode permintaan tersebut. Misalnya: metode doGet() untuk permintaan GET HTTP.

Untuk memetakan URL ke servlet, deklarasikan servlet dengan elemen <servlet>, lalu tentukan pemetaan dari jalur URL ke deklarasi servlet dengan elemen <servlet-mapping>.

Elemen <servlet> mendeklarasikan servlet, termasuk nama yang digunakan untuk merujuk ke servlet oleh elemen lain dalam file, class yang akan digunakan untuk servlet, dan parameter inisialisasi. Anda dapat mendeklarasikan beberapa servlet menggunakan class yang sama dengan parameter inisialisasi yang berbeda. Nama untuk setiap servlet harus unik di seluruh deployment descriptor.

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

Elemen <servlet-mapping> menentukan pola URL dan nama servlet yang dideklarasikan untuk digunakan oleh permintaan yang URL-nya cocok dengan pola. Pola URL dapat menggunakan tanda bintang (*) di awal atau akhir pola untuk menunjukkan nol atau beberapa karakter apa pun. Pola URL tidak mendukung karakter pengganti di tengah string, dan tidak mengizinkan beberapa karakter pengganti dalam satu pola. Polanya cocok dengan jalur lengkap URL, dimulai dengan dan termasuk garis miring (/) setelah nama domain. Jalur URL tidak boleh diawali dengan titik (.).

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

Dengan contoh ini, permintaan untuk URL http://www.example.com/blue/teamProfile ditangani oleh class TeamServlet, dengan parameter teamColor setara dengan blue dan parameter bgColor setara dengan #0000CC. Servlet dapat memperoleh bagian jalur URL yang cocok dengan karakter pengganti menggunakan metode getPathInfo() objek ServletRequest.

Servlet dapat mengakses parameter inisialisasinya dengan mendapatkan konfigurasi servlet menggunakan metode getServletConfig()-nya sendiri, lalu memanggil metode getInitParameter() pada objek konfigurasi menggunakan nama parameter sebagai argumen.

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

JSP

Aplikasi dapat menggunakan JavaServer Pages (JSP) untuk mengimplementasikan halaman web. JSP adalah servlet yang ditentukan menggunakan konten statis, seperti HTML, yang dipadukan dengan kode Java.

App Engine mendukung kompilasi otomatis dan pemetaan URL untuk JSP. File JSP dalam WAR aplikasi (di luar WEB-INF/) yang nama filenya diakhiri dengan .jsp dikompilasi secara otomatis ke dalam class servlet, dan dipetakan ke jalur URL yang setara dengan jalur ke file JSP dari root WAR. Misalnya, jika aplikasi memiliki file JSP bernama start.jsp di subdirektori bernama register/ dalam WAR-nya, App Engine akan mengompilasinya dan memetakannya ke jalur URL /register/start.jsp.

Jika menginginkan kontrol lebih besar atas cara pemetaan JSP ke URL, Anda dapat menentukan pemetaan secara eksplisit dengan mendeklarasikannya bersama elemen <servlet> dalam deployment descriptor. Namun, tentukan elemen <jsp-file> dengan jalur ke file JSP dari root WAR, bukan elemen <servlet-class>. Elemen <servlet> untuk JSP dapat berisi parameter inisialisasi.

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

Anda dapat menginstal library tag JSP dengan elemen <taglib>. Library tag memiliki jalur ke file Deskripsi Library Tag (TLD) JSP (<taglib-location>) dan URI yang digunakan JSP untuk memilih library untuk dimuat (<taglib-uri>). Perhatikan bahwa App Engine menyediakan Library Tag Standar Halaman JavaServer (JSTL), dan Anda tidak perlu menginstalnya.

    <taglib>
        <taglib-uri>/escape</taglib-uri>
        <taglib-location>/WEB-INF/escape-tags.tld</taglib-location>
    </taglib>

Keamanan dan autentikasi

Aplikasi App Engine dapat menggunakan Akun Google untuk autentikasi pengguna. Aplikasi dapat menggunakan Google Accounts API untuk mendeteksi apakah pengguna sudah login, mendapatkan alamat email pengguna yang saat ini login, serta membuat proses login dan log out URL. Aplikasi juga dapat menentukan pembatasan akses untuk jalur URL berdasarkan Akun Google, menggunakan deployment descriptor.

Elemen <security-constraint> menentukan batasan keamanan untuk URL yang cocok dengan pola. Jika pengguna mengakses URL yang jalurnya memiliki batasan keamanan dan pengguna tidak login, App Engine akan mengalihkan pengguna ke halaman login Akun Google. Akun Google mengalihkan pengguna kembali ke URL aplikasi setelah berhasil login atau mendaftarkan akun baru. Aplikasi tidak perlu melakukan hal lain untuk memastikan bahwa hanya pengguna yang login yang dapat mengakses URL.

Batasan keamanan mencakup batasan otorisasi yang menentukan pengguna Akun Google mana yang dapat mengakses jalur tersebut. Jika batasan otorisasi menentukan peran pengguna *, semua pengguna yang login dengan Akun Google dapat mengakses URL tersebut. Jika batasan menentukan peran pengguna admin, hanya developer aplikasi terdaftar yang dapat mengakses URL. Peran admin memudahkan pembuatan bagian khusus administrator di situs Anda.

    <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 tidak mendukung peran keamanan khusus (<security-role>) atau mekanisme autentikasi alternatif (<login-config>) dalam deployment descriptor

Batasan keamanan berlaku untuk file statis serta servlet.

URL aman

App Engine mendukung koneksi aman dengan HTTPS untuk URL yang menggunakan domain REGION_ID.r.appspot.com. Saat permintaan mengakses URL menggunakan HTTPS, dan URL tersebut dikonfigurasi untuk menggunakan HTTPS di file web.xml, data permintaan dan data respons akan dienkripsi oleh pengirim sebelum dikirim, dan didekripsi oleh penerima setelah mereka diterima. Koneksi aman berguna untuk melindungi data pelanggan, seperti informasi kontak, sandi, dan pesan pribadi.

Untuk mendeklarasikan bahwa HTTPS harus digunakan untuk URL, siapkan batasan keamanan dalam deployment descriptor (seperti yang dijelaskan dalam Keamanan dan autentikasi) dengan <user-data-constraint> yang <transport-guarantee>-nya adalah CONFIDENTIAL. Contoh:

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

Permintaan yang menggunakan HTTP (tidak aman) untuk URL yang jaminan transpornya adalah CONFIDENTIAL akan otomatis dialihkan ke URL yang sama menggunakan HTTPS.

Setiap URL dapat menggunakan jaminan transpor CONFIDENTIAL, termasuk JSP dan file statis.

Server web pengembangan aplikasi tidak mendukung koneksi HTTPS. Tindakan ini mengabaikan jaminan transpor, sehingga jalur yang ditujukan untuk digunakan dengan HTTPS dapat diuji menggunakan koneksi HTTP reguler ke server web pengembangan aplikasi.

Saat Anda menguji pengendali HTTPS aplikasi menggunakan URL appspot.com berversi, seperti https://1.latest.your_app_id.REGION_ID.r.appspot.com/, browser akan memperingatkan Anda bahwa sertifikat HTTPS tidak ditandai untuk jalur domain spesifik tersebut. Jika Anda menyetujui sertifikat untuk domain tersebut, halaman akan berhasil dimuat. Pengguna tidak akan melihat peringatan sertifikat saat mengakses https://your_app_id.REGION_ID.r.appspot.com/.

Anda juga dapat menggunakan bentuk alternatif dari URL appspot.com berversi yang dirancang untuk menghindari masalah ini dengan mengganti titik yang memisahkan komponen subdomain dengan string "-dot-". Misalnya, contoh sebelumnya dapat diakses tanpa peringatan sertifikat di https://VERSION_ID-dot-default-dot-PROJECT_ID.REGION_ID.r.appspot.com.

Login dan logout Akun Google selalu dilakukan menggunakan koneksi yang aman dan tidak terkait dengan cara URL aplikasi dikonfigurasi.

Seperti yang disebutkan di atas, batasan keamanan berlaku untuk file statis serta servlet. Ini termasuk jaminan transpor.

Catatan: Google menyarankan penggunaan protokol HTTPS untuk mengirim permintaan ke aplikasi Anda. Google tidak menerbitkan sertifikat SSL untuk domain dengan karakter pengganti ganda yang dihosting di appspot.com. Oleh karena itu, dengan HTTPS, Anda harus menggunakan string "-dot-", bukan "." ke subdomain terpisah, seperti yang ditunjukkan dalam contoh di bawah ini. Anda dapat menggunakan "." sederhana dengan domain kustom Anda sendiri atau dengan alamat HTTP.

Daftar file sambutan

Jika URL untuk situs Anda mewakili jalur ke file statis atau JSP di WAR, sebaiknya jalur ke direktori juga melakukan hal yang berguna. Pengguna yang mengunjungi jalur URL /help/accounts/password.jsp untuk mengetahui informasi tentang sandi akun mungkin mencoba membuka /help/accounts/ untuk menemukan halaman yang memperkenalkan dokumentasi sistem akun. Deployment descriptor dapat menentukan daftar nama file yang harus dicoba server saat pengguna mengakses jalur yang mewakili subdirektori WAR yang belum dipetakan secara eksplisit ke servlet. Spesifikasi servlet menyebutnya welcome file list.

Misalnya, jika pengguna mengakses jalur URL /help/accounts/, elemen <welcome-file-list> berikut dalam deployment descriptor memberi tahu server untuk memeriksa help/accounts/index.jsp dan help/accounts/index.html sebelum melaporkan bahwa URL tidak ada:

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

Filter

Filter adalah class yang bertindak berdasarkan permintaan seperti servlet, tetapi dapat memungkinkan penanganan permintaan untuk dilanjutkan dengan filter atau servlet lainnya. Filter dapat melakukan tugas tambahan, seperti logging, melakukan pemeriksaan autentikasi khusus, atau menganotasi objek permintaan atau respons sebelum memanggil servlet. Filter memungkinkan Anda membuat tugas pemrosesan permintaan dari deployment descriptor.

Contoh implementasi filter berikut mencatat pesan, dan meneruskan kontrol secara berkesinambungan, yang dapat mencakup filter lain atau servlet, seperti yang dijelaskan oleh deployment descriptor untuk versi 21 dan yang lebih baru di EE10 (default), versi 21 di EE8, dan versi 17 dan yang lebih lama. Untuk menggunakan versi terbaru yang didukung pada konfigurasi default, Anda harus mengupdate servlet dan dependensi aplikasi untuk menyertakan namespace Jakarta. Untuk mempelajari opsi konfigurasi lebih lanjut, lihat Mengupgrade aplikasi yang ada.

v21 dan yang lebih baru (EE10)

Class filter ini mengimplementasikan antarmuka jakarta.servlet.Filter dengan metode doFilter().

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)

Class filter ini mengimplementasikan antarmuka javax.servlet.Filter dengan metode doFilter().

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 dan yang lebih lama

Class filter ini mengimplementasikan antarmuka javax.servlet.Filter dengan metode doFilter().

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() {}

}

Serupa dengan servlet, Anda mengonfigurasi filter dalam deployment descriptor dengan mendeklarasikan filter menggunakan elemen <filter>, lalu memetakannya ke pola URL dengan elemen <filter-mapping>. Anda juga dapat memetakan filter secara langsung ke servlet lainnya.

Elemen <filter> berisi elemen <filter-name>, <filter-class>, dan <init-param> opsional.

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

Elemen <filter-mapping> berisi <filter-name> yang cocok dengan nama filter yang dideklarasikan, dan elemen <url-pattern> untuk menerapkan filter ke URL, atau elemen <servlet-name> yang sesuai dengan nama servlet yang dideklarasikan untuk menerapkan filter setiap kali servlet dipanggil.

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

Pengendali error

Anda dapat menyesuaikan apa yang dikirim server kepada pengguna saat terjadi error, menggunakan deployment descriptor. Server dapat menampilkan lokasi halaman alternatif saat akan mengirimkan kode status HTTP tertentu, atau saat servlet memunculkan pengecualian Java tertentu.

Elemen <error-page> berisi elemen <error-code> dengan nilai kode error HTTP (seperti 500), atau elemen <exception-type> dengan nama class pengecualian yang diharapkan (seperti java.io.IOException). Objek ini juga berisi elemen <location> yang berisi jalur URL resource yang akan ditampilkan saat terjadi error.

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

Anda tidak dapat mengonfigurasi pengendali error kustom untuk kondisi error berikut:

  • Halaman respons 404 jika tidak ada pemetaan servlet yang ditentukan untuk URL.
  • Halaman error kuota 403
  • Halaman error server 500 yang muncul setelah error internal App Engine.

Fitur web.xml yang tidak didukung

Fitur web.xml berikut tidak didukung oleh App Engine:

  • App Engine mendukung elemen <load-on-startup> untuk deklarasi servlet. Namun, pemuatan sebenarnya terjadi selama permintaan pertama yang ditangani oleh instance server web, bukan sebelum permintaan tersebut.
  • Beberapa elemen deployment descriptor dapat mengambil nama tampilan, deskripsi, dan ikon yang dapat dibaca manusia untuk digunakan dalam IDE. App Engine tidak menggunakannya, dan mengabaikannya.
  • App Engine tidak mendukung variabel lingkungan JNDI (<env-entry>).
  • App Engine tidak mendukung resource EJB (<resource-ref>).
  • Notifikasi tentang penghancuran servlet, konteks servlet, atau filter tidak didukung.
  • Elemen <distributable> diabaikan.
  • Penjadwalan servlet dengan <run-at> tidak didukung.