Looking for Computer Science  & Information Technology online courses ?
Check my new web site: https://www.yesik.it !

Cet article est une reprise de l'article Premiers pas avec les Servlets que j'avais précédemment publié sur http://wiki.esicom-st-malo.fr

Une Servlet est une application Java/JEE côté serveur qui s'exécute dans le contexte d'un container de Servlet.

Nous ne parlerons dans cet article que de Servlet Http. Et nous allons voir comment créer une Servlet HTTP et la déployer.

Objectifs A la fin de ce tutoriel, vous saurez:
  • Ecrire une Servlet pour répondre à une requête HTTP,
  • Créer une archive Web (fichier WAR),
  • Déployer une Servlet dans son container.
Prérequis
Moyens
  • Un container de Servlet (Tomcat, par ex.) ou un serveur d'application (JBoss AS, par ex).


Remarque:

Cet article est écrit en supposant que vous aller déployer votre Servlet sur le serveur d'application JBoss. Cependant, tout autre serveur d'application JEE, ou container de Servlet pourra aussi être utilisé. Seule la technique de déploiement devra être adaptée.

Principe de fonctionnement d'une Servlet

Une Servlet HTTP est juste une classe qui dérive de la classe javax.servlet.http.HttpServlet et qui implémente une ou plusieurs méthodes doXXX pour répondre à des requêtes HTTP (où XXX est le nom de la méthode HTTP à laquelle la méthode Java répond).

Piège:

Ne confondez pas la méthode HTTP (GET, POST, etc.) qui est envoyée par le client avec sa requête, et la méthode Java (doGET, doPOST, etc.) qui est implémentée dans la Servlet et qui sert à répondre à la requête!

Comme on le voit dans le diagramme de séquence ci-dessus, c'est le serveur d'application qui est chargé d'instancier la Servlet. Celui-ci n'attend pas nécessairement la première requête pour créer la Servlet.

Quand le serveur d'application reçoit une requête HTTP, il détermine à quelle Servlet cette requête est destinée, puis appelle la méthode service de cette dernière. Celle-ci décode la requête, et invoque la méthode doXXX appropriée. La réponse effectue le même trajet, mais en sens inverse, pour finalement arriver chez le client.

Note:

Il faut savoir qu'une même instance de Servlet peut servir plusieurs requêtes, même issues de clients différents!

Le code source de la Servlet

Commençons par donner le code source de la Servlet. Comme vous le voyez MyServlet est simplement une classe dérivée de javax.servlet.http.HttpServlet. Notre Servlet n'implémente que la méthode doGET: elle ne saura donc répondre qu'à une requête HTTP GET.

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 * Servlet implementation class for Servlet: MyServlet
 */
 public class MyServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, 
                             HttpServletResponse response)
	                     throws ServletException, IOException {
		response.setContentType("text/plain");
		response.getWriter().println("Hello World");
	}  	
}

Vous pouvez d'ores et déjà essayer de compiler. Néanmoins, pour cette tâche le compilateur Java a besoin des bibliothèques associées à votre serveur d'application (ou votre container de Servlet). Pour Tomcat ou JBoss (qui utilise Tomcat) il faut indiquer le chemin de la bibliothèque servlet-api.jar. En supposant que vous utilisiez JBoss et que la variable d'environnement JBOSS_HOME indique le répertoire racine de votre installation, la commande suivante devrait faire l'affaire:

sh$ javac -classpath "${JBOSS_HOME}/server/default/lib/servlet-api.jar" MyServlet.java

Mais compiler la servlet ne suffit pas. En fait, les spécifications de JEE imposent que le dossier qui contient une application Web ait une structure bien définie.

Note:

Dans le jargon JEE, une application Web est un composant déployable sur un serveur d'application (éventuellement sur un container de Servlet). Une application Web peut contenir une ou plusieurs Servlet, mais aussi des documents statiques (pages HTML, images GIF, JPEG, etc.) et bien d'autres choses encore!

Structure du dossier

Pour pouvoir être déployé, le dossier d'une application Web doit avoir la structure illustrée ci-contre.

Bien entendu, il est toujours possible de gérer ce dosser à la main en déplaçant ce fichier après chaque compilation:

