Descripteur de déploiement : web.xml

ID de la région

Le code REGION_ID est attribué par Google en fonction de la région que vous sélectionnez lors de la création de votre application. L'ajout de REGION_ID.r dans les URL App Engine est facultatif pour les applications existantes. Il sera bientôt nécessaire pour toutes les nouvelles applications.

Pour assurer une transition en douceur, nous mettons lentement à jour App Engine afin d'utiliser les ID de région. Si nous n'avons pas encore mis à jour votre projet Google Cloud, vous ne verrez pas d'ID de région pour votre application. Étant donné que l'ID est facultatif pour les applications existantes, vous n'avez pas besoin de mettre à jour les URL ni d'effectuer d'autres modifications une fois l'ID de région disponible pour vos applications existantes.

En savoir plus sur les ID de région.

Les applications Web Java utilisent un fichier descripteur de déploiement pour définir la méthode de mappage des URL sur les servlets, déterminer les URL qui nécessitent une authentification ainsi que d'autres informations. Ce fichier s'appelle web.xml et il se trouve dans le fichier d'archives WAR de l'application, sous le répertoire WEB-INF/. web.xml fait partie de la norme Servlet pour les applications Web.

Pour plus d'informations sur la norme web.xml, consultez le wiki de référence sur Metawerx web.xml et la spécification de servlet.

Descripteurs de déploiement

Le descripteur de déploiement d'une application Web décrit les classes, les ressources et la configuration de l'application, ainsi que la manière dont le serveur Web les utilise pour diffuser des requêtes Web. Lorsque le serveur Web reçoit une requête pour une application, il se sert du descripteur de déploiement pour mapper l'URL de la requête sur le code destiné à traiter la requête.

Le descripteur de déploiement est un fichier appelé web.xml. Il se trouve dans le fichier d'archives WAR de l'application, sous le répertoire WEB-INF/. Il s'agit d'un fichier XML dont l'élément racine est <web-app>.

Voici un exemple web.xml simple de fichier qui mappe tous les chemins d'URL (/*) sur la classe de 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>

Servlets et chemins d'URL

Le fichier web.xml définit les mappages entre les chemins d'URL et les servlets qui traitent les requêtes avec ces chemins. Le serveur Web utilise cette configuration pour identifier le servlet afin de traiter une requête donnée, et ainsi appeler la méthode de classe qui correspond à la méthode de requête. Par exemple : la méthode doGet() pour les requêtes HTTP GET.

Pour mapper une URL sur un servlet, vous déclarez le servlet avec l'élément <servlet>, puis vous définissez un mappage à partir d'un chemin d'URL sur une déclaration de servlet avec l'élément <servlet-mapping>.

L'élément <servlet> déclare le servlet, notamment le nom utilisé pour faire référence au servlet via d'autres éléments du fichier, la classe utilisée avec le servlet et les paramètres d'initialisation. Il vous est possible de déclarer plusieurs servlets à l'aide de la même classe via des paramètres d'initialisation différents. Chaque nom de servlet doit être unique au sein du descripteur de déploiement.

    <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'élément <servlet-mapping> indique un modèle d'URL et le nom d'un servlet déclaré à utiliser avec les requêtes dont l'URL correspond au modèle. Un astérisque (*) peut être utilisé en début ou en fin de modèle pour remplacer un zéro ou plusieurs caractères. La norme n'autorise pas les caractères génériques au milieu d'une chaîne, ni l'utilisation de plusieurs caractères génériques dans un même modèle. Le modèle correspond au chemin complet de l'URL, commençant par la barre oblique (/) suivie du nom de domaine. Le chemin de l'URL ne peut pas commencer par un point (.).

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

Dans cet exemple, une requête pour l'URL http://www.example.com/blue/teamProfile est traitée par la classe TeamServlet, avec le paramètre teamColor égal à blue et le paramètre bgColor égal à #0000CC. Le servlet peut faire correspondre la portion du chemin d'URL au caractère générique à l'aide de la méthode getPathInfo() de l'objet ServletRequest.

Le servlet peut accéder à ses paramètres d'initialisation en obtenant la configuration du servlet via sa propre méthode getServletConfig(), puis en appelant la méthode getInitParameter() sur l'objet de configuration via le nom du paramètre en tant qu'argument.

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

Pages JSP

Une application peut utiliser des pages JSP pour implémenter des pages Web. Les JSP sont des servlets définis à l'aide d'un contenu statique (HTML, par exemple) et de code Java.

App Engine est compatible avec la compilation automatique, ainsi que le mappage d'URL pour les JSP. Tout fichier JSP contenu dans le fichier d'archives WAR de l'application (en dehors de WEB-INF/), dont le nom de fichier se termine par .jsp, est compilé automatiquement dans une classe de servlet et est mappé sur le chemin d'URL qui correspond au chemin d'accès au fichier JSP dans la racine WAR. Par exemple, si une application possède un fichier JSP nommé start.jsp dans un sous-répertoire appelé register/ de son fichier d'archives WAR, App Engine le compile et le mappe sur le chemin d'accès à l'URL /register/start.jsp.

