Il descrittore del deployment: web.xml

ID regione

REGION_ID è un codice abbreviato assegnato da Google in base alla regione selezionata al momento della creazione dell'app. Non corrisponde a un paese o a una provincia, anche se alcuni ID regione possono apparire simili ai codici di paese e provincia di uso comune. Per le app create dopo febbraio 2020, REGION_ID.r è incluso negli URL di App Engine. Per le app esistenti create prima di questa data, l'ID regione è facoltativo nell'URL.

Scopri di più sugli ID regione.

Le applicazioni web Java utilizzano un file descrittore di deployment per determinare in che modo gli URL vengono mappati ai servlet, quali URL richiedono l'autenticazione e altre informazioni. Questo file è denominato web.xml e si trova nel WAR dell'app nella directory WEB-INF/. web.xml fa parte dello standard servlet per le applicazioni web.

Per ulteriori informazioni sullo standard web.xml, consulta la specifica Servlet.

descrittore di deployment web.xml

Il descrittore di deployment di un'applicazione web descrive le classi, le risorse e la configurazione dell'applicazione e il modo in cui il server web le utilizza per gestire le richieste web. Quando il server web riceve una richiesta per l'applicazione, utilizza il descrittore di deployment per mappare l'URL della richiesta al codice che deve gestire la richiesta.

Il descrittore di deployment è un file denominato web.xml. Si trova nella sezione WAR dell'app nella directory WEB-INF/. Il file è un file XML il cui elemento principale è <web-app>.

