Descripteur de déploiement : web.xml

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 réside dans le fichier WAR de l'application, dans le répertoire WEB-INF/. web.xml fait partie de la norme de servlet des applications Web.

Pour plus d'informations sur la norme web.xml, consultez la référence wiki sur Metawerx web.xml et la spécification 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 nommé web.xml. Il se trouve dans le fichier d'archives WAR de l'application dans le répertoire WEB-INF/. Il s'agit d'un fichier XML dont l'élément racine est <web-app>.

Voici un exemple simple de fichier web.xml qui mappe l'ensemble des chemins d'URL (/*) à 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

web.xml définit les correspondances 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, y compris un nom utilisé par d'autres éléments du fichier pour désigner le servlet, la classe à utiliser pour le servlet et des 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> spécifie un modèle d'URL et le nom d'un servlet déclaré à utiliser pour 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 gérée par la classe TeamServlet, avec le paramètre teamColor égal à blue et le paramètre bgColor égal à #0000CC. Le servlet peut mapper la partie du chemin de l'URL avec le caractère générique en utilisant la méthode getPathInfo() de l'objet ServletRequest.

Le servlet peut accéder à ses paramètres d'initialisation en obtenant sa configuration de servlet à l'aide de sa propre méthode getServletConfig(), puis en lançant la méthode getInitParameter() sur l'objet de configuration en utilisant le nom du paramètre comme 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, puis 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 mieux contrôler les conditions de mappage des JSP sur une 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'un élément <servlet-class>, vous spécifiez un élément <jsp-file> avec le chemin d'accès au fichier JSP de la racine 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 avec l'élément <taglib>. Une bibliothèque de balises possède un chemin d'accès au fichier JSP descripteur de la bibliothèque de balises (TLD) (<taglib-location>) et un URI que JSP utilise pour sélectionner la bibliothèque pour le chargement (<taglib-uri>). Notez que App Engine fournit la Bibliothèque de balises standards des pages JSP (JSTL), et il n'est pas nécessaire 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 format. 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 gère pas 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 prend en charge les connexions sécurisées via HTTPS à l'aide du domaine *.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 :

    <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 ne prend pas en charge 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 en utilisant l'URL d'appspot.com versionnée, comme https://1.latest.your_app_id.appspot.com/, votre navigateur vous avertit que le certificat HTTPS n'a pas été signé pour ce chemin d'accès de domaine spécifique. Si vous acceptez le certificat pour ce domaine, le chargement des pages s'effectue correctement. Les utilisateurs ne verront pas l'avertissement de certificat lors de l'accès à https://your_app_id.appspot.com/.

Vous pouvez également utiliser une autre forme de l'URL d'appspot.com versionnée conçue pour éviter ce problème en remplaçant les points séparant les composants du sous-domaine par la chaîne "-dot-". Par exemple, l'exemple précédent était accessible sans avertissement de certificat sur https://1-dot-latest-dot-your_app_id.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 <welcome-file-list> suivant présent dans le descripteur de déploiement indique au serveur de rechercher 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() {}

}

Comme avec les servlets, vous configurez un filtre dans le descripteur de déploiement en déclarant le filtre à l'aide de 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> contient un <filter-name>, une <filter-class>, et 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> contient un nom <filter-name> qui correspond au nom d'un filtre déclaré, et soit un élément <url-pattern> pour appliquer le filtre aux URL, soit un élément <servlet-name> qui correspond au nom d'un servlet déclaré pour l'application du 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 (telle que 500), soit un élément <exception-type> avec le nom de classe de l'exception attendue (tel que java.io.IOException). Il inclut également un élément <location> contenant le chemin d'URL de la ressource à afficher quand 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 accepte l'élément <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 n'accepte pas les variables d'environnement de JNDI (<env-entry>).
  • App Engine n'accepte pas 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> est ignoré.
  • La planification de servlet avec <run-at> n'est pas acceptée.
Cette page vous a-t-elle été utile ? Évaluez-la :

Envoyer des commentaires concernant…

Environnement standard App Engine pour Java