Si vous souhaitez exercer un contrôle plus rigoureux sur la manière dont la page JSP est mappée sur l'URL, vous pouvez spécifier explicitement le mappage en le déclarant avec un élément <servlet> dans le descripteur de déploiement. Au lieu d'indiquer un élément <servlet-class>, vous spécifiez un élément <jsp-file> avec le chemin d'accès au fichier JSP à partir de la racine du fichier d'archives WAR. L'élément <servlet> du JSP peut comporter des paramètres d'initialisation.

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

Vous pouvez installer des bibliothèques de balises JSP à l'aide de l'élément <taglib>. Une bibliothèque de balises comporte un chemin d'accès au fichier JSP de descripteur de bibliothèque de tags ou TLD (<taglib-location>) et un URI que les JSP utilisent pour sélectionner la bibliothèque à charger (<taglib-uri>). Notez qu'App Engine fournit la bibliothèque de balises standards des pages JavaServer (JSTL) et que vous n'avez pas besoin de l'installer.

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

Sécurité et authentification

Une application App Engine peut utiliser Google Accounts pour procéder à l'authentification utilisateur. L'application peut utiliser l'API Google Accounts pour détecter si l'utilisateur est connecté, obtenir l'adresse électronique de l'utilisateur connecté actuellement, et générer les URL de connexion et déconnexion. Une application peut également définir des restrictions d'accès pour les chemins d'URL sur la base de Google Accounts, en utilisant le descripteur de déploiement.

L'élément <security-constraint> définit une contrainte de sécurité pour les URL qui correspondent à un modèle. Si un utilisateur accède à une URL dont le chemin possède une contrainte de sécurité et que l'utilisateur n'est pas connecté, App Engine redirige l'utilisateur vers la page de connexion de Google Accounts. Google Accounts redirige l'utilisateur vers l'URL de l'application une fois que l'utilisateur est connecté ou qu'il a ouvert un nouveau compte. L'application n'effectue aucune action pour vérifier que seuls les utilisateurs connectés peuvent accéder à l'URL.

Une contrainte de sécurité inclut une contrainte d'autorisation qui indique les utilisateurs Google Accounts habilités à accéder à l'URL. Si la contrainte d'autorisation spécifie un rôle d'utilisateur *, tous les utilisateurs connectés à un compte Google peuvent accéder à l'URL. Si la contrainte indique un rôle d'utilisateur admin, seuls les développeurs enregistrés de l'application peuvent accéder à l'URL. Le rôle admin permet de construire plus facilement des sections administrateur uniquement au sein de votre site.

    <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 ne permet pas d'utiliser les rôles de sécurité personnalisés (<security-role>) ni les mécanismes d'authentification de substitution (<login-config>) dans le descripteur de déploiement.

Les contraintes de sécurité s'appliquent aussi bien aux fichiers statiques qu'aux servlets.

URL sécurisées

Google App Engine autorise les connexions sécurisées via HTTPS pour les URL utilisant le domaine REGION_ID.r.appspot.com. Lorsqu'une requête accède à une URL via HTTPS et que cette URL est configurée pour utiliser HTTPS dans le fichier web.xml, l'expéditeur chiffre les données contenues dans la requête et dans la réponse avant de les transmettre, et le destinataire les déchiffre après leur réception. Les connexions sécurisées permettent de protéger les données des clients, telles que les coordonnées, les mots de passe et les messages privés.

Pour déclarer que HTTPS doit être utilisé pour une URL, vous devez définir une contrainte de sécurité dans le descripteur de déploiement (comme cela est décrit dans la section Sécurité et authentification) avec une contrainte <user-data-constraint> dont la garantie de transport <transport-guarantee> est CONFIDENTIAL. Par exemple : Exemple :

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

Les requêtes basées sur le protocole non sécurisé HTTP pour les URL dont la garantie de transport est CONFIDENTIAL sont automatiquement redirigées vers la même URL via HTTPS.

Toute URL peut utiliser la garantie de transport CONFIDENTIAL, y compris les JSP et les fichiers statiques.

Le serveur Web de développement n'accepte pas les connexions HTTPS. Il ignore la garantie de transport de sorte que les chemins accessibles via HTTPS peuvent être testés par le biais de connexions HTTP standard vers le serveur Web de développement.

Lorsque vous testez les gestionnaires HTTPS de votre application à l'aide de l'URL appspot.com correcte, telle que https://1.latest.your_app_id.REGION_ID.r.appspot.com/, votre navigateur vous informe que le certificat HTTPS n'a pas été signé pour le chemin de domaine spécifié. Si vous acceptez le certificat pour ce domaine, le chargement des pages s'effectue correctement. Les utilisateurs ne verront pas l'avertissement concernant le certificat lorsqu'ils accéderont à l'adresse https://your_app_id.REGION_ID.r.appspot.com/.

Vous pouvez également utiliser une autre forme de l'URL versionnée d'appspot.com conçue pour éviter ce problème en remplaçant les points séparant les composants du sous-domaine par "-dot-". Par exemple, l'exemple précédent est accessible sans avertissement de certificat à l'adresse https://VERSION_ID-dot-default-dot-PROJECT_ID.REGION_ID.r.appspot.com.