Ecco un semplice esempio di web.xml che mappa tutti i percorsi URL (/*) alla classe di servlet mysite.server.ComingSoonServlet:

<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">
    <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 e percorsi degli URL

web.xml definisce le mappature tra i percorsi dell'URL e i servlet che gestiscono le richieste con questi percorsi. Il server web utilizza questa configurazione per identificare il servlet in grado di gestire una determinata richiesta e di chiamare il metodo della classe che corrisponde al metodo della richiesta. Ad esempio, il metodo doGet() per le richieste HTTP GET.

Per mappare un URL a un servlet, devi dichiarare il servlet con l'elemento <servlet>, quindi definire una mappatura da un percorso dell'URL a una dichiarazione servlet con l'elemento <servlet-mapping>.

L'elemento <servlet> dichiara la servlet, inclusi un nome utilizzato per fare riferimento al servlet da altri elementi nel file, la classe da utilizzare per il servlet e i parametri di inizializzazione. Puoi dichiarare più servlet utilizzando la stessa classe con parametri di inizializzazione diversi. Il nome di ogni servlet deve essere univoco nel descrittore di deployment.

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

L'elemento <servlet-mapping> specifica un pattern URL e il nome di un servlet dichiarato da utilizzare per le richieste il cui URL corrisponde al pattern. Il pattern URL può utilizzare un asterisco (*) all'inizio o alla fine del pattern per indicare zero o più caratteri. Lo standard non supporta i caratteri jolly nel mezzo di una stringa e non consente più caratteri jolly in un pattern. Il pattern corrisponde al percorso completo dell'URL, a partire dalla barra (/) che segue il nome di dominio, inclusa. Il percorso dell'URL non può iniziare con un punto (.).

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

Con questo esempio, una richiesta per l'URL http://www.example.com/blue/teamProfile viene gestita dalla classe TeamServlet, con il parametro teamColor uguale a blue e il parametro bgColor uguale a #0000CC. Il servlet può recuperare la parte del percorso dell'URL che corrisponde al carattere jolly utilizzando il metodo getPathInfo() dell'oggetto ServletRequest.

Il servlet può accedere ai suoi parametri di inizializzazione ottenendo la sua configurazione tramite il proprio metodo getServletConfig(), quindi chiamando il metodo getInitParameter() sull'oggetto di configurazione utilizzando il nome del parametro come argomento.

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

JSP

Un'app può utilizzare JavaServer Pages (JSP) per implementare le pagine web. I JSP sono servlet definiti utilizzando contenuti statici, come HTML, mixati con codice Java.

App Engine supporta la compilazione automatica e il mapping degli URL per JSP. Un file JSP nel file WAR dell'applicazione (esterno a WEB-INF/) il cui nome termina con .jsp viene compilato automaticamente in una classe servlet e mappato al percorso dell'URL equivalente al percorso del file JSP dalla radice WAR. Ad esempio, se un'app ha un file JSP denominato start.jsp in una sottodirectory denominata register/ nella sua libreria WAR, App Engine lo compila e la mappa al percorso dell'URL /register/start.jsp.

Se vuoi avere un maggiore controllo sul modo in cui JSP viene mappato a un URL, puoi specificare il mapping in modo esplicito dichiarandolo con un elemento <servlet> nel descrittore di deployment. Anziché un elemento <servlet-class>, devi specificare un elemento <jsp-file> con il percorso al file JSP dalla radice WAR. L'elemento <servlet> per JSP può contenere parametri di inizializzazione.

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

Puoi installare le librerie di tag JSP con l'elemento <taglib>. Una libreria di tag include un percorso al file JSP Tag Library Descriptor (TLD) (<taglib-location>) e un URI utilizzato dai JSP per selezionare la libreria per il caricamento (<taglib-uri>). Tieni presente che App Engine fornisce la libreria tag standard di JavaServer (JSTL) e che non è necessario installarla.

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

Sicurezza e autenticazione

Un'applicazione App Engine può utilizzare gli Account Google per l'autenticazione degli utenti. L'app può utilizzare l'API Google Account per rilevare se l'utente ha eseguito l'accesso, recuperare l'indirizzo email dell'utente che ha effettuato l'accesso e generare URL di accesso e di uscita. Un'app può anche specificare limitazioni di accesso per i percorsi degli URL basati sugli Account Google utilizzando il descrittore di deployment.

L'elemento <security-constraint> definisce un vincolo di sicurezza per gli URL che corrispondono a un pattern. Se un utente accede a un URL il cui percorso prevede un vincolo di sicurezza e l'utente non ha eseguito l'accesso, App Engine reindirizza l'utente alla pagina di accesso degli Account Google. Gli Account Google reindirizzano l'utente all'URL dell'applicazione dopo aver eseguito l'accesso o aver registrato un nuovo account. L'app non deve fare altro per garantire che soltanto gli utenti che hanno effettuato l'accesso possano accedere all'URL.

Un vincolo di sicurezza include un vincolo di autorizzazione che specifica gli utenti degli Account Google che possono accedere al percorso. Se il vincolo di autorizzazione specifica un ruolo utente di *, tutti gli utenti che hanno eseguito l'accesso con un Account Google potranno accedere all'URL. Se il vincolo specifica un ruolo utente pari a admin, solo gli sviluppatori registrati dell'applicazione possono accedere all'URL. Il ruolo admin semplifica la creazione di sezioni del tuo sito riservate agli amministratori.

    <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 non supporta ruoli di sicurezza personalizzati (<security-role>) o meccanismi di autenticazione alternativi (<login-config>) nel descrittore di deployment.

I vincoli di sicurezza si applicano ai file statici e ai servlet.

URL protetti

Google App Engine supporta connessioni sicure tramite HTTPS per gli URL che utilizzano il dominio REGION_ID.r.appspot.com. Quando una richiesta accede a un URL tramite HTTPS e questo URL è configurato in modo da utilizzare HTTPS nel file web.xml, sia i dati della richiesta sia quelli della risposta vengono criptati dal mittente prima di essere trasmessi e decriptati dal destinatario dopo la ricezione. Le connessioni sicure sono utili per proteggere i dati dei clienti, ad esempio le informazioni di contatto, le password e i messaggi privati.

Per dichiarare che HTTPS deve essere utilizzato per un URL, devi configurare un vincolo di sicurezza nel descrittore di deployment (come descritto in Sicurezza e autenticazione) con <user-data-constraint> il cui <transport-guarantee> è CONFIDENTIAL. Ad esempio:

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

Le richieste che utilizzano HTTP (non sicuro) per gli URL la cui garanzia di trasporto è CONFIDENTIAL vengono reindirizzate automaticamente allo stesso URL utilizzando HTTPS.

Qualsiasi URL può utilizzare la garanzia di trasporto CONFIDENTIAL, inclusi JSP e file statici.

Il server web di sviluppo non supporta connessioni HTTPS. Ignora la garanzia di trasporto, pertanto i percorsi destinati a essere utilizzati con HTTPS possono essere testati utilizzando le normali connessioni HTTP al server web di sviluppo.

Quando testi i gestori HTTPS della tua app utilizzando l'URL appspot.com con il controllo delle versioni, ad esempio https://1.latest.your_app_id.REGION_ID.r.appspot.com/, il tuo browser ti avvisa che il certificato HTTPS non è stato firmato per quel percorso di dominio specifico. Se accetti il certificato per quel dominio, le pagine verranno caricate correttamente. Gli utenti non vedranno l'avviso relativo al certificato quando accedono a https://your_app_id.REGION_ID.r.appspot.com/.

Puoi anche utilizzare una forma alternativa dell'URL di appspot.com con il controllo delle versioni, progettato per evitare questo problema sostituendo i punti che separano i componenti del sottodominio con la stringa "-dot-". Ad esempio, è possibile accedere all'esempio precedente senza un avviso di certificato all'indirizzo https://VERSION_ID-dot-default-dot-PROJECT_ID.REGION_ID.r.appspot.com.

L'accesso e la disconnessione degli Account Google vengono sempre eseguiti utilizzando una connessione sicura e non sono correlati al modo in cui sono configurati gli URL dell'applicazione.

Come già detto, i vincoli di sicurezza si applicano ai file statici e ai servlet. È inclusa la garanzia di trasporto.

Nota: Google consiglia di utilizzare il protocollo HTTPS per inviare richieste alla tua app. Google non rilascia certificati SSL per i domini con caratteri jolly ospitati in appspot.com. Di conseguenza, con HTTPS devi utilizzare la stringa "-dot-" anziché "." per separare i sottodomini, come mostrato negli esempi riportati di seguito. Puoi utilizzare un semplice "." con il tuo dominio personalizzato o con indirizzi HTTP. Per maggiori informazioni, consulta HTTPS come indicatore di ranking.

L'elenco dei file di benvenuto

Quando gli URL del tuo sito rappresentano percorsi a file statici o JSP nella WAR, è spesso una buona idea che anche i percorsi delle directory svolgano qualcosa di utile. Un utente che visita il percorso dell'URL /help/accounts/password.jsp per informazioni sulle password degli account potrebbe provare a visitare /help/accounts/ per trovare una pagina che presenta la documentazione del sistema degli account. Il descrittore di deployment può specificare un elenco di nomi file che il server deve provare quando l'utente accede a un percorso che rappresenta una sottodirectory WAR che non è già mappata esplicitamente a un servlet. Lo standard servlet lo chiama "elenco dei file di benvenuto".

Ad esempio, se l'utente accede al percorso dell'URL /help/accounts/, il seguente elemento <welcome-file-list> nel descrittore di deployment indica al server di verificare la presenza di help/accounts/index.jsp e help/accounts/index.html prima di segnalare che l'URL non esiste:

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

Filtri

Un filtro è una classe che agisce su una richiesta come un servlet, ma può consentire la gestione della richiesta per continuare con altri filtri o servlet. Un filtro può eseguire un'attività ausiliaria, ad esempio il logging, l'esecuzione di controlli di autenticazione specializzati o l'annotazione degli oggetti di richiesta o risposta prima di chiamare il servlet. I filtri consentono di comporre attività di elaborazione delle richieste dal descrittore di deployment.

Una classe di filtro implementa l'interfaccia javax.servlet.Filter, incluso il metodo doFilter(). Di seguito è riportata una semplice implementazione di filtro che registra un messaggio e trasmette il controllo lungo la catena, che può includere altri filtri o un servlet, come descritto dal descrittore di deployment:

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

}

Come per i servlet, devi configurare un filtro nel descrittore di deployment dichiarando il filtro con l'elemento <filter> e poi mappandolo a un pattern URL con l'elemento <filter-mapping>. Puoi anche mappare i filtri direttamente ad altri servlet.

L'elemento <filter> contiene un elemento <filter-name>, <filter-class> e gli elementi <init-param> facoltativi.

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

L'elemento <filter-mapping> contiene un elemento <filter-name> che corrisponde al nome di un filtro dichiarato e un elemento <url-pattern> per applicare il filtro agli URL oppure un elemento <servlet-name> che corrisponde al nome di una servlet dichiarata per l'applicazione del filtro ogni volta che viene richiamata la 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>

Gestori degli errori

Puoi personalizzare ciò che il server invia all'utente quando si verifica un errore utilizzando il descrittore di deployment. Il server può visualizzare un percorso di pagina alternativo quando sta per inviare un determinato codice di stato HTTP o quando un servlet genera una particolare eccezione Java.

L'elemento <error-page> contiene un elemento <error-code> con un valore del codice di errore HTTP (come 500) o un elemento <exception-type> con il nome della classe dell'eccezione prevista (come java.io.IOException). Contiene inoltre un elemento <location> contenente il percorso dell'URL della risorsa da mostrare quando si verifica l'errore.

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

Funzionalità web.xml non supportate

Le seguenti funzionalità web.xml non sono supportate da App Engine:

  • App Engine supporta l'elemento <load-on-startup> per le dichiarazioni servlet. Tuttavia, il carico si verifica effettivamente durante la prima richiesta gestita dall'istanza del server web, non prima.
  • Alcuni elementi dei descrittore di deployment possono avere un nome visualizzato, una descrizione e un'icona leggibili da una persona per l'utilizzo negli IDE. App Engine non le utilizza e le ignora.
  • App Engine non supporta le variabili di ambiente JNDI (<env-entry>).
  • App Engine non supporta le risorse EJB (<resource-ref>).
  • La notifica dell'eliminazione di servlet, contesto servlet o filtri non è supportata.
  • L'elemento <distributable> viene ignorato.
  • La pianificazione servlet con <run-at> non è supportata.