Les servlets
Introduction
Dans l’environnement Java, une application web est une collection de servlets, de pages HTML, de classes et de toutes autres ressources utiles à la bonne exécution de l’application (des fichiers CSS, des fichiers JavaScript, des fichiers images...).
Une servlet est un composant web de la technologie Java. Une servlet est une classe Java permettant de générer un contenu dynamique. Elle est gérée par un conteneur appelé généralement conteneur web, conteneur de servlet ou moteur de servlets.
Ce conteneur est une extension à un serveur web et propose les fonctionnalités indispensables au fonctionnement des servlets (décoder les requêtes, générer les réponses, gérer le cycle de vie des servlets).
La spécification Java Servlet Specification est actuellement dans sa version 5.0. Vous pouvez la consulter à l’adresse suivante : https://jakarta.ee/specifications/servlet/5.0/jakarta-servlet-spec-5.0.pdf.
La servlet est, bien entendu, l’élément central de cette spécification. Il ne faut cependant pas oublier d’autres composants importants de cette spécification :
-
les filtres,
-
les événements,
-
les cookies,
-
les sessions.
Le chapitre aborde l’ensemble de ces points.
La structure d’une application web
1. Présentation
Une application web, quelle que soit la technologie serveur utilisée, permet de délivrer des réponses à des requêtes HTTP. Un ensemble de langages est commun à tous les environnements :
-
HTML (HyperText Markup Language) : langage incontournable dans le développement web. Il permet de présenter le résultat à l’utilisateur.
-
CSS (Cascading Style Sheet) : langage permettant d’améliorer la présentation HTML en définissant des règles de représentation (coloration, police d’écriture, disposition...).
-
JavaScript : langage permettant d’améliorer l’expérience utilisateur en apportant des traitements plus ou moins complexes côté client. Il peut, aujourd’hui, aussi être utilisé côté serveur à l’instar du Java.
-
SQL (Structured Query Language) : langage permettant d’accéder aux données si la base de données sous-jacente est une base de données relationnelles.
D’autres langages/technologies peuvent être utilisés comme le XML...
Pour rendre la génération des réponses dynamiques, il est nécessaire d’utiliser une technologie prévue à cet effet. Parmi les plus connues, citons :
-
Le PHP,
-
Le C# et le VB.NET de l’environnement Microsoft,
-
Et bien entendu, le Java.
2. La structure logique d’une application web
Le schéma suivant montre la communication entre le client et le serveur et la manière classique utilisée par le serveur pour restituer une réponse générée dynamiquement :
Le client émet une requête HTTP vers le serveur. Si la requête HTTP est associée à une servlet, alors celle-ci est exécutée. Cette servlet utilise des classes Java pour calculer la réponse (Modèle). Lorsque toutes les informations sont obtenues, la servlet demande à une page JSP (Java Server Page) de constituer une réponse exploitable par le client (typiquement en HTML). Le chapitre suivant est dédié à la technologie JSP. Dans le cadre du chapitre actuel, les servlets généreront elles-mêmes la réponse exploitable par le client.
Cette architecture...
Le projet
La suite du chapitre se base sur un projet exemple nommé Projet_Servlet.
Commencez par créer un projet de type Gradle Project avec les mêmes caractéristiques que dans le chapitre précédent.
Complétez l’arborescence de répertoires pour qu’elle ressemble à cela :
Ajoutez un fichier nommé web.xml dans le répertoire src/main/webapp/WEB-INF avec le contenu décrit dans la section précédente.
Modifiez le fichier build.gradle avec le contenu suivant (observez la section dependencies permettant de référencer l’API des servlets) :
plugins {
id 'java'
id 'war'
}
repositories {
jcenter()
}
dependencies {
compileOnly "jakarta.servlet:jakarta.servlet-api:5.0.0"
}
Sélectionnez le menu contextuel Gradle - Refresh Gradle Project de votre projet pour télécharger les dépendances.
Le projet est prêt pour manipuler les servlets.
Les servlets
Tout est prêt pour commencer à développer des servlets.
1. Qu’est-ce qu’une servlet ?
Une servlet est tout simplement une classe Java utilisée pour étendre les capacités d’un serveur qui héberge des applications accessibles au travers d’un modèle de programmation requête/réponse. Les servlets peuvent donc répondre à n’importe quel type de requêtes cependant, le cas le plus courant est le traitement de requêtes HTTP.
Dans le cadre d’une application web, une servlet est une classe Java accessible au travers d’une ou plusieurs URL HTTP.
Les packages jakarta.servlet et jakarta.servlet.http fournissent les interfaces et les classes nécessaires à l’écriture des servlets. Une servlet doit implémenter l’interface Servlet définissant les méthodes du cycle de vie d’une servlet. La classe abstraite GenericServlet implémente cette interface. La classe HttpServlet hérite de cette classe et ajoute les méthodes permettant de traiter les requêtes HTTP comme les méthodes doGet(...) et doPost(...) pour traiter les requêtes de type GET et de type POST.
La création d’une servlet consiste à créer une classe Java héritant de la classe HttpServlet et à substituer les méthodes nécessaires pour obtenir le comportement attendu.
Voici un diagramme de classes résumant cette architecture :
La classe fr.editions_eni.jakartaee.servlets.MaServlet est une servlet permettant de traiter une requête HTTP et de retourner une réponse HTTP.
2. Le cycle de vie d’une servlet
Le développeur n’a pas à créer lui-même d’instances de la servlet. Le cycle de vie d’une servlet est contrôlé par le conteneur dans lequel la servlet est déployée. Lorsqu’une requête HTTP nécessite l’exécution d’une servlet, le conteneur effectue les traitements suivants :
-
Si aucune instance de la servlet n’existe, alors le conteneur :
-
Charge la classe de la servlet.
-
Crée une instance de la servlet.
-
Appelle la méthode init() pour initialiser d’éventuels paramètres.
-
Le conteneur appelle ensuite systématiquement...
Le suivi de l’activité de l’utilisateur
1. Présentation
Le protocole HTTP est un protocole sans état. C’est-à-dire que lorsqu’une requête est traitée, le client et le serveur s’oublient mutuellement. Or il est important de pouvoir maintenir un dialogue entre les deux parties. Lorsque vous naviguez dans un site de e-commerce, il est normal que votre panier ne soit pas vidé à chaque fois que vous changez de page. Lorsque vous vous connectez à votre banque en ligne, il est normal que le serveur se souvienne de vous tout le long de l’activité que vous menez sur le site. Il faut donc stocker des informations contextuelles. Ces informations peuvent être stockées au niveau du poste client ; les cookies sont alors utilisés. Ces informations peuvent être stockées au niveau du serveur ; les sessions sont alors utilisées.
Les prochaines sections traitent de ces deux modes de stockage.
2. Les cookies
a. Présentation
Un cookie est tout simplement un couple clé/valeur. La clé et la valeur sont représentées sous la forme d’une chaîne de caractères. La taille d’un cookie ne peut pas dépasser 4 096 octets. Les cookies peuvent être vus comme des petits fichiers contenant des informations. Ils sont créés par le serveur et envoyés vers le navigateur qui s’occupe de les stocker.
Lorsque le client effectue une nouvelle requête vers l’application ayant fourni les cookies, ceux-ci sont renvoyés vers le serveur. Ils peuvent permettre au serveur de se souvenir du dialogue en cours. Le serveur renverra à son tour les cookies si ceux-ci ont été modifiés.
Voici un schéma résumant ce principe :
Il existe différents types de cookies. La spécification n’autorise que la manipulation de cookies de type HttpOnly. Ces cookies ont la particularité de ne pas pouvoir être exploités par un script côté client écrit en JavaScript par exemple. Cela permet d’éviter les attaques par cross-site scripting (XSS).
Les cookies peuvent être refusés par le navigateur si l’utilisateur l’a paramétré ainsi. Ceci peut être un problème pour une bonne utilisation de l’application....
Les filtres
1. Présentation
Un filtre est un composant logiciel s’exécutant à l’arrivée d’une requête HTTP sur le serveur avant que celle-ci ne soit traitée pour ce qu’elle est. Un filtre permet donc de faire des traitements préalables. Ces traitements peuvent être divers et variés, comme par exemple :
-
Vérifier que le client est autorisé à accéder à la ressource demandée.
-
Enregistrer des informations liées à la requête pour effectuer des statistiques ultérieures.
-
Modifier les en-têtes de requête ou de réponse.
Voici un schéma récapitulatif de ce mécanisme :
Il peut y avoir un ou plusieurs filtres. Certains filtres peuvent empêcher l’accès à la ressource (sous conditions) en retournant une réponse au client ou rediriger vers une autre ressource. Toutes les ressources ne sont pas forcément derrière un filtre à partir du moment où ils sont utilisés.
Un filtre correspond à une classe Java qui implémente l’interface javax.servlet.Filter.
2. Mise en œuvre
a. La création d’un filtre
Pour créer un filtre, veuillez suivre les étapes suivantes :
Faites un clic droit sur le projet et cliquez sur le menu New - Filter. L’écran suivant apparaît, dans lequel vous saisissez un nom de package et un nom de classe.
Cliquez sur le bouton Next pour arriver sur l’écran suivant permettant de définir des paramètres d’initialisation et les URL pour lesquelles le filtre doit s’exécuter. Par défaut, l’URL paramétrée correspond au nom du filtre.
Cliquez sur le bouton Add de la section Filter mappings pour arriver sur l’écran suivant permettant d’ajouter des Servlet ou des URL pattern pour lesquels le filtre doit s’exécuter.
Cochez la case URL pattern et saisissez le pattern /*. Le filtre sera ainsi exécuté pour toutes les requêtes HTTP. La section Select dispatchers permet de préciser les origines de la requête pour lesquelles le filtre va être exécuté :
-
REQUEST : la requête provient du client.
-
FORWARD : la requête fait suite à l’appel...
Les événements
1. Présentation
Lorsqu’une application est en cours d’exécution, des objets gérés par le conteneur de servlets sont créés, manipulés et détruits. Il peut être intéressant d’être notifié de ces événements afin d’opérer des traitements associés. Pour être notifié d’un événement, il faut créer une classe implémentant une interface correspondant à l’événement nous intéressant. Les sections suivantes traitent de ces événements en fonction du contexte auquel ils se rapportent. Pour plus d’informations sur les contextes, veuillez vous référer à la section Les différents contextes un peu plus haut dans ce chapitre.
Dans les captures d’écran de cette section, des interfaces du package javax.servlet.http sont mentionnées mais dans la dernière spécification, ce package a été renommé jakarta.servlet.http.
2. Le paramétrage des classes
La classe doit être déclarée dans l’environnement pour que les méthodes qu’elle a implémentées soient appelées lors de l’événement correspondant. Cette déclaration peut se faire comme pour les servlets et les filtres au niveau du descripteur de déploiement ou à l’aide d’une annotation.
Dans le fichier web.xml, il faut déclarer la classe à l’aide de la balise <listener> et de la sous-balise <listener-class> comme le montre l’exemple suivant :
<listener>
<listener-class>
fr.editions_eni.jakartaee.listeners.ExempleListener
</listener-class>
</listener
Avec les annotations, il suffit de placer l’annotation @WebListener au niveau de la déclaration de la classe :
@WebListener
public class ExempleListener implements
XXXListener,
YYYListener
{
//...
}
Les interfaces XXXListener et YYYListener sont à remplacer par les interfaces décrites dans...
La sécurité
La sécurité est abordée dans le chapitre traitant du déploiement sur Tomcat.
Conclusion
Ce chapitre a permis de passer en revue les éléments essentiels pour bien démarrer un projet utilisant les servlets. Les servlets sont le cœur de la spécification éponyme. Elles permettent de traiter des requêtes HTTP et d’apporter des réponses adaptées. Cependant, sans l’existence des autres éléments, la technologie resterait limitée. Les cookies, les sessions et les filtres font partie intégrante de la spécification et apportent la richesse et la flexibilité nécessaires.