Transmission de données

Ce contenu est obsolète. Il peut contenir des informations intéressantes mais soyez prudent avec celles-ci.

Nous nous sommes jusqu'à présent contentés d'afficher une page web au contenu figé, comme nous l'avions fait via une simple page HTML écrite en dur en tout début de cours. Seulement cette fois, notre contenu est présent dans une page JSP à laquelle nous avons associé une servlet. Nous disposons ainsi de tout ce qui est nécessaire pour ajouter du dynamisme à notre projet. Il est donc grand temps d'apprendre à faire communiquer entre eux les différents éléments constituant notre application !

Données issues du serveur : les attributs

Transmettre des variables de la servlet à la JSP

Jusqu'à présent nous n'avons pas fait grand-chose avec notre requête HTTP, autrement dit avec notre objet HttpServletRequest : nous nous sommes contentés de le transmettre à la JSP. Pourtant, vous avez dû vous en apercevoir lorsque vous avez parcouru sa documentation, ce dernier contient énormément de méthodes !

Puisque notre requête HTTP passe maintenant au travers de la servlet avant d'être transmise à la vue, profitons-en pour y apporter quelques modifications ! Utilisons donc notre servlet pour mettre en place un semblant de dynamisme dans notre application : créons une chaîne de caractères depuis notre servlet, et transmettons-la à notre vue pour affichage.

1
2
3
4
5
public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException{
    String message = "Transmission de variables : OK !";
    request.setAttribute( "test", message );
    this.getServletContext().getRequestDispatcher( "/WEB-INF/test.jsp" ).forward( request, response );
}

Transmission d'une variable

Comme vous pouvez le constater, le principe est très simple et tient en une ligne (la ligne 3). Il suffit d'appeler la méthode setAttribute() de l'objet requête pour y enregistrer un attribut ! Cette méthode prend en paramètre le nom que l'on souhaite donner à l'attribut suivi de l'objet lui-même.

Ici, l'attribut que j'ai créé est une simple chaîne de caractères - un objet de type String - que j'ai choisi de nommer test lors de son enregistrement dans la requête.

Ne confondez pas le nom que vous donnez à votre objet au sein du code et le nom que vous donnez à l'attribut au sein de la requête. Ici mon objet se nomme message mais j'ai nommé par la suite test l'attribut qui contient cet objet dans la requête. Côté vue, c'est par ce nom d'attribut que vous pourrez accéder à votre objet !

C'est tout ce qu'il est nécessaire de faire côté servlet. Regardons maintenant comment récupérer et afficher l'objet côté vue :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<%@ page pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Test</title>
    </head>
    <body>
        <p>Ceci est une page générée depuis une JSP.</p>
        <p>
            <% 
            String attribut = (String) request.getAttribute("test");
            out.println( attribut );
            %>
        </p>
    </body>
</html>

/WEB-INF/test.jsp

Ne paniquez pas, vous ne connaissez pas cette notation (lignes 11 à 14) et c'est bien normal puisque je ne vous l'ai pas encore présentée… :-°

Voici donc une première information concernant la technologie JSP : elle permet d'inclure du code Java dans une page en entourant ce code des balises <% et %> . Ce sont des marqueurs qui délimitent les portions contenant du code Java du reste de la page, contenant ici simplement des balises HTML et du texte. À l'intérieur, tout se passe comme si on écrivait du code directement dans une servlet : on fait appel à la méthode println() de l'objet PrintWriter out pour afficher du contenu. La seule différence réside dans le fait que depuis une JSP, il n'est plus nécessaire de spécifier le content-type de la réponse HTTP ni d'y récupérer l'objet PrintWriter, comme nous l'avions fait deux chapitres auparavant depuis notre servlet. Ceci est rendu possible grâce à l'existence d'objets implicites, sur lesquels nous allons revenir très bientôt !

En ce qui concerne la récupération de l'attribut depuis la requête, je pense que vous êtes assez grands pour faire vous-mêmes l'analogie avec sa création : tout comme il suffit d'appeler setAttribute() pour créer un attribut dans une requête depuis une servlet, il suffit d'appeler la méthode getAttribute() pour en récupérer un depuis une JSP ! Ici, je récupère bien mon objet nommé test .