Pour les comptes Google, la connexion et la déconnexion s'effectuent toujours via une connexion sécurisée, quelle que soit la manière dont les URL sont configurées.

Comme indiqué précédemment, les contraintes de sécurité s'appliquent aussi bien aux fichiers statiques qu'aux servlets. Cela inclut la garantie de transport.

Remarque : Google recommande d'utiliser le protocole HTTPS pour envoyer des requêtes à votre application. Google n'émet pas de certificat SSL pour les domaines à double caractère générique hébergés sur appspot.com. Par conséquent, les requêtes HTTPS doivent utiliser la chaîne "-dot-", au lieu de "." pour séparer les sous-domaines, comme illustré dans les exemples ci-dessous. Vous pouvez utiliser une notation simple "." avec votre propre domaine personnalisé ou avec des adresses HTTP.

Liste des fichiers de bienvenue

Lorsque les URL de votre site représentent des chemins d'accès à des fichiers statiques ou à des JSP dans votre fichier d'archives WAR, il peut être judicieux que les chemins d'accès aux répertoires représentent également quelque chose. Par exemple, si un utilisateur accède au chemin d'URL /help/accounts/password.jsp pour obtenir des informations sur les mots de passe du compte, il essaiera peut-être d'accéder au chemin /help/accounts/ pour afficher une page présentant la documentation système sur les comptes. Le descripteur de déploiement permet de spécifier une liste de noms de fichiers que le serveur doit consulter lorsque l'utilisateur accède à un chemin qui correspond à un sous-répertoire du fichier d'archives WAR (qui n'est pas explicitement mappé sur un servlet). La norme de servlet l'appelle la "liste des fichiers de bienvenue".

Par exemple, si l'utilisateur accède au chemin d'URL /help/accounts/, l'élément suivant <welcome-file-list> du descripteur de déploiement demande au serveur de vérifier les fichiers help/accounts/index.jsp et help/accounts/index.html avant de signaler que l'URL n'existe pas.

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

Filtres

Un filtre est une classe qui agit sur une requête comme un servlet, mais qui permet de poursuivre le traitement de la requête avec d'autres filtres ou servlets. Un filtre peut exécuter une tâche secondaire telle que la connexion, en effectuant des vérifications d'authentification spéciales ou en annotant les objets de requête ou de réponse avant d'appeler le servlet. Les filtres vous permettent d'élaborer des tâches de traitement des requêtes à partir du descripteur de déploiement.

Une classe de filtre met en œuvre l'interface javax.servlet.Filter, y compris la méthode doFilter(). Voici une simple mise en œuvre de filtre qui enregistre un message, puis transmet le contrôle à la chaîne qui peut inclure d'autres filtres ou un servlet, comme décrit dans le descripteur de déploiement :

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

}

De la même manière que pour les servlets, vous configurez un filtre dans le descripteur de déploiement en déclarant le filtre avec l'élément <filter>, puis en le mappant sur un modèle d'URL avec l'élément <filter-mapping>. Vous avez également la possibilité de mapper les filtres directement sur d'autres servlets.

L'élément <filter> comporte un élément <filter-name> et <filter-class> ainsi que des éléments <init-param> facultatifs.

    <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'élément <filter-mapping> comporte un élément <filter-name> qui correspond au nom d'un filtre déclaré, et soit un élément <url-pattern> permettant d'appliquer le filtre aux URL, soit un élément <servlet-name> qui correspond au nom d'un servlet déclaré afin d'appliquer le filtre chaque fois que le servlet est appelé.

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

Gestionnaire d'erreurs

Grâce au descripteur de déploiement, vous pouvez personnaliser les données que le serveur envoie à l'utilisateur en cas d'erreur. Le serveur peut afficher une page de remplacement lorsqu'il est sur le point d'envoyer un code d'état HTTP particulier, ou lorsqu'un servlet génère une exception Java particulière.

L'élément <error-page> contient soit un élément <error-code> avec une valeur de code d'erreur HTTP (par exemple, 500), soit un élément <exception-type> avec le nom de classe de l'exception attendue (par exemple, java.io.IOException). Il contient également l'élément <location> contenant le chemin d'URL de la ressource à afficher lorsque l'erreur se produit.

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

Fonctionnalités web.xml incompatibles

Les caractéristiques web.xml suivantes ne sont pas compatibles avec App Engine :

  • App Engine prend en charge les éléments <load-on-startup> pour les déclarations de servlet. Toutefois, la charge se produit lors de la première requête traitée par l'instance de serveur Web, et non avant.
  • Certains éléments de descripteur de déploiement peuvent avoir un nom à afficher, une description et une icône interprétables par l'utilisateur sous des environnements de développement intégrés. App Engine ne tient pas compte de ces éléments.
  • App Engine ne prend pas en charge les variables d'environnement JNDI (<env-entry>).
  • App Engine ne prend pas en charge les ressources EJB (<resource-ref>).
  • La notification de la destruction de servlets, de contexte de servlet, ou de filtres n'est pas acceptée.
  • L'élément <distributable> n'est pas pris en compte.
  • La planification des servlets avec <run-at> n'est pas prise en charge.