sh$ cp -f MyServlet.class WebContent/WEB-INF/classes/

C'est non seulement fastidieux, mais c'est aussi source d'erreur: oublie de copie d'un fichier, ou copie dans le "mauvais" répertoire. Un moyen d'automatiser ces opérations est d'utiliser un buildfile Ant.

<?xml version="1.0" encoding="UTF-8" ?>
<project name="MyServlet" default="compile">
    <property name="project.name" value="mywebapp" />
    <property name="project.src.dir" value="src" />
    <property name="project.web.dir" value="WebContent" />
 
    <property name="JBOSS_HOME" value="../../jboss" />
    <path id="JBoss.libraryclasspath">
        <pathelement location="${JBOSS_HOME}/server/default/lib/servlet-api.jar"/>
    </path>
 
    <target name="init">
        <mkdir dir="${project.web.dir}" />
        <mkdir dir="${project.web.dir}/WEB-INF" />
        <mkdir dir="${project.web.dir}/WEB-INF/classes" />
    </target>
 
    <target name="clean">
        <delete dir="${project.web.dir}/WEB-INF/classes"/>
    </target>
 
    <target name="compile" depends="init">
        <javac srcdir="${project.src.dir}"
               destdir="${project.web.dir}/WEB-INF/classes">
            <classpath refid="JBoss.libraryclasspath" />
        </javac>
    </target>
</project>

Il s'agit d'un buildfile tout ce qu'il y a de plus classique: après avoir définit des propriétés et le chemin vers la bibliothèque servlet-api.jar nécessaire lors de la phase de compilation, on trouve trois tâches:

Remarque:

Vous remarquerez que la tâche de compilation va chercher les sources dans le sous-répertoire src.

Faire les choses au propre

Reprenons un peu la création de notre Servlet, mais cette fois en faisant les choses plus "proprement" et en utilisant Ant pour compiler:

sh$ mkdir PremiersPasServlet
sh$ cd PremiersPasServlet
sh$ mkdir src
sh$ cp /path/to/MyServlet.java src
sh$ cp /path/to/build.xml .


Il est maintenant possible d'invoquer Ant pour créer les autres dossiers et compiler notre Servlet:

sh$ ant

Si tout se passe bien, vous devriez vous retrouver avec l'arborescence ci-contre.

En cas d'erreur de compilation, pensez à vérifier que les chemins dans build.xml correspondent bien à ceux de votre installation.

Comme vous le constatez, le répertoire WebContent correspond quasiment à ce qui est nécessaire d'après les spécifications JEE. Il ne manque que le descripteur de déploiement web.xml.

Le descripteur de déploiement

Le fichier web.xml contient les informations nécessaires au serveur pour déployer une application Web.

Dans notre cas, ce fichier va simplement indiquer que notre application est constituée d'une Servlet, et préciser à quelle URL il faudra que le client se connecte pour y accéder:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" >
  <servlet>
    <servlet-name>myservlet</servlet-name>
    <servlet-class>MyServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>myservlet</servlet-name>
    <url-pattern>/theservlet</url-pattern>
  </servlet-mapping>
</web-app>

Piège:

N'oubliez pas que le fichier web.xml doit se trouver dans le répertoire WEB-INF! Sous Linux, vous pouvez vérifier que vous avez bien la bonne arborescence ainsi:

sh$ find . -print
.
./build.xml
./src
./src/MyServlet.java
./WebContent
./WebContent/WEB-INF
./WebContent/WEB-INF/classes
./WebContent/WEB-INF/classes/MyServlet.class
./WebContent/WEB-INF/web.xml

L'archive Web

C'est presque fini! Il ne nous reste plus qu'à construire l'archive web. Il ne s'agit de rien d'autre qu'un JAR qui contient un dossier dont l'arborescence respecte celle exposée plus haut - et dont l'extension est .war au lieu de .jar.

Vous vous en doutez, nous allons utiliser Ant pour construire ce fichier WAR. Nous allons tout d'abord ajouter une nouvelle propriété pour définir le nom de notre archive:

<property name="project.war.file" value="${project.name}.war" />

Puis une nouvelle tâche pour fabriquer l'archive:

<!-- ... -->
    <target name="war" depends="compile">
        <jar destfile="${project.war.file}" basedir="${project.web.dir}" />
    </target>
