A. Présentation

publicité
Les servlets
A. Présentation
La première question que l'on se pose lorsque l'on commence à développer des
applications Web concerne en général l'aspect que peut avoir une servlet. En fait
une servlet est une simple classe Java permettant d'ajouter des fonctionnalités à un
serveur d'application. Pour que le serveur puisse prendre en charge cette nouvelle
classe, celle-ci doit respecter certaines contraintes.
Lorsqu'un client souhaite exécuter le code ajouté sur le serveur d'application, il doit
en faire la demande au serveur par l'intermédiaire du protocole HTTP. Cette
demande prend en général la forme d'une requête HTTP expédiée par le client à
destination de l'URL associée par le serveur à la servlet. Celle-ci exécute le
traitement et génère une réponse HTTP pour transmettre au client le résultat de
son exécution.
ã Editions ENI - All rights reserved
1. Dialogue avec une servlet
La base du dialogue entre un client et une servlet repose donc sur le protocole
HTTP. Ce protocole est basé sur l'utilisation d'un couple requête-réponse. La
requête est utilisée pour véhiculer l'information du client vers le serveur, la réponse
étant bien sûr utilisée pour transporter de l'information du serveur vers le client.
Les informations insérées dans la réponse HTTP sont en général liées aux résultats
de l'exécution du code de la servlet. La création et l'expédition de la requête HTTP
sont généralement confiées à un navigateur web. Celui-ci collecte les informations
saisies par l'utilisateur par l'intermédiaire d'un document HTML puis effectue la
mise en forme de ces informations en générant une requête HTTP. Cette requête
est expédiée via un réseau à destination du serveur d'application. Le serveur
réceptionne et analyse alors cette requête puis exécute la servlet concernée par la
requête HTTP. La réponse HTTP est alors générée par le serveur puis expédiée vers
le client toujours par l'intermédiaire du réseau. Le client (navigateur) réceptionne
alors cette réponse et analyse son contenu afin de déterminer comment il doit
l'interpréter (page HTML, image, son...).
Le développement d'applications web avec JEE 6
45
Chapitre 3
Ce fonctionnement est résumé sur le schéma ci-dessous.
2. Traitements effectués
Lors de la réception d'une requête HTTP par le serveur d'application, celui-ci
transforme la requête HTTP, qui pour le moment est sous la forme d'une chaîne de
caractères, en objet Java. Les informations contenues dans la requête HTTP sont
transférées dans les propriétés de l'objet Java créé. Un objet Java représentant la
réponse HTTP est également créé. Il est utilisé par la servlet pour construire la
réponse qui sera ensuite renvoyée vers le client. Le serveur extrait ensuite de la
requête le nom de la servlet qu'il doit exécuter. Le contrôle est alors passé à la
servlet par l'appel de sa méthode service. Les objets représentant la requête et
la réponse HTTP sont passés comme paramètres à la méthode service. Le principal
travail de celle-ci consiste à déterminer le type de requête HTTP (GET, POST...).
La dernière étape pour la servlet consiste à exécuter la méthode appropriée pour le
traitement de ce type de requête (doGet, doPost...). Ces méthodes reçoivent
également les deux objets créés pour représenter la requête et la réponse HTTP. Le
contenu de chacune de ces méthodes n'est pas figé mais sera redéfini par le
concepteur de la servlet. Notre principal travail avec les servlets va donc consister
à concevoir le contenu de ces méthodes. Dans la grande majorité des cas, ces
méthodes vont extraire de la requête HTTP les paramètres reçus à partir du client,
effectuer un traitement, puis construire la réponse. Lorsque le traitement de la
servlet est terminé le serveur est à nouveau mis à contribution pour cette fois
exécuter l'opération inverse de précédemment. L'objet représentant la réponse est
transformé en réponse HTTP sous forme de texte puis celui-ci est retourné au
client. Le traitement de la requête par la servlet est alors terminé.
46
Java Enterprise Edition
Les servlets
3. Classes et interfaces utilisées
Pour réaliser le traitement d'une requête HTTP, le serveur utilise de nombreuses
classes et interfaces. Lorsque le serveur transforme la requête HTTP brute (sous
forme d'une chaîne de caractères) en objet Java il utilise une classe qui
implémente l'interface javax.servlet.http.HttpServletRequest. Cette
interface hérite elle-même de l'interface javax.servlet.ServletRequest.
L'objet obtenu permet ainsi d'accéder facilement aux principales informations
véhiculées par la requête HTTP. Son utilisation est détaillée dans la section Utiliser
la requête HTTP de ce chapitre.
ã Editions ENI - All rights reserved
Un autre objet implémentant l'interface javax.servlet.http.HttpServletResponse, héritant de l'interface javax.servlet.ServletResponse est
également créé pour permettre la construction de la réponse HTTP par la servlet.
L'utilisation de cet objet est détaillée dans la section Construire la réponse HTTP
de ce chapitre.
Pour que le serveur d'application puisse prendre en charge l'exécution de la servlet,
celle-ci doit respecter certaines caractéristiques. Ces caractéristiques sont définies
dans l'interface javax.servlet.Servlet qui est implémentée par la classe
abstraite javax.servlet.GenericServlet. Cette classe est ensuite
spécialisée par la classe javax.servlet.http.HttpServlet définissant les
caractéristiques d'une servlet pouvant être contactée grâce au protocole HTTP.
C'est pratiquement toujours cette classe qui est utilisée comme classe de base pour
les servlets. La section suivante détaille les principales méthodes disponibles
pouvant être redéfinies dans cette classe.
Le développement d'applications web avec JEE 6
47
Chapitre 3
B. Cycle de vie d'une servlet
Comme n'importe quelle classe Java, une servlet doit être instanciée pour pouvoir
être utilisée. Généralement lorsque vous avez besoin d'une instance de classe, vous
utilisez l'opérateur new pour la créer. Le problème avec une servlet est que l'on ne
sait pas exactement à quel moment on va en avoir besoin. Ce sont en fait les
clients qui décident lorsqu'une instance de servlet est nécessaire en générant une
requête HTTP pour demander son exécution. Le serveur d'application étant le
mieux placé pour détecter cette demande, c'est donc lui qui est responsable de la
création et de la destruction des instances de servlets. Pour ceci il utilise la
stratégie suivante :
Dès la réception d'une requête HTTP, il détermine si celle-ci concerne une servlet.
Si c'est le cas, il vérifie s'il y a déjà une instance de cette servlet en mémoire, il
appelle alors la méthode service de cette instance de servlet. Si aucune instance
de cette servlet n'est disponible le serveur en crée une puis appelle la méthode
init de cette nouvelle instance. Il peut alors ensuite appeler la méthode
service de la servlet.
Avec cette technique, une même instance de servlet va donc traiter les requêtes
HTTP de très nombreux clients. Lorsque le serveur estime qu'il n'a plus besoin de
cette servlet, il détruit automatiquement l'instance correspondante. Cette situation
se produit en général uniquement lors de l'arrêt du serveur ou lorsqu'une nouvelle
version de la servlet est disponible. Avant la suppression de l'instance d'une servlet
la méthode destroy de celle-ci est exécutée.
1. Déclaration de la servlet
Pour que le serveur puisse instancier la servlet, il doit bien sûr être informé de son
existence. Celle-ci doit donc être déclarée dans le descripteur de déploiement de
l'application. La déclaration suivante est à insérer dans le descripteur de déploiement pour chaque servlet de l'application.
<servlet>
<servlet-name>PremiereServlet</servlet-name>
<servlet-class>fr.eni.ri.PremiereServlet</servlet-class>
</servlet>
48
Java Enterprise Edition
Les servlets
Il est également conseillé d'ajouter une déclaration <servlet-mapping> afin de
définir le ou les noms permettant de provoquer l'exécution de la servlet depuis une
URL.
<servlet-mapping>
<servlet-name>PremiereServlet</servlet-name>
<url-pattern>/PremiereServlet</url-pattern>
<url-pattern>/FirstServlet</url-pattern>
</servlet-mapping>
Cette déclaration est généralement utilisée pour éviter d'avoir à spécifier le nom du
package lors de l'appel de la servlet.
La version 3.0 des spécifications JEE concernant les servlets permet de remplacer
ces deux déclarations par des annotations Java placées directement dans le code
source de la servlet. Ces annotations sont analysées lors du déploiement de la
servlet sur le serveur d'application.
Les deux déclarations précédentes peuvent être remplacées par l'annotation suivante utilisée sur la classe de la servlet.
@WebServlet(name="PremiereServlet",
urlPatterns={"/PremiereServlet", "/FirstServlet" })
public class PremiereServlet extends HttpServlet
{
...
}
D'autres annotations permettant la simplification du descripteur de déploiement
sont répertoriées en annexe.
ã Editions ENI - All rights reserved
2. Méthode init
La méthode init est appelée par le serveur aussitôt après l'instanciation de la
servlet. Par défaut l'implémentation de cette méthode ne fait rien. Elle est en fait
prévue pour permettre l'initialisation des ressources dont va avoir besoin la servlet
pour exécuter ses traitements. Elle peut par exemple être utilisée pour établir une
connexion vers un serveur de base de données ou ouvrir un fichier dans lequel la
servlet va enregistrer des informations (journalisation d'informations). Si l'exécution
de la méthode init ne se passe pas correctement une exception de type
ServletException doit être déclenchée. Cette exception permet au serveur de
détecter l'indisponibilité de la servlet.
Le développement d'applications web avec JEE 6
49
Chapitre 3
3. Paramètres d'initialisation
Il est possible d'éviter de placer directement dans le code certaines informations
dont une servlet va avoir besoin pour son initialisation. Par exemple dans le cas où
celle-ci a besoin d'établir une connexion vers un serveur de base de données les
coordonnées du serveur ne seront connues qu'au moment du déploiement de
l'application sur le serveur de production. Si ces informations sont inscrites directement dans le code, il faut obligatoirement modifier celui-ci et le recompiler lors du
déploiement de l'application. Pour éviter cette manipulation, ce type d'information
peut être placé dans le descripteur de déploiement de l'application (web.xml). La
méthode init va pouvoir récupérer les informations à partir de ce fichier. Les
informations d'initialisation de chaque servlet sont à ajouter à l'intérieur de la balise
<servlet> par l'intermédiaire d'une balise <init-param>. Cette balise
comporte deux éléments obligatoires :
- <param-name> : représente le nom du paramètre. Ce nom doit être utilisé
dans la méthode init de la servlet pour accéder au paramètre.
- <param-value> : représente la valeur affectée au paramètre.
L'élément <description> est quant à lui optionnel mais très utile pour la clarté
du descripteur de déploiement.
La déclaration d'une servlet dans le fichier web.xml prend donc la forme suivante :
<servlet>
<servlet-name>PremiereServlet</servlet-name>
<servlet-class>fr.eni.ri.PremiereServlet</servlet-class>
<init-param>
<description>
adresse du serveur de base de données
</description>
<param-name>adresseIpBDD</param-name>
<param-value>127.0.0.1</param-value>
</init-param>
</servlet>
Il est également possible de déclarer les paramètres d'initialisation d'une servlet en
utilisant les annotations.
@WebServlet(name"PremiereServlet",
urlPatterns={"/PremiereServlet", "/FirstServlet" },
initParams={@WebInitParam(description="adresse du serveur de base de données" ,
name="adresseIpBDD" , value="127.0.0.1")})
50
Java Enterprise Edition
Téléchargement