Nous avons ici transmis un simple objet String, mais il est possible de transmettre n'importe quel objet, comme un entier ou une liste par exemple. Remarquez à ce sujet la nécessité de convertir (cast) l'objet récupéré dans la JSP au type souhaité, la méthode getAttribute() renvoyant un objet global de type Object.

Alors c'est ça une JSP ? Une autre page dans laquelle on remet une couche de Java ?

Non, bien sûr que non ! Écrire du Java dans une JSP n'a aucun sens : l'intérêt même de ces pages est de s'affranchir du langage Java ! À ce compte-là, autant n'utiliser qu'une servlet et ne pas mettre en place de JSP…

Cependant comme vous pouvez le voir, cela fonctionne très bien ainsi : ça confirme ce que je vous disais dans la première partie de ce cours. En Java EE, rien n'impose au développeur de bien travailler, et il est possible de coder n'importe comment sans que cela n'impacte le fonctionnement de l'application. Voilà donc un premier exemple destiné à vous faire comprendre dès maintenant que mettre du code Java dans une page JSP, c'est mal.

Pour ce qui est de notre exemple, ne vous y méprenez pas : si je vous fais utiliser du code Java ici, c'est uniquement parce que nous n'avons pas encore découvert le langage JSP. D'ailleurs, autant vous prévenir tout de suite : à partir du chapitre suivant, nous allons tout mettre en œuvre pour ne plus jamais écrire de Java directement dans une JSP !

Données issues du client : les paramètres

Qu'est-ce qu'un paramètre de requête ?

Si vous êtes assidus, vous devez vous souvenir de la description que je vous ai faite de la méthode GET du protocole HTTP : elle permet au client de transmettre des données au serveur en les incluant directement dans l'URL, dans ce qui s'appelle les paramètres ou query strings en anglais. Eh bien c'est cela que nous allons apprendre à manipuler ici : nous allons rendre notre projet interactif, en autorisant le client à transmettre des informations au serveur.

La forme de l'URL

Les paramètres sont transmis au serveur directement via l'URL. Voici des exemples des différentes formes qu'une URL peut prendre :

1
2
3
4
5
6
7
8
<!-- URL sans paramètres -->
/page.jsp

<!-- URL avec un paramètre nommé 'cat' et ayant pour valeur 'java' -->
/page.jsp?cat=java

<!-- URL avec deux paramètres nommés 'lang' et 'admin', et ayant pour valeur respectivement 'fr' et 'true' -->
/page.jsp?lang=fr&admin=true

Il y a peu de choses à retenir :

  • le premier paramètre est séparé du reste de l'URL par le caractère « ? » ;
  • les paramètres sont séparés entre eux par le caractère « & » ;
  • une valeur est attribuée à chaque paramètre via l'opérateur « = ».

Il n'existe pas d'autre moyen de déclarer des paramètres dans une requête GET, ceux-ci doivent impérativement apparaître en clair dans l'URL demandée. À ce propos, souvenez-vous de ce dont je vous avais avertis lors de la présentation de cette méthode GET : la taille d'une URL étant limitée, la taille des données qu'il est ainsi possible d'envoyer est limitée également !

À vrai dire, la norme ne spécifie pas de limite à proprement parler, mais les navigateurs imposent d'eux-mêmes une limite : par exemple, la longueur maximale d'une URL est de 2 083 caractères dans Internet Explorer 8. Au-delà de ça, autrement dit si votre URL est si longue qu'elle contient plus de 2 000 caractères, ce navigateur ne saura pas gérer cette URL ! Vous disposez donc d'une certaine marge de manœuvre ; pour des chaînes de caractères courtes comme dans notre exemple cette limite ne vous gêne absolument pas. Mais d'une manière générale et même si les navigateurs récents savent gérer des URL bien plus longues, lorsque vous avez beaucoup de contenu à transmettre ou que vous ne connaissez pas à l'avance la taille des données qui vont être envoyées par le client, préférez la méthode POST.