<!-- ... -->

enfin, nous pouvons aussi en profiter pour modifier la tâche clean pour supprimer l'archive au moment de "faire le ménage":

<!-- ... -->
    <target name="clean">
        <delete dir="${project.web.dir}/WEB-INF/classes"/>
        <delete file="${project.war.file}" />
    </target>
<!-- ... -->

Testons ces modifications:

sh$ ant war
Buildfile: build.xml

init:

compile:

war:
      [jar] Building jar: /private/tmp/PremiersPasServlet/mywebapp.war

BUILD SUCCESSFUL
Total time: 4 seconds
sh$ ls *.war
mywebapp.war

Déployer l'application

Il nous reste maintenant à déployer l'application. Selon le serveur d'application la procédure varie. Ici nous allons exposer comment faire pour JBoss/Tomcat.

JBoss permet le déploiement "à chaud". C'est à dire qu'il n'est pas nécessaire d'arrêter le serveur pour ajouter - ou supprimer - une application Web. La procédure est extrêmement simple, puisqu'il suffit de copier l'archive WAR dans le dossier de déploiement:

sh$ cp -f mywebapp.war ${JBOSS_HOME}/server/default/deploy/

Si vous avez lancé JBoss à partir d'un terminal, au bout de quelques secondes vous devriez voir un message qui vous signale le déploiement de votre application. Dans tous les cas, après quelques secondes votre application est prête à être testée.

Pour essayer votre Servlet, il vous suffit de vous connecter à l'URL http://localhost:8080/mywebapp/theservlet à partir de votre client HTTP préféré (navigateur ou autre).

Note:

Dans l'URL http://localhost:8080/mywebapp/theservlet:

  • localhost:8080 est l'hôte et le port sur lesquels écoutent le serveur d'application,
  • mywebapp est le nom de l'application web (le nom du fichier .war),
  • /theservlet est le chemin indiqué dans le descripteur de déploiement (élément url-pattern du fichier web.xml).

Ici pour illustrer, nous allons nous connecter avec curl:

sh$ curl -D - http://localhost:8080/mywebapp/theservlet
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Powered-By: Servlet 2.4; JBoss-4.2.1.GA (build: SVNTag=JBoss_4_2_1_GA  date=200707131605)/Tomcat-5.5
Content-Type: text/plain;charset=ISO-8859-1
Content-Length: 13
Date: Tue, 11 Dec 2007 14:47:28 GMT

Hello World

La connexion a échoué?

Si votre client renvoie un message d'erreur du style "La connexion a échoué" ou "Connection refused":

  • Vérifiez que vous avez bien lancé JBoss
  • Vérifiez que vous vous connectez sur le bon port!

Ajouter un fichier d'accueil

Nous l'avons dit, une application web ne se limite pas forcément à une seule Servlet. En particulier, il est possible d'ajouter à l'application des documents statiques. Juste pour illustrer ce point, nous allons rajouter un fichier index.html qui servira de page d'accueil à notre application et qui proposera un lien vers notre Servlet:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/2002/REC-xhtml1-20020801/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>Bienvenue sur Hello Servlet</title></head>
<body>
 <h1>Bienvenue sur Hello Servlet 1.0</h1>
 <p>cliquez ici pour tester <a href="theservlet">votre Servlet</a></p>
</body>
</html>

Comme tous les documents statiques, index.html doit se trouver dans le répertoire WebContent ou un de ses sous-répertoires (mais pas dans WEB-INF).

Remarque:

Si votre application possède un fichier d'accueil (welcome file), il est conseillé de le placer directement dans le répertoire WebContent: En effet, par défaut, quand un utilisateur se connecte à l'URL d'une application web sans indiquer de chemin, le serveur renvoie le fichier index.html (s'il est présent).

Concrètement, si l'utilisateur se connecte à l'URL http://localhost:8080/mywebapp/theservlet il accède directement à la Servlet, et s'il se connecte à http://localhost:8080/mywebapp il voit notre page d'accueil qui lui propose un lien vers la Servlet.

Pour tester il ne vous reste plus qu'à reconstruire le fichier .war et à re-déployer cette application sur votre serveur.