|
Servlet & JSP - Développement Web
3.2.Implémentation de base
3.2.1.Structure fondamentale
Nous avons vu précédemment comment installer et
configurer un serveur Web et un moteur de servlets. Nous allons
maintenant nous attarder sur le concept même des servlets avec
leur conception proprement dite.
3.2.1.1.Interface Servlet
Pour qu’une classe représente une servlet, il faut
impérativement qu’elle implémente l’interface
Servlet (du package javax.servlet) directement ou
indirectement. Cette interface oblige à implémenter les
méthodes suivantes :
-
La méthode public void init( ServletConfig cfg )
-
La méthide public void service ( ServletRequest req,
ServletResponse res)
-
La méthode public void destroy ()
-
La méthode public ServletConfig getServletConfig ()
-
La méthode public String getServletInfo ()
Nous étudierons ces méthodes en détail
ci-dessous.
Remarque : les trois premières méthodes
représentent le cycle de vie d’une servlet.
L’utilisation de l’interface Servlet n’est pas très
courante. En effet différentes classes abstraites ont été
développées afin de simplifier la tâche au
développeur.
3.2.1.2.Classe GenericServlet
Cette première classe est la plus basique. Elle appartient
elle aussi au package java.servlet. Il vous suffit tout
simplement, dans une classe fille, d’implémenter la
méthode : public void service ( ServletRequest
req, ServletResponse res).
Voici un exemple de servlet implémentant cette classe :
import
java.io.IOException;
import
java.io.PrintWriter;
import
javax.servlet.GenericServlet;
import
javax.servlet.ServletRequest;
import
javax.servlet.ServletResponse;
public
final class
HelloServlet extends GenericServlet
{
public
void service (ServletRequest req,
ServletResponse res)
throws
IOException
{
res.setContentType
(“text/html”);
PrintWriter pageWriter =
res.getWriter();
pageWriter.println(“<html>”);
pageWriter.println(“<body>”);
pageWriter.println(“Coucou”);
pageWriter.println(“</body>”);
pageWriter.println(“</html>”);
}
}
3.2.1.3.Classe HttpServlet
Cette classe est un peu plus évoluée et davantage
orientée développement Web. Elle est cependant inclue
dans le package : javax.servlet.http. De même
que pour la classe précédente, nous pouvons simplement
implémenter la méthode : public void service (
ServletRequest req, ServletResponse res) cependant une
alternative s’ouvre à nous. Comme le protocole HTTP
permet de transmettre des données de différentes
manières (GET ou POST), cette classe possède les
méthodes s’y rapportant. Cela permet d’implémenter
les méthodes indépendamment des méthodes que
l’on souhaite utiliser.
-
La méthode public doGet ( ServletRequest req,
ServletResponse res) est appelée lors d’une
requête de type GET.
-
La méthode public doPost ( ServletRequest req,
ServletResponse res) est appelée lors d’une
requête de type POST.
Vous pouvez également trouver d’autres méthodes
public doXxx (ServletRequest req, ServletResponse res)
avec Xxx = ( Put, Delete, Options …)
Remarque : si vous ne souhaitez pas différencier
le type de méthode utilisée pour la requête, vous
pouvez soit utiliser la classe GenericServlet, soit n’implémenter
que la méthode service() dans votre servlet.
3.2.2.Cycle de vie
Nous avons pu voir que le moteur de servlet n’utilise qu’une
seule instance par servlet et que chaque requête cliente a pour
résultat un nouveau thread qui est transmis à doGet()
ou à doPost() ou bien service()
(selon les cas). Nous allons ici examiner comment les servlets sont
initialisées, utilisées et détruites. Ces étapes
s’appellent le « Cycle de vie » d’une
servlet.
3.2.2.1.La méthode init()
La méthode
init() est appelée uniquement lors du premier
appel à la servlet (soit via un appel client soit lors du
démarrage du serveur en fonction de votre configuration
serveur). Par conséquent, elle est employée pour
effectuer les opérations de paramétrage et
d’initialisation de la servlet.
Il existe
deux prototypes de la méthode init().
- Le
premier ne prend aucun argument et est utilisé lorsque la
servlet n’a pas à lire de paramètre variant d’un
serveur à l’autre.
La définition de celle-ci ressemble à ceci :
public
void init () throws
ServletException {
// Initialisation Code
}
-
La seconde version de init est utilisée lorsque le
servlet a besoin d’accéder aux paramètres de
configuration du serveur afin de s’adapter au serveur sur
laquelle elle est lancée. On peut très bien penser
récupérer les paramètres de connexion à
une base de données par exemple, un fichier de mots de passes
ou bien d’autres choses encore.
Le second prototype ressemble à ceci :
public
void init (ServletConfig cfg) throws
ServletException {
super.init(cfg);
// Initialisation Code
}
Cette méthode admet un argument de type ServletConfig
qui permet de récupérer les valeurs des différents
paramètres de configuration grâce à la méthode
getInitParameter() qui demande en entrée le nom
du paramètre et retourne, en sortie, sa valeur.
La première ligne du corps de la méthode fait appel à
super.init(). Cette ligne ne doit pas être
oubliée, en effet la méthode init() de la
classe parent enregistre l’objet ServletConfig à
un endroit précis dans la servlet qui est utilisé par
la suite.
Remarque : si vous décidez de surcharger la
méthode init(), n’oubliez surtout pas
l’appel à super.init() car vous risquez
d’avoir des problèmes …
3.2.2.2.La méthode service
Cette méthode est appelée pour chaque requête
reçue. Cette méthode vérifie le type de requête
et appelle automatiquement soit doGet(), doPost(),
doTrace() … Dans une servlet, qui doit traiter
les requêtes POST et GET de la même manière, vous
pourriez être tenté de surcharger service()
mais ce n’est pas la bonne solution ! En effet, cela
risquerait de nuire à l’évolution de votre
servlet. Il vaut mieux dans ce cas appeler doPost() via
doGet() ou inversement.
Grâce à cette méthode, vous pourrez, par la
suite, surcharger les méthodes doPut(),
doTrace(), doOptions() soit directement dans la
servlet soit dans les « servlets filles ».
Voici le prototype de cette méthode :
public
void service (ServletRequest req,
ServletResponse res)throws
IOException
3.2.2.3.La méthode destroy
Le serveur peut demander la suppression de l’instance de la
servlet, soit par demande explicite de l’administrateur
(redémarrage du serveur par exemple), soit parce que la
servlet demeure inactif pendant une trop longue période. Le
serveur appelle alors la méthode destroy de la servlet
afin que celle-ci effectue toutes les opérations de
destruction. Vous pouvez retrouver des opérations de fermeture
de connexion à une base de données, d’interruption
de threads lancés en tâches de fond, fermer un fichier…
Remarque : un serveur Web peut très bien
s’interrompre à cause d’un bug ou autre problème
technique (une personne peut très bien débrancher la
prise de courant !) c’est pour cela qu’il ne faut
pas faire confiance à 100% à l’appel automatique
de cette méthode et faire des sauvegardes d’éléments
principaux durant l’exécution de la servlet.
Voici le prototype de cette méthode :
public
void destroy()
3.2.3.Lire la requête
La lecture
des données de la requête se fait via l’instance
de l’objet : HttpServletRequest passée en
paramètre des méthodes doGet, doPost …
Depuis la
requête, il est possible de récupérer tous les
paramètres passés au ServeurWeb par le client :
Il existe
quatre méthodes pour cela :
-
La méthode getParameter ( String name ) :
retourne la valeur d’un parameter à partir de son nom
-
La méthode getParameterValues ( String name ) :
retourne une liste de valeurs d’un parameter à partir
de son nom (utilisé par exemple dans une liste à choix
multiples)
-
La méthode getParameterMap ( String name ) :
retourne une liste d’associations de paramètres et de
valeurs
-
La méthode getParameterNames ( String name ) :
retourne la liste de tous les noms des paramètres passés
au serveur web
Cet objet
permet également de récupérer des informations
concernant le client :
-
La méthode getRemoteAddr () : retourne l’IP
du client
-
La méthode getRemoteHost () : retourne le nom
complet de l’hôte client
De la même façon, nous pouvons récupérer
des informations concernant le serveur :
-
La méthode getServerName () : retourne le nom
complet du serveur
-
La méthode getServerPort () : retourne le
numéro du port utilisé par le serveur
Vous pouvez également accéder à l’ensemble
des variables d’environnement du serveur (comme pour les
scripts CGI).
Voici un tableau récapitulatif des méthodes à
utiliser :
Variable d’environnement
CGI
|
Méthodes d’une
servlet HTTP
|
|
|
SERVER_NAME
|
getServerName()
|
SERVER_PROTOCOLE
|
getProtocole()
|
SERVER_PORT
|
getServerPort()
|
REQUEST_METHOD
|
getMethod()
|
PATH_INFO
|
getPathInfo()
|
PATH_TRANSLATED
|
getPathTranslated()
|
SCRIPT_NAME
|
getServletPath()
|
DOCUMENT_ROOT
|
getServletContext().getRealPath(« / »)
|
QUERY_STRING
|
getQueryString()
|
REMOTE_HOST
|
getRemoteHost()
|
REMOTE_ADDR
|
getRemoteAddr()
|
AUTH_TYPE
|
getAuthType()
|
REMOTE_USER
|
getRemoteUser()
|
CONTENT_TYPE
|
getContentType()
|
CONTENT_LENGTH
|
getContentLength()
|
HTTP_ACCEPT
|
getHeader(« Accept » )
|
HTTP_USER_AGENT
|
getHeader(« User-Agent » )
|
HTTP_REFERER
|
getHeader(« Referer » )
|
3.2.4.Écrire la réponse
La réponse
à la requête se fait via l’instance de l’objet :
HttpServletResponse passée en paramètre des
méthodes doGet(), doPost() …
(Nous noterons l’instance de cet objet : « res »).
3.2.4.1.Type de contenu
La
première chose à faire est d’indiquer à la
servlet le type de données qu’elle va renvoyer. En effet
vous pouvez très bien retourner du html, une image générée
…
La
méthode : setContentType() vous permettra
d’effectuer cela. Elle prend en paramètre le type de
contenu. Voici quelques exemples d’utilisation de cette
méthode :
res.setContentType
(“text/html”) // page html
res.setContentType
(“text/xml”) // page xml
res.setContentType
(“image/jpeg”) // image jpeg
Il est
possible de renvoyer tout type de contenu en spécifiant
exactement le bon type mime.
3.2.4.2.Écriture
L’écriture
des données de type texte dans la réponse se fait par
l’objet : PrintWriter que l’on peut récupérer
par la méthode : getWriter().
PrintWriter out =
res.getWriter();
out.println(“<HTML>”);
out.println(“<BODY>”);
out.println(“Bonjour
le monde”);
out.println(“</BODY>”);
out.println(“</HTML>”);
out.close();
Si votre
réponse renvoie des données binaires, il est préférable
d’utiliser l’objet ServletOutputStream dont une
instance est retournée par la méthode :
getOutputStream()
Voici un
exemple pour retourner une image à partir d’une image
locale :
res.setContentType
(“image/gif”);
ServletOutputStream out =
res.getOutputStream();
FileInputStream
fis = new FileInputStream (new
File (“./logo.gif”));
while
(fis.available() > 0)
{
fis.read (buf,0,buf.length);
out.write(buf);
out.flush();
}
fis.close();
out.close();
|
|
 |