J'en profite enfin pour vous reparler des recommandations d'usage HTTP : lorsque vous envoyez des données au serveur et qu'elles vont avoir un impact sur la ressource demandée, il est, là encore, préférable de passer par la méthode POST du protocole, plutôt que par la méthode GET.

Que signifie "avoir un impact sur la ressource" ?

Eh bien cela veut dire "entraîner une modification sur la ressource", et en fin de compte tout dépend de ce que vous faites de ces données dans votre code. Prenons un exemple concret pour bien visualiser. Imaginons une application proposant une page compte.jsp qui autoriserait des actions diverses sur le compte en banque de l'utilisateur. Ces actions ne se dérouleraient bien évidemment pas comme cela dans une vraie application bancaire, mais c'est simplement pour que l'exemple soit parlant.

  • Si le code attend un paramètre précisant le mois pour lequel l'utilisateur souhaite afficher la liste des entrées et sorties d'argent de son compte, par exemple compte.jsp?mois=avril, alors cela n'aura pas d'impact sur la ressource. En effet, nous pouvons bien renvoyer 10 fois la requête au serveur, notre code ne fera que réafficher les mêmes données à l'utilisateur sans les modifier.
  • Si par contre le code attend des paramètres précisant des informations nécessaires en vue de réaliser un transfert d'argent, par exemple compte.jsp?montant=100&destinataire=01K87B612, alors cela aura clairement un impact sur la ressource : en effet, si nous renvoyons 10 fois une telle requête, notre code va effectuer 10 fois le transfert !

Ainsi, si nous suivons les recommandations d'usage, nous pouvons utiliser une requête GET pour le premier cas, et devons utiliser une requête POST pour le second. Nous reviendrons sur les avantages de la méthode POST lorsque nous aborderons les formulaires, dans une des parties suivantes de ce cours.

N'importe quel client peut-il envoyer des paramètres à une application ?

Oui, effectivement. Par exemple, lorsque vous naviguez sur Zeste de Savoir, rien ne vous empêche de rajouter des paramètres tout droit issus de votre imagination lors de l'appel de la page d'accueil du site : par exemple, www.zestedesavoir.com/?mascotte=clem. Le site n'en fera rien, car la page n'en tient pas compte, mais le serveur les recevra bien. C'est en partie pour cela, mais nous aurons tout le loisir d'y revenir par la suite, qu'il est impératif de bien vérifier le contenu des paramètres envoyés au serveur avant de les utiliser.

Récupération des paramètres par le serveur

Modifions notre exemple afin d'y inclure la gestion d'un paramètre nommé auteur :

1
2
3
4
5
6
7
public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException{
    String paramAuteur = request.getParameter( "auteur" );
    String message = "Transmission de variables : OK ! " + paramAuteur;
    request.setAttribute( "test", message );

    this.getServletContext().getRequestDispatcher( "/WEB-INF/test.jsp" ).forward( request, response );
}

Servlet

La seule ligne nécessaire pour cela est la ligne 2 : il suffit de faire appel à la méthode getParameter() de l'objet requête, en lui passant comme argument le nom du paramètre que l'on souhaite récupérer. La méthode retournant directement le contenu du paramètre, je l'ai ici inséré dans une String que j'ai nommée paramAuteur.

Pour vous montrer que notre servlet récupère bien les données envoyées par le client, j'ai ajouté le contenu de cette String au message que je transmets ensuite à la JSP pour affichage. Si vous appelez à nouveau votre servlet depuis votre navigateur, rien ne va changer. Mais si cette fois vous l'appelez en ajoutant un paramètre nommé auteur à l'URL, par exemple :

1
http://localhost:8080/test/toto?auteur=Coyote

Alors vous observerez que le message affiché dans le navigateur contient bien la valeur du paramètre précisé dans l'URL :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Test</title>
    </head>
    <body>
        <p>Ceci est une page générée depuis une JSP.</p>
        <p>
            Transmission de variables : OK ! Coyote
        </p>
    </body>
</html>

Contenu de la page finale

Vous avez donc ici la preuve que votre paramètre a bien été récupéré par la servlet. Comprenez également que lorsque vous envoyez un paramètre, il reste présent dans la requête HTTP durant tout son cheminement. Par exemple, nous pouvons très bien y accéder depuis notre page JSP sans passer par la servlet, de la manière suivante :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<%@ page pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Test</title>
    </head>
    <body>
        <p>Ceci est une page générée depuis une JSP.</p>
        <p>
            <% 
            String attribut = (String) request.getAttribute("test");
            out.println( attribut );

            String parametre = request.getParameter( "auteur" );
            out.println( parametre );
            %>
        </p>
    </body>
</html>

/WEB-INF/test.jsp

En procédant ainsi, lorsque nous appelons l'URL en y précisant un paramètre nommé auteur, nous obtenons bien le résultat escompté : notre JSP affiche une seconde fois "Coyote", cette fois en récupérant directement la valeur du paramètre depuis la requête HTTP.

Si vous ne précisez pas de paramètre auteur dans l'URL, alors la méthode getParameter() renverra null en lieu et place du contenu attendu.

Note : il est très imprudent de procéder à l'utilisation ou à l'affichage d'un paramètre transmis par le client sans en contrôler et éventuellement sécuriser son contenu auparavant. Ici il s'agit d'un simple exemple, nous ne nous préoccupons pas encore des problèmes potentiels. Mais c'est une bonne pratique de toujours contrôler ce qu'on affiche au client. Nous y reviendrons à plusieurs reprises dans la suite du cours dans des cas plus concrets, et vous comprendrez alors mieux de quoi il retourne.

Nous allons nous arrêter là pour le moment. L'utilisation la plus courante des paramètres dans une application web est la récupération de données envoyées par le client via des formulaires, mais nous ne sommes pas encore prêts pour cela. Avant de passer à la suite, une dernière petite précision s'impose.

Quelle est la différence entre ces paramètres et les attributs que nous avons découverts en début de chapitre ?

Il ne faut pas faire de confusion ici :

  • les paramètres de requête sont un concept appartenant au protocole HTTP. Ils sont envoyés par le client au serveur directement au sein de l'URL, et donc sous forme de chaînes de caractères. Il n'est pas possible de forger des paramètres dans l'objet HttpServletRequest, il est uniquement possible d'y accéder en lecture. Ce concept n'étant absolument pas spécifique à la plate-forme Java EE mais commun à toutes les technologies web, il ne peut pas être "objectifié". C'est la raison pour laquelle la méthode getParameter() retourne quoi qu'il arrive un objet de type String, et il n'est pas possible d'ajouter une quelconque logique supplémentaire à un tel objet.
  • les attributs de requête sont un concept appartenant au conteneur Java, et sont donc créés côté serveur : c'est au sein du code de l'application que l'on procède à leur initialisation, et qu'on les insère dans la version "objectifiée" de la requête, à savoir l'objet HttpServletRequest. Contrairement aux paramètres, ils ne sont pas présents directement dans la requête HTTP mais uniquement dans l'objet Java qui l'enveloppe, et peuvent contenir n'importe quel type de données. Ils sont utilisés pour permettre à une servlet de communiquer avec d'autres servlets ou pages JSP.

En résumé, les paramètres de requête sont propres au protocole HTTP et font partie intégrante de l'URL d'une requête, alors que les attributs sont des objets purement Java créés et gérés par le biais du conteneur.


  • Un attribut de requête est en réalité un objet stocké dans l'objet HttpServletRequest, et peut contenir n'importe quel type de données.
  • Les attributs de requête sont utilisés pour permettre à une servlet de transmettre des données à d'autres servlets ou à des pages JSP.
  • Un paramètre de requête est une chaîne de caractères placée par le client à la fin de l'URL de la requête HTTP.
  • Les paramètres de requête sont utilisés pour permettre à un client de transmettre des données au serveur.