Академический Документы
Профессиональный Документы
Культура Документы
Tutoriel J2EE : les Servlets Version HTML Version HTML/ZIP Version PDF
Prface Public vis Connaissances requises Objectifs de cet ouvrage 1 - Prsentation 1.1 - L'origine des Servlets 1.2 - Les technologies utilises 1.3 - La place des Servlets 1.3.1 - A quoi a sert ? 1.3.2 - Public vis 1.3.3 - Les possibilits 1.4 - Quels sont les acteurs sur le march ? 1.5 - Les solutions de substitution 2 - Introduction au dveloppement 2.1 - Les bases des applications Web ct serveur 2.1.1 - Les applications client-serveur 2.1.2 - Le protocole HTTP 2.2 - La mise en place du serveur 2.2.1 - Les diffrents types de solutions 2.2.2 - Le choix de la solution 2.2.3 - L'installation de Tomcat et Apache 2.2.3.1 - L'installation de l'environnement de dveloppement Java 2.2.3.2 - L'installation de Tomcat 2.2.3.3 - Installation et configuration de Apache 2.2.3.4 - Configuration de mod_jserv 2.2.3.5 - La configuration de mod_jk 2.3 - Ecrire sa premire Servlet 2.4 - Les autres modes de programmation 2.4.1 - SSI 2.4.2 - JSP 2.4.3 - La forme 2.4.4 - En coulisses 2.5 - Les outils pour dvelopper 3 - Fonctionnement interne 3.1 - Le modle de fonctionnement 3.2 - Le cycle de vie 3.2.1 - Le chargement 3.2.2 - L'excution 3.2.3 - La destruction 3.2.4 - Les contextes 3.2.4.1 - Dfinition d'un contexte 3.2.4.2 - Configuration avec Tomcat
-2Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
3.2.4.3 - La configuration d'un contexte 3.2.4.4 - Les diffrentes choses savoir propos des contextes 4 - Les servlets HTTP 4.1 - La gestion des requtes 4.1.1 - Les informations propos du serveur 4.1.2 - Les informations propos du client 4.1.3 - Les informations sur la requte 4.2 - La rponse 4.2.1 - Les en-ttes HTTP 4.2.2 - Envoyer les donnes 4.2.3 - Persistance de la connexion 4.2.4 - La production de pages web crites en HTML 4.2.5 - La gnration de contenu multimdia 4.2.6 - La gnration d'images 5 - Le mot de la fin
http://java.developpez.com/cours/servlets/
Ce projet tant effectu dans le cadre de mes tudes au dpartement informatique de l'IUT de Montpellier, je m'adresse avant tout ses tudiants. En m'adressant ces tudiants, je touche, plus gnralement, un public d'tudiants en informatique dans leur premier cycle universitaire.
Connaissances requises
Malgr les efforts que je fournirai pour tre le plus clair et didactique possible, il est ncessaire pour le lecteur de possder les connaissances de base en ce qui concerne l'informatique, et plus prcisemment le langage de programmation Java, les concepts lis aux rseaux et plus particulirement les protocoles les plus courants comme HTTP (bien que j'effectuerais un rappel lorsque nous entrerons dans le vif du sujet). Tout ce qui sort du cadre de la technologie des Servlets, c'est dire qui n'a pas de rpercutions sur le comportement des Servlets en particulier, ne sera pas expliqu. Par exemple, je ne dcrirais pas la syntaxe utilise dans le code source qui sera fourni en tant qu'exemple plusieurs reprises.
-4Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
relatives ces sujets, de cette manire le lecteur pourra consulter une documentation spcifique de qualit bien meilleure que celle que j'aurais pu fournir en quelques pages.
http://java.developpez.com/cours/servlets/
-6Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
En pratique, les Servlets permettent donc exclusivement le dveloppement d'applications Web ct serveur., ceci de manire pouvoir fournir un contenu dynamique aux visiteurs de sites Web.
Depuis leur cration en 1996, de plus en plus d'acteurs majeurs de l'industrie de l'informatique ont propos une offre autour des Servlets. Tout d'abord en ce qui concerne les serveurs d'applications. Ces solutions sont trs fortement lies tous les domaines d'activit de l'entreprise. De nombreux composants "mtiers" sont utiliss (comme les EJB qui sont les Enterprise Java Beans), et des critres comme la fiabilit, le support technique et l'adquation avec les contraintes professionnelles de l'entreprise sont primordiaux. Il est donc comprhensible que d'importants fournisseurs d'applications aient investi ce secteur. Ces fournisseurs sont IBM (avec WebSphere), BEA (avec WebLogic), Oracle (avec Oracle Application Server) et iPlanet (avec iPlanet Application Server). Ces serveurs utilisent des moteurs de Servlets et des serveurs Web parfois indpendants. Par exemple IBM a dvelopp un serveur Web pour WebSphere qui se base sur le serveur Web Apache. Ensuite viennent les moteurs de Servlets, qui ne fonctionnent pas tous suivant le mme modle. Ce sont des applications qui implmentent toutes une version de la norme de l'API des Servlets, ils ne se diffrencient donc pas selon leurs fonctionnalits mais selon leurs performances. Les principaux moteurs de Servlets sont Tomcat (de la fondation Apache), Resin (de Caucho), JServ (de la fondation Apache galement), Allaire avec JRun. Enfin ces moteurs de Servlets sont souvent rattachs des serveurs Web (car c'est un serveur Web que sont destins les requtes provenant d'un navigateur dans de nombreux cas). tant donn qu'un site Web ne se base pas exclusivement sur les Servlets, les serveurs Web les plus utiliss pour fournir d'autres services sont en gnral choisis. Ces serveurs sont Apache (de la fondation Apache), iPlanet Web Server (de iPlanet) et IIS (de Microsoft). D'autres entreprises trs prsentes dans le secteur du dveloppement traditionnel fournissent des outils aux dveloppeurs dsirant obtenir une forte intgration avec leur serveur supportant les Servlets. Je pense par exemple Borland avec JBuilder, Macromedia UltraDev, et PowerJ de Sybase. Le reste des outils est dvelopp par les acteurs cits ci-dessus (Oracle avec JDeveloper, IBM avec Visual Age, Allaire avec JRun Studio). On ne peut que constater l'absence de Sun et de Microsoft quant aux outils permettant le dveloppement et le dploiement de Servlets. En ce qui concerne Sun, ce n'est pas tout fait vrai. En effet, ils fournissent un moteur de Servlets intgr un serveur Web nomm Java Web Server mais il constitue plus une solution pionnire qui a permis de disposer d'une premire plate-forme que d'une solution destine tre utilise en production. Ils proposent galement un outil de dveloppement appel Fort (anciennement Net Beans) qui, dans sa version entreprise, supporte les Servlets. Cet outil n'est pas vritablement utilis cause de sa lourdeur mais fut quand mme le premier outil RAD permettant le dveloppement de Servlets. Ils ne proposent donc ces outils que dans un but d'introduction aux concepts qu'ils proposent, ils ont par ailleurs fort faire normaliser l'API des Servlets tout en dveloppant son implmentation et ses fonctionnalits. Quant Microsoft, il suffit de songer leur mode de diffusion pour comprendre leur position. Les produits de Microsoft sont diffuss en partie car ils constituent un standard impos par le caractre propritaire de leurs applications. Ils fournissent des applications en troite relation avec leur systme : on choisit le systme de Microsoft car on ne peut se passer de leurs applications et vice-versa. Avec Java, on peut disposer d'une plate-forme pouvant apporter des solutions globales (comme les serveurs d'applications) et ceci de manire portable : l'informaticien et l'utilisateur sont indpendants de l'architecture matrielle et logicielle. On peut donc trs bien choisir d'autres produits que ceux de Microsoft. Afin de rsister la dferlante Java, Microsoft a donc annonc le dveloppement d'une
-8Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
plate-forme similaire : la plate-forme .NET. C'est un ensemble d'outils pour le dveloppement, le dploiement et l'utilisation d'applications distribues, qui met en valeur l'utilisation des rseaux (locaux ou Internet). Cette solution reprend de nombreuses caractristiques de Java comme le langage C# dont la syntaxe est tonnamment similaire celle de Java, la prsence d'une machine virtuelle qui interprte un langage intermdiaire, le caractre distribu des applications (un utilisateur peut utiliser une application distante) et d'autres encore. On peut donc voir la plate-forme .NET comme un concurrent la plate-forme J2EE1.4. Bien entendu cette situation n'est pas fige et elle sera probablement amene changer au fur et mesure de l'arrive des nouveaux acteurs et des dparts des anciens, qui seront peut tre attirs par d'autres plate-formes.
Je ne compare pas ces possibilits aux Servlets pour l'instant car je ne vous ai pas donn assez d'lments de rflexion, mais sachez que cela sera fait ultrieurement. Je ferai parfois, et tout au long de cet ouvrage, quelques comparaisons ponctuelles sur des points prcis entre les Servlets et certaines des solutions sus-cites. Sachez seulement pour l'instant que toutes ces technologies ne sont utilisables que par l'intermdiaire du protocole HTTP, ce qui n'est pas le cas des Servlets, mme si c'est cet aspect que je dvelopperai en majorit.
http://java.developpez.com/cours/servlets/
2 - Introduction au dveloppement
Maintenant que les prsentations sont faites, je vous invite manipuler les Servlets. Cette introduction au dveloppement des Servlets vous donnera les connaissances de base sur les technologies constituant les fondements sur lesquels reposent les Servlets (comme le protocole HTTP). Elle dcrira en dtail l'installation du moteur de Servlets Tomcat coupl au serveur Apache aprs avoir fait le tour des solutions et justifi mon choix et vous expliquera prcisemment sous quelle forme se prsente une Servlet, comment et avec quels outils les dvelopper.
2.1 - Les bases des applications Web ct serveur 2.1.1 - Les applications client-serveur
Le fonctionnement d'une application client-serveur peut tre dcrit de la manire suivante. Un programme s'excutant sur une machine logique proposant un support des connexions vers d'autres ordinateurs au travers d'un rseau offre ses services. Sur une autre machine logique , proposant elle aussi un support des connexions vers d'autres ordinateurs au travers d'un rseau, s'excute un programme qui met des requtes vers des machines faisant office de serveur, afin d'utiliser les services proposs.
Un programme serveur peut grer, en gnral, plusieurs requtes la fois provenant de clients diffrents ou identiques. Un programme client peut, en gnral, utiliser plusieurs connexions vers des serveurs diffrents ou identiques en mme temps. Ces deux machines logiques (car le programme client peut fonctionner sur la mme machine physique que le programme serveur) utilisent un ensemble de protocoles pour communiquer entre elles. Ces protocoles sont un ensemble de rgles respecter pour pouvoir communiquer correctement selon le but recherch (transmission d'informations confidentielles, transmission rapide d'informations peu importantes etc.). Ces protocoles se placent divers niveaux de la couche du modle OSI qui dfinit l'architecture logique du support des communications au travers d'un rseau sur la plupart des machines. Ces couches vont des plus abstraites et orientes "applications" en haut aux plus concrtes et orientes "implmentation physique" en bas. C'est ainsi que les couches les plus basses du modle OSI permettent de grer toutes les
- 10 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
communications au travers d'un rseau, alors que ce sont les couches les plus hautes qui fournissent des diffrences notables au programmeur et l'utilisateur d'applications de haut niveau. Ces couches les plus hautes dfinissent donc des protocoles spcifiques chaque type d'applications que l'on peut trouver sur un rseau : transfert de fichiers (FTP), envoi et rception de courriers lectroniques (SMTP), consultation de sites Web (HTTP) etc.. Le client et le serveur dialoguent donc l'aide des mmes protocoles, mais d'un ct le serveur fournit les services, de l'autre le client en bnficie. Un serveur, grce la sparation des protocoles orients "application" peut fournir le type de service qu'il veut. Il n'est pas oblig de fournir tous les services existants (simplement la consultation de sites Web par exemple), mais il peut le faire. Un client peut en mme temps faire office de serveur. Les communications entre ordinateurs ne sont pas unidirectionnelles.
o adresse_ip_serveur est l'adresse ip du serveur web cible (je pense que vous le saviez dej ;-)). Il ne vous reste plus qu' entrer la requte l'invite qui vous est propose. La partie principale de la requte en ce qui concerne le client est la commande, place sur la premire
http://java.developpez.com/cours/servlets/
ligne de la reqete. Elle dtermine l'action effectuer. Ces commandes sont parfois accompagnes d'arguments qui prcisent l'objet sur lequel porte la commande. L'action la plus courament utilise est la rcupration d'un document en utilisant la commande GET ou POST (GET et POSt sont deux mthodes HTTP diffrentes pour effectuer la mme action). Cette commande prend comme argument la ressource rcuprer, c'est dire le chemin vers le fichier rcuprer (ce n'est pas un chemin absolu, mais relatif la racine du serveur). Par exemple :
GET /index.html HTTP/1.0
permet de rcuprer le fichier index.html qui est situ la racine du rpertoire d'installation du serveur en utilisant la version 1.0 de HTTP. De manire gnrale, les clients placent une entte dans leur requte, la suite de la commande, dcrivant par exemple qui ils sont (le nom et le numro de version pour un navigateur par exemple) et ce qu'ils peuvent accepter (des images, du texte au format HTML pour le mme type de logiciel par exemple). Certaines enttes sont optionelles et d'autres obligatoires, cela dpend de la requte et de la configuration du serveur Web qui la requte est transmise. Vous devrez par exemple ajouter une entte spcifiant un identifiant et un mot de passe si le serveur Web est configur de telle manire qu'il n'accepte pas les personnes inconnues. Par exemple :
GET / index.html HTTP/1.0 Accept: text/html, image/gif User-Agent: Mozilla/4.0 (compatible; MSIE 4.0; Linux X11 2.2.17)
nous indique que le client l'origine de la requte est le navigateur netscape (bas sur Mozilla, d'o l'apparition de ce nom) tournant sous Linux et qu'il accepte le texte au format HTML et les images au format GIF. La requte d'un client Web doit tre suivie de deux sauts la ligne pour tre prise en compte. Une fois la requte du client analyse (entte et corps de la requte), le serveur dispose de tous les lments pour produire une rponse. Le premier lment de la rponse est appel l'tat qui spcifie la version du protocole HTTP utilise, un code d'tat et une courte description de cet tat. L'entte de la rponse vient aprs cette ligne d'tat. Celle ci dcrit par exemple le type de donnes qui est envoy (texte au format ASCII, au format HTML, images au format gif, etc.). Le serveur peut ensuite envoyer les donnes au navigateur qui les analysera correctement en se conformant aux directives donnes par l'entte de la rponse du serveur. Par exemple :
HTTP/1.0 200 OK Server: Apache/1.3.14 mod_php4 Content-type: text/html
nous indique que la requte peut tre traite avec succs ( code d'tat 200 et description du code "OK" ) et qu'elle est traite par le serveur Apache dans sa version 1.3.14. On sait galement que la rponse contient exclusivement du texte au format HTML. Une fois cette entte envoye au client, le serveur peut dbuter l'envoi des donnes (le fichier
- 12 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
index.html si on se base sur la requte en exemple au dessus) en sparant l'entte et les donnes de deux lignes vides. Ces deux lignes vides sont indispensables indispensables. Je le rpte, aprs l'envoi des donnes au client, la connexion est interrompue, mme si le client est susceptible d'mettre une requte pour accder une ressource sur ce mme serveur immdiatement aprs. On dit que le protocole HTTP n'est pas orient session : il n'y a aucun moyen d'identifier un utilisateur au cours d'une srie de connexion un site Web. Or il est frquent que des utilisateurs effectuent une srie d'actions logiques destines atteindre un but bien prcis (acheter un produit sur un site marchand par exemple). Il est donc problmatique d'identifier correctement cette suite logique avec les seuls outils mis disposition par le protocole HTTP. Certains outils des Servlets que nous verrons dans le chapitre consacr au suivi de session sont l pour corriger ce manque.
Les moteurs de Servlets indpendants constituent une partie intgrante du serveur Web. Pour qu'une telle chose soit possible, il faut en principe que le serveur Web soit dvelopp en Java. Un exemple de ce type de serveurs est le Java Web Server, ou encore Tomcat (dont nous analyserons la configuration en dtail ultrieurement). Les moteurs de Servlets embarqus sont une combinaison d'un ajout un serveur Web et d'une implmentation de l'API Servlet. L'ajout (le plugin) au serveur Web permet d'aiguiller les requtes venant des clients et qui concernent des Servlets vers une machine virtuelle contenue dans le processus du serveur Web. Cette machine virtuelle est excute dans un thread spar ce qui implique le fonctionnement du serveur Web en multi-threads, ce qui n'est pas le cas de tous les serveurs Web (par exemple Apache sous Unix). Cette configuration apporte de bonnes performances, car les changements de contexte sont moins coteux, mais est limite en possibilit d'extensions (un serveur supportant un trs grand nombre de requtes au mme moment aura du mal pouvoir rpondre ces dernires). Les moteurs de Servlets externes sont une combinaison entre un plugin "greff" au serveur et une machine virtuelle tournant l'extrieur de celui-ci. Afin de communiquer entre eux, le plugin et le processus associ la machine virtuelle utilisent un mcanisme de communication inter-processus tel que les sockets TCP/IP. Si une requte passe au serveur Web concerne les Servlets, celui-ci passe
http://java.developpez.com/cours/servlets/
la requte au moteur de Servlets en utilisant le mcanisme sus-cit. Un des inconvnients de cette mthode est la diminution des performances. Par contre, ce type de serveur est en gnral plus stable (un arrt du serveur Web n'agit pas sur le moteur de Servlets et vice-versa) et plus extensible. De plus, tant donn que la machine virtuelle est extrieure au serveur Web, elle peut tourner sur n'importe quelle machine, ce qui vous permet de faire tourner le serveur Web sur une machine diffrente de celle sur laquelle est lanc le moteur de Servlets. Vous pouvez galement mettre en place plusieurs machines virtuelles pour un mme serveur Web2.2. En bref, la souplesse que l'on gagne peut tre intressante de nombreux points. En gnral, les personnes dsirant fournir un support pour les Servlets sur leur serveur fournissent dj un support pour d'autres technologies de dveloppement Web ct serveur, ou proposent tout simplement l'hbergement de pages statiques. Il est clair qu'un moteur de Servlets, mme s'il peut faire office de serveur Web dans le cas o il peut tourner en mode indpendant (comme pour Tomcat ou le Java Web Server), est beaucoup moins performant que les produits spcialiss lorsqu'il faut fournir un contenu diffrent des Servlets (pages statiques, fichiers, etc.). On comprend donc facilement qu'il vaut mieux choisir un moteur de Servlets "greffable" sur un serveur Web existant, afin de rester performant en ce qui concerne le contenu statique (c'est le serveur Web qui le gre) et le contenu dynamique faisant appel des Servlets (c'est le moteur de Servlets qui le gre). Cela nous laisse donc le choix entre la solution un et deux (embarqus ou externes) Bien sur, il est tout fait possible de travailler avec des moteurs de Servlets indpendants des fins de dveloppement, je les dconseille simplement pour de la production. Venons-en aux serveurs d'applications. J'ai dit prcdemment qu'ils taient souvent un assemblage entre un serveur Web existant, un moteur de Servlets existant et des outils orients "mtier" en plus, comme l'incorporation des EJBs et d'autres outils spcifique une activit industrielle (gestion des transactions, relation client, etc.). ce sont des outils trs pointus, qui cotent souvent trs chers, et qui requirent de multiples comptences. Leur utilisation et leur configuration est similaire aux solution plus classiques, avec souvent des outils de configuration plus simples utiliser pour les taches courantes, mais en ce qui concerne le dveloppement strict de Servlets, ils n'apportent quasiment rien ( part des optimisations des performances ou de la fiabilit dans des environnements bien prcis, souvent des gros systmes comme les S/390). On voit trs bien que les aspects intressants de ces solutions sortent du cadre de mes comptences et de cet ouvrage, et c'est pour cette raison que je les car terais de mon choix. Pour conclure propos de ces solutions, elles sont souvent moins souples utiliser que des applications plus classiques en raison de leur complexit et de leur course l'utilisation facile. Les problmes rapports sur les listes de diffusion ayant trait la configuration de moteurs de Servlets concernent la plupart du temps ce type de serveurs. Il apparat que le type de serveur runissant le plus d'avantages est le moteur de Servlets externe reli un serveur Web performant via un plugin. En effet, comme on a pu le voir, c'est une solution fiable, souple et assez performante. De plus, moyennant quelques efforts de configuration, ce type de serveur peut tout fait inclure un nombre trs important de fonctionnalits comme les EJBs, ce qui leur donne accs aux composants mtiers si chers aux serveurs d'applications, ou le support de plusieurs machines virtuelles. Maintenant que nous avons choisi (mme si je vous ai aid) le type de serveur utiliser, choisissons lequel utiliser dans cette catgorie.
contenu autre que des Servlets, de deux critres : la version de l'API Servlet supporte et la version des JSP supporte. En effet, bien que les comparaisons de performances entre solutions soient abondantes, elles ne signifient rien si elles ne concernent pas directement l'application que vous voulez faire fonctionner. Plus la version de l'API supporte est rcente, plus vous pourrez bnficier de fonctionnalits utiles (par exemple la version 2.0 de l'API des Servlets ne supporte pas le RequestDispatcher). Le raisonnement est similaire en ce qui concerne les JSPs. Afin de bnficier d'une vision claire de ces deux critres, je vous invite consulter l'URL suivant : http://java.sun.com/products/servlet/industry.html. Ici, le systme d'exploitation choisit n'entre pas en compte pour le choix du moteur de Servlets car, tant donn que ce type de serveur est (en gnral) programm entirement en Java, tout systme d'exploitation disposant d'une implmentation de la machine virtuelle Java est cens fonctionner. Cependant, tant donn que nous avons choisis de coupler ce moteur de Servlets un serveur Web, nous devrons prter attention aux serveurs Web supports, afin que nous puissions utiliser ce couple avec le systme d'exploitation de notre choix. Vous pouvez voir que quelques serveurs externes (c'est dire qui peuvent tre interfacs avec un serveur Web, ne pas confondre avec indpendant) correspondent ces deux critres. Le choix que je vais proposer ici ne dpend que de prfrences auxquelles vous n'adhrerez pas forcment, mais je tenterais de justifier le rejet d'autres solutions (comme je l'ai fait pour le choix du type de serveur). Tout d'abord WAIColRunner doit tre utilis conjointement un serveur Web Netscape Enterprise Server ou Netscape Fast Track Server (le dernier est une version allge du premier). Cela limite considrablement le choix quant au serveur Web, mme si celui-ci est trs largement diffus au sein des entreprises. C'est un moteur de Servlets payant ds que l'on veut obtenir un support technique. En ce qui concerne JRun de Allaire, il propose, grce JRun Studio une suite intgre sduisante pour le dveloppement de Servlets (dbogage distance, dveloppement rapide, etc., ) et propose quelques caractristiques intressantes comme la compatibilit avec la majorit des serveurs Web existants mais il est payant (le prix varie entre 495 dollars et 18 395 dollars). Il reste alors Resin de Caucho et Tomcat de la Fondation Apache. Le premier possde un nombre impressionnant d'avantages : il supporte les principaux serveurs Web du marche (iPlanet, IIS, Apache), est dot d'outils intressants comme le support de XSL et X ML pour grer les modles de documents (entre autres) et supporte mme la version 2.3 de l'API des Servlets (qui n'est qu'au stade de proposition)2.3. Cependant l'utilisation est payante si elle entre dans un cadre commercial. Le dernier qui, vous l'aurez compris, est le moteur de Servlets sur lequel je porte mon choix, est Tomcat de la fondation Apache. Je l'ai choisi car il tourne sur un nombre trs important de systmes d'exploitation diffrents, qu'il est trs bien intgr au serveur Apache (mais aussi d'autres comme IIS), et qu'il est distribu dans les termes d'une licence en faisant en logiciel libre (il est donc disponible gratuitement). De ces caractristiques dcoule qu'il est trs simple de se documenter sur ce moteur de Servlets, de trouver des personnes sachant le manipuler et que son dveloppement est trs actif2.4. De plus, il n'est pas ncessaire de dmontrer l'efficacit du serveur Web Apache auquel on l'associe en gnral. Nous disposons maintenant d'une solution souple et performante base sur le moteur de Servlets Tomcat et le serveur Web Apache. Je vais vous guider maintenant dans l'tape d'installation et de configuration de cette solution, en me concentrant sur ce qui peut vous tre utile et en vous laissant consulter la documentation livre avec le serveur pour les dtails.
http://java.developpez.com/cours/servlets/
que l'installation sur des systmes de la famille Unix ne changera que trs peu au pire des cas, et que l'installation sous Windows ne diffrera qu'au niveau des fichiers installer (il faudra tlcharger les binaires pour Windows et non les sources pour Unix) et ne ncessitera pas de compilation. Je vais donc vous dcrire l'installation de Tomcat et Apache sous un systme Linux, en particulier une distribution Debian dans sa version 2.2. Il est admis ici que vous disposez d'un compilateur de programmes crits en C qui fonctionne et qui est compatible avec gcc. Pour vous en assurer, entrez la commande :
gcc -version
Une fois ceci effectu, dplacez vous dans le rpertoire $JAVA_HOME/bin o $JAVA_HOME est le rpertoire dans lequel le JDK est install (dans notre exemple : /usr/local/jdk1.3/bin) de la manire suivante :
cd /usr/local/jdk1.3/bin
Si vous obtenez un message vous indiquant toutes les options disponibles pour le compilateur Java, c'est gagn. afin de faire bnficier toutes vos applications susceptibles d'utiliser Java (comme Tomcat) de l'environnement install, je vous conseille d'ajouter les outils du langage dans votre PATH comme ceci :
export PATH=$PATH:/usr/local/jdk1.3/bin
en considrant toujours que vous avez install le JDK dans /usr/local/jdk1.3. Maintenant vous pouvez utiliser les outils du langage (le compilateur, le visionneur d'applets, etc.) o que vous soyez dans l'arborescence de votre systme de fichiers.
- 16 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
Maintenant que l'environnement de dveloppement pour Java est install, nous allons passer l'installation du moteur de Servlets Tomcat.
Une fois ces outils tlchargs, vous devez crer un rpertoire de base pour la cration d'une version binaire de Tomcat : nous utiliserons /usr/local/tomcat-dist :
mkdir /usr/local/tomcat-dist
http://java.developpez.com/cours/servlets/
Installons maintenant les packages Java ncessaires la compilation de Tomcat. Nous avons dj copi le package des Servlets dans /usr/local/jdk1.3/jre/lib, il faut faire de mme avec les fichiers jaxp.jar et parser.jar de la version de JAXP que vous avez rcupr et avec les fichiers jnet.jar, jsse.jar et jcert.jar que vous avez rcupr dans l'archive de JSSE. Ce procd vous vite d'ajouter le chemin vers ces fichiers dans la variable d'environnement CLASSPATH, mais vous pouvez galement utiliser cette mthode. Maintenant, il faut compiler Ant. Pour cela, allez dans le rpertoire dans lequel vous l'avez dcompress et entrez :
./build.sh
la compilation devrait se drouler sans aucun problme. Si une erreur de compilation mentionne qu'une classe ou qu'un package est introuvable, vous devriez vrifier que les .jar sus-cits sont un emplacement correct (ou que la variable d'environnement CLASSPATH contient de bonnes valeurs.). Il faut maintenant compiler Tomcat. Pour cela positionnez vous dans le rpertoire dans lequel vous l'avez dcompress, et lancez :
./build.sh dist
cette commande va construire une "distribution" binaire identique celle qui est tlchargeable sur le site de la fondation Apache mais adapte votre configuration. Une fois la compilation effectue, vous pouvez tester le fonctionnement de tomcat. Pour cela, allez dans le rpertoire "bin" de votre distribution de Tomcat qui devrait tre $TOMCAT_HOME/build/tomcat/bin si $TOMCAT_HOME est /usr/local/tomcat-dist. Entrez en tant qu'utilisateur "root" :
./startup.sh
Vous devriez voir un srie de messages apparatre mentionnant le dmarrage de Tomcat. Ouvrez ensuite un navigateur Web, et demandez d'accder l'URL suivant : http://127.0.0.1:8080/. Si vous obtenez la page de garde du serveur Tomcat, tout fonctionne parfaitement. A ce moment prcis, Tomcat fonctionne en mode indpendant, ce qui n'est pas ce que nous
- 18 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
souhaitons (voir choix_solution). Nous allons maintenant dcrire son association avec le serveur Web Apache de faon en faire un moteur de Servlets externe.
ce qui devrait crer le rpertoire /usr/local/src/apache-1.3.14. Allez dans ce rpertoire avec la commande :
cd /usr/local/src/apache-1.3.14
ceci va activer le support des modules chargeables dynamiquement, ce qui sera ncessaire pour la communication entre Apache et Tomcat. Une fois le script de configuration termin, lancez la commande suivante :
make install
qui va compiler et installer le serveur Web Apache dans le rpertoire /usr/local/apache. Passons maintenant la prise en charge de Tomcat. Comme je l'ai dcrit plus haut, il existe deux faons diffrentes de procder (voir jk_versus_jserv).
si vous avez effectu les mmes manipulations que celles qui ont t dcrites prcdemment. Il faut ensuite utiliser l'utilitaire apxs fournit avec Apache et qui se trouve dans /usr/local/apache/bin (toujours si vous avez suivi mes instructions la lettre) comme ceci :
http://java.developpez.com/cours/servlets/
ce qui devrait crer un module chargeable mod_jserv.so. Copiez ce fichier dans le rpertoire de stockage des modules chargeables de Apache comme ceci :
cp mod_jserv.so /usr/local/apache/libexec
et spcifiez Apache que vous dsirez utiliser ce module pour communiquer avec Tomcat. Pour cela, un fichier tomcat-apache.conf a t cr dans l'arborescence de la distribution de Tomcat que vous avez cr. Il suffit de l'inclure dans le fichier de configuration de Apache. Ceci peut tre effectu en ajoutant la ligne suivante dans le fichier /usr/local/apache/conf/httpd.conf :
Include /usr/local/tomcat-dist/build/tomcat/conf/tomcat-apache.conf
et en validant la modification. Arrtez ensuite tout processus concernant Apache ou Tomcat et lancez Tomcat puis Apache comme ceci :
/usr/local/tomcat-dist/build/tomcat/bin/startup.sh /usr/local/apache/bin/apachectl start
ce qui devrait afficher quelques messages prcisant que ces deux applications se sont correctement lances. Vous pouvez maintenant tester votre installation en accdant l'URL http://127.0.0.1/test/. Si vous obtenez une page Web vous souhaitant un joyeux Nol, la configuration est termine.
et inclure le fichier /usr/local/tomcat-dist/build/tomcat/conf/mod_jk.conf dans le fichier de configuration d'Apache httpd.conf. Redmarrez Tomcat et Apache comme prcis dans la section prcdente et effectuez le mme test.
- 20 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
La configuration des outils de communication entre Apache et Tomcat sont mis en place, mais je n'ai pas expliqu leur comportement en dtail, ce qui peut tre gnant si vous dsirez personnaliser votre systme. Je vous conseille donc de vous reporter la documentation de Tomcat livre avec les sources de celui-ci pour bnficier d'avantages comme la rpartition de charge, l'utilisation de machines virtuelles java distantes ou encore le rglage fin de la scurit.
Le programme Java tendant une de ces deux classes peut galement utiliser les classes de l'API standard ou d'autres extensions (Java Mail, JTA ou autres) comme n'importe quel programme Java. La ncessit d'implmenter l'interface javax.servlet.Servlet vient du fait que le moteur de Servlet qui gre les appels votre Servlet doit pouvoir obtenir un point d'entre dans votre programme (qui n'est pas la mthode main puisqu'une Servlet est instancie une seule fois, son premier lancement) pour chaque requte. Ce point d'entre est une des mthodes dfinie dans l'interface javax.servlet.Servlet. Voici un exemple de code pour vous donner une ide plus prcise :
import javax.servlet.*; import java.servlet.http.*; public class BonjourMonde extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException) { res.setContentType("text/html"); PrintWriter out = res.getWriter(); out.println("<html><head></head><body>"); out.println("Hello world !!!"); out.println("</body></html>"); } }
Dans cet exemple, c'est la mthode doGet() qui sert de point d'entre. Elle est excute quand un
http://java.developpez.com/cours/servlets/
client effectue une requte utilisant la mthode HTTP GET et construit une page HTML, qui est retourne au client. Saisissez cet exemple dans un diteur de texte quelconque, sauvegardez sous le nom "BonjourMonde.java" et compilez le l'aide la commande suivante :
javac BonjourMonde.java
En principe, aucun message ne devrait apparatre. Si ce n'est pas le cas, vrifiez bien que vous avez bien suivi toutes les tapes du procd d'installation de l'environnement de travail. Votre premire Servlet est maintenant compile, vous devez la publier sur votre serveur. En ce qui concerne Tomcat, vous devez placer le fichier .class obtenu la suite de la compilation du source un endroit bien prcis. Le choix de cet emplacement dpend du rle de votre Servlet et de vos fichiers de configuration relatifs Tomcat et Apache. Lorsque vous ne modifiez aucun de ces fichiers, vous pouvez par exemple copier les fichiers .class de votre Servlet dans $TOMCAT_HOME/webapps/test/WEB-INF/classes/ o $TOMCAT_HOME correspond au rpertoire dans lequel Tomcat est install. Dans ce cas prcis, vous accderez votre Servlet via l'URL http://127.0.0.1/test/servlet/BonjourMonde. Un charmant message devrait apparatre sur votre navigateur : vous venez de programmer votre premire Servlet. Il existe d'autres manires de dvelopper des Servlets. Ce sont les JSP (pour Java Server Pages) et SSI (pour Server Side Includes).
2.4.1 - SSI
C'est une mthode qui existe dj pour d'autres techniques de programmation d'applications qui tournent sur un serveur Web. En effet, il est possible d'utiliser SSI en programmant des scripts CGI par exemple. Afin de pouvoir utiliser cette technique, le serveur Web doit proposer un support pour les SSI. Ce support varie d'un serveur l'autre. Une Servlet utilise avec SSI se compose de deux parties : le code de la Servlet elle-mme et le code HTML de la page Web qui inclue le rsultat de cette Servlet. Voici un exemple de code HTML pour une page dsirant utiliser la Servlet Bonjour :
- 22 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
<HTML> <BODY> <TITLE>Essai d'utilisation de SSI</TITLE> <P> Voici un exemple d'utilisation de la sortie produite par une Servlet. </P> <SERVLET CODE=Bonjour CODEBASE=http://localhost:8080/> <PARAM NAME="nom" VALUE="Julien"> Si vous lisez ce texte, c'est que votre serveur Web ne supporte pas les Servlets utilises via SSI. </SERVLET> </BODY> </HTML>
Afin de signaler au serveur Web que cette page HTML comprend une directive SSI, il faut nommer le fichier avec l'extension ".shtml", et non ".html". Ceci est le comportement par dfaut et dpend en ralit de la configuration de votre serveur Web. Tout d'abord on remarque une balise inhabituelle : la balise <SERVLET>. C'est elle qui indique que l'on veut inclure le contenu produit par une Servlet dans la page Web. Cette balise reconnat plusieurs paramtres. Le paramtre CODE indique le nom de la Servlet invoquer. Le paramtre CODEBASE doit, juxtapos la valeur du paramtre CODE, former l'URL grce auquel on peut accder la Servlet en temps normal (sans utiliser SSI). Ensuite, il est possible de passer des paramtres cette Servlet, grce la balise PARAM. Le nom de ce paramtre est prcis par l'attribut NOM et la valeur par VALUE. Ces paramtres seront rcuprs par la mthode getParameter(String nomParametre) de l'objet de type HttpServletRequest pass la Servlet lors de son invocation. Le texte crit juste avant la fermeture de la balise SERVLET s'affiche au cas o le serveur Web ne supporte pas cette balise (et donc les Servlets invoques via SSI). Il est galement possible de dterminer les valeurs de certains paramtres ds l'initiali sation grce un attribut plac dans la balise <SERVLET> de la forme initParamtre1=valeur1. La servlet Bonjour, appele lors de l'analyse de la page HTML ci-dessus, pourrait tre la suivante :
import javax.servlet.*; import java.servlet.http.*; public class BonjourMonde extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException) { PrintWriter out = res.getWriter(); String param1 = req.getParameter("nom");
http://java.developpez.com/cours/servlets/
Il suffit de compiler cette Servlet de manire classique et de la placer l'emplacement indiqu par la balise "CODEBASE" du code HTML de la page incluant la sortie de la Servlet. On note la compacit du code par rapport une Servlet autonome produisant le mme effet. Les Servlets invoques via SSI sont intressantes lorsque le contenu statique est plus important que le contenu dynamique. Cela permet l'intgrateur du code HTML et au dveloppeur de Servlets une plus grande libert : ils n'ont rien modifier pour que les modifications soient prisent en compte des deux cts. On remarque aussi qu'il ne faut pas dfinir le type MIME de la rponse, car la rponse du serveur Web a dj dbut au moment de l'appel la Servlet, et ce dbut de rponse contenait l'entte prcisant son type MIME (voir protocole_http). La ligne :
res.setContentType("text/html");
2.4.2 - JSP
Une autre technique d'inclusion de code dans des pages HTML est JSP. Cette technique est ne d'un besoin manant des dveloppeurs : ils avaient besoin d'un mode de dveloppement similaire aux ASP de Microsoft (voir ASP_microsoft) et PHP (voir la mme section que pour ASP). De cette manire ils pourraient inclure directement du code (et non pas un marqueur appelant une Servlet) dans la structure de leurs documents crits en HTML. Les JSP permettent donc d'viter au programmeur d'employer l'instruction out.println(String chaine_a_imprimer) trop souvent lorsque le contenu est en majorit statique. Cependant, elles ne garantissent pas une trs bonne coopration entre l'intgrateur HTML et le dveloppeur de Servlets, dans le cas o ils ne sont pas la mme personne. En effet si le programmeur dsire changer son code, il doit ouvrir le fichier contenant le code HTML et si l'intgrateur HTML dsire changer la structure ou le contenu de la page Web, il doit ouvrir le fichier contenant le code de la Servlet. C'est donc priori moins souple mais il s'avre que cette technique est trs bien adapte pour les dveloppements de petite envergure, et lorsque le dveloppeur et l'intgrateur HTML ne sont qu'une seule personne.
2.4.3 - La forme
Voici comment se prsente une JSP qui produit le mme message que les Servlets prcdentes (une salutation amicale trs clbre) :
<HTML> <HEAD> <TITLE>Essai de JSP</TITLE> </HEAD> <BODY>
- 24 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
<% if (request.getParameter("nom") == null) { out.println("Bonjour monde !"); } else { out.println("Bonjour " + request.getParameter("nom") + " !"); } %> </BODY> </HTML>
Il suffit d'enregistrer ce fichier avec un nom ayant pour extension ".jsp" et de le placer dans le rpertoire adquat, ce qui peut dpendre de la configuration de votre serveur Web ou du moteur de Servlets que vous utilisez. Je vais vous donner maintenant quelques explications sur les critures pouvant vous sembler mystrieuses. Premirement, la balise "<%" permet d'indiquer le dbut d'une section de code dynamique. La balise "%>" permet donc de marquer la terminaison d'une telle section (on appelle ce type de section une scriptlet). Je garde une appellation aussi gnrale car il est possible d'crire des JSP avec un autre langage que Java (comme javascript qui est compltement diffrent) mme si ce n'est pas trs courant. A l'intrieur de ce code, on peut placer plusieurs types d'instructions : les directives. les expressions. le code classique.
Les directives permettent de dfinir certains aspects structurels de la servlet de fond, comme l'importation d'un package, l'extension d'une classe, le type de contenu produit ou encore la mthode HTTP utilise (voir mthodes http pour connatre ce qu'est une mthode HTTP). Les dfinitions sont effectues par l'intermdiaire d'affectation de valeurs des variables bien dfinies. Ces directives sont encadres d'une balise ouvrante "<%@" et d'une balise fermante "%>". Par exemple, pour importer le package "monpackage" dans la JSP, il suffit d'insrer le code suivant :
<%@ import = "monpackage.*"%>
si l'on veut que la servlet de fond tende la classe maClassePersoHttp. Je ne vais pas numrer toutes les directives disponibles ici, pour cela je vous invite vous reporter l'annexe B et la documentation de rfrence propos de jsp disponible http://java.sun.com/products/jsp/. Les expressions permettent de convertir le rsultat de l'expression value en String et d'inclure ce rsultat converti dans le code HTML de la page Web gnre par la Servlet de fond. Cela permet d'liminer les appels la mthode println(String chaine). Une expression dbute par la balise ouvrante
http://java.developpez.com/cours/servlets/
"<%=" et se termine par la balise fermante "%>". Par exemple, l'expression suivante :
<%= ma_variable %>
inclut la valeur de la variable ma_variable dans le code HTML gnr. On peut bien entendu utiliser des mthodes comme expression valuer comme dans :
<%= request.getParameter("parametre") %>
qui permet d'inclure la valeur du paramtre de nom parametre pass la Servlet de fond. Remarquez que l'absence de ";" la fin de l'expression n'est pas un oubli. Le code classique utilise les mmes conventions que les Servlets traditionelles, mais vous pouvez remarquer l'emploi d'identifiants qui n'ont pas t dfinies. Ces identifiants sont : request : l'objet reprsentant la requte venant du client. out : l'objet reprsentant le flux d'impression en sortie.
Ils sont utilisables dans chaque page Web utilisant JSP. Maintenant que nous avons dcrit la forme du dveloppement de Servlets grce JSP, intressons-nous au fonctionement interne.
2.4.4 - En coulisses
Je mentionne dans la section prcdente le terme de "Servlet de fond". En effet, le moteur de Servlets ne procde pas un interprteur spcifique aux Servlets et un autre spcifique aux documents utilisant JSP. Le procd d'excution d'une JSP se droule en plusieurs tapes. Tout d'abord, le fichier correspondant la JSP, qui comprend la fois du code HTML, du code Java ainsi que les directives et dclarations, est traduit afin d'obtenir le code d'une Servlet aboutissant au mme rsultat. Cette traduction est quasiment directe pour le code dynamique tandis que le code statique est traduit grce des appels la mthode println(String chaine). Une fois la traduction effectue, la Servlet de fond obtenue (qui est alors une servlet tout fait classique jusqu' la fin de son cycle de vie) est dplace dans un emplacement particulier du systme de fichier du moteur de Servlet pour y tre compile, comme une Servlet traditionnelle. Une fois compile, la Servlet de fond est charge, initialise et excute. De ce procd d'excution des JSP dcoulent plusieurs de leurs comportements propres. En effet, lors de la premire excution d'une JSP, vous constaterez qu'il est ncessaire de patienter un certain temps avant d'obtenir le rsultat du traitement, alors que lors des appels ultrieurs, ce n'est pas le cas. Cela est d au fait que lors du premier appel, il faut raliser tout le procd de la traduction l'excution (en passant par la compilation) alors que lors des appels suivants, seule l'excution est ncessaire. Ensuite, il est maintenant clair et lgitime de ne pas disposer d'une API spcifique aux JSP, car ce sont en dfinitive des Servlets classiques avant leur compilation. Seul le support propos
- 26 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
par le moteur de Servlets influe sur les possibilits dont vous pouvez bnficier (comme de nouvelles directives permettant d'inclure des Java Beans par exemple). Enfin, vous pourrez comprendre que votre JSP se recharge automatiquement ds que le fichier contenant son code est modifi (le fichier possdant l'extension ".jsp") car une Servlet est recharge par le moteur de Servlets pour les mmes raisons. Il me semble ncessaire de prciser que malgr les services que peuvent rendre les JSPs pour de petites applications, elles ont surtout t cres pour opposer une rponse aux ASPs de Microsoft. Ces dernires ressemblent en effet normment aux JSPs tous les niveaux, et sont apprcies des programmeurs Web ct serveur pour leur facilit d'utilisation. Vous connaissez maintenant les principales formes de dveloppement des Servlets, je vais maintenant vous proposer quelques rfrences propos d'outils de dveloppement pouvant faciliter la programmation en tirant parti des avantages de la technologie de la plate-forme Java ct serveur.
http://java.developpez.com/cours/servlets/
Toutes ces caractristiques et d'autres encore sont reprises par plusieurs outils que je vais prsenter succintement ici, il ne tient qu' vous de devenir un utilisateur averti de ces logiciels. Le premier de ces outils est JBuilder de Borland. La version 4.0 a apport de sensibles amliorations et cet IDE (pour Integrated Development Environmnent) propose quelques caractristiques intressantes comme l'intgration de la version 1.3 du JDK, le dbogage distance, le dbogage et mise en valeur du code source pour JSP, le support de la version 2.2 de l'API Servlet et de la version 1.1 des JSP, un moteur de Servlets intgr (WebLogic de BEA, voir weblogic_bea), la cration visuelle de Java Beans et le dploiement de ceux-ci sans redmarrer le moteur de Servlets. Toutes ces caractristiques sont disponibles avec la version "Entreprise" du logiciel, qui est la plus aboutie mais aussi la plus chre . Certaines sont disponibles avec des versions moins volues, pour en savoir plus reportez vous l'URL http://www.borland.com/jbuilder/jb4/feamatrix/. Il est noter que la version personnelle disponible gratuitement ne propose aucun de ces avantages. Nous trouvons ensuite JRun Studio de Allaire, qui en est actuellement sa version 3.1. C'est un outil de dveloppement destin tre coupl au serveur d'application JRun du mme diteur. Ce produit ne fonctionne que sous Windows et dispose de fonctionalits similaires JBuilder mais il contient de nombreuses fonctionnalits destines la conception d'applications Web, la manire d'un outil d'intgration HTML. Certains peuvent le percevoir comme un avantage (les intgrateurs de code HTML), d'autres comme un inconvnient (les programmeurs) car cela peut ajouter un peu de confusion.
- 28 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
3 - Fonctionnement interne
Vous devriez maintenant disposer des connaissances suffisantes pour pouvoir dbuter le dveloppement de servlets et les faire fonctionner grce aux outils de travail que vous avez pu mettre en place prcdemment. Je vais maintenant tenter de vous dcrire de manire complte le fonctionnement interne du moteur de servlets qui permettra de faire fonctionner vos futures servlets de manire efficace et cohrente. Grce aux connaissances que vous allez acqurir dans ce chapitre, j'espre que vous comprendrez rellement le fonctionnement des servlets. Cela devrait vous permettre d'tre relativement indpendant par rapport la suite de votre apprentissage car vous pourrez comprendre n'importe quel document au sujet des servlets et vous pourrez aussi dduire des connaissances par vous mme au prix d'un effort de rflexion logique. Il est important de noter que, mme si les notions voques dans ce chapitre paraissent trop techniques et relever du dtail, elles vous seront vraiment utiles dans votre dveloppement de tous les jours. En effet, les mcanismes de fonctionnement de la plate-forme Java influeront directement sur le code que vous crirez. Comme le dit si bien le proverbe, je vais tenter de vous apprendre pcher plutt que de vous offrir le poisson chaque fois que le besoin s'en fera sentir. Les moteurs de Servlets ont besoin d'une machine virtuelle Java pour fonctionner. Cela signifie qu'en rentrant dans les dtails de fonctionnement des Servlets, j'voquerai de nombreuses reprises des notions ayant trait au fonctionnement de toute machine virtuelle Java et des notions encore plus universelles comme les threads, les processus, le chargement des classes au dmarrage d'une application, le ramasse-miettes ou encore les rfrences. Je considre tout ceci comme acquis et je ne donnerai pas d'explications sur ces notions part si elles possdent quelques spcificits lies leur utilisation par les Servlets. Il est donc temps, si vous ne matrisez pas toutes ces notions, de vous documenter. Une bonne source pour se documenter sur de tels sujets est le bouquin "The Java Virtual Machine" disponible l'URL http://java.sun.com/docs/books/vmspec/ qui vous apportera plus de connaissances qu'il n'en faut. Il existe de nombreux fournisseurs de machines virtuelles Java diffrents. Chaque fournisseur se conforme la norme dfinie par Sun et les bibliothques de classes ainsi que les machines virtuelles fournies par ces organismes possdent les mmes "interfaces" mais pas forcment la mme implmentation de ces interfaces. Un chargeur de classes peut trs bien utiliser une mthode diffrente pour la JVM de Microsoft pque pour la JVM de Sun. Ce n'est pas une chose rare. Les moteurs de Servlets eux aussi proviennent de nombreux diteurs diffrents et sont donc programms diffremment par des dveloppeurs diffrents. Ils se conforment aux aussi une norme dfinie par Sun qui est reprsente par les spcifications de l'API des Servlets qui ne dcrit que les comportements que doivent suivre les moteurs de Servlets de faon gnrale. L'implmentation est libre et toujours diffrente entre deux moteurs de Servlets diffrents. Or nous avons vu que les moteurs de Servlets ne peuvent pas fonctionner sans une machine vi rtuelle Java, ce qui m'amne cet avertissement : les comportements que je vais dcrire dans le prsent chapitre sont des comportements recommands et rencontrs le plus souvent possible mais peuvent tre diffrents selon la solution adopte. Je vous conseille donc de garder un oeil critique sur ces descriptions, surtout celles qui voquent les dtails d'implmentation. Les comportements gnraux sont quant eux, en gnral, identiques pour chaque solution. Je tenterai d'effectuer une comparaison avec les autres solutions une fois toutes les connaissances acquises propos du fonctionnement interne.
http://java.developpez.com/cours/servlets/
Nous savons que pour faire fonctionner des Servlets, il est ncessaire de disposer d'une machine virtuelle Java, d'un moteur de Servlets implmentant l'API des Servlets et ventuellement d'un serveur Web. Ces diffrents composants prenant part au systme d'excution des Servlets cooprent d'une faon bien dtermine. J'ai rapidement prsent ce fonctionnement lors de la description des diffrentes solutions (voir choix_solution) pour la mise en place d'une plate-forme excutant des Servlets, mais il est ncessaire d'apporter des prcisions. La machine virtuelle Java peut tre relie de plusieurs faons au serveur Web qui gre les requtes venant de l'utilisateur, ceci dpendant du type de solution choisi : La machine virtuelle fait partie intgrante serveur, le serveur tant crit en Java : c'est le cas du moteur de Servlets indpendant (comme Java Web Server ou Tomcat dans certains cas). Le moteur de Servlets est alors un thread de la JVM au mme titre que les Servlets qu'il excute, et que le serveur Web qui accepte les requtes HTTP. La machine virtuelle Java constitue un des Threads du serveur Web : c'est le cas du moteur de Servlets embarqu dans un serveur Web mono-processus et multi-threads. Dans ce cas prcis l'intgration des Servlets dans le serveur Web est importante et il est facile, par exemple, de rcuprer des informations concernant la requte provenant du client via les mthodes fournies par l'API des Servlets. La machine virtuelle Java est un processus externe au serveur Web, qui est lui multi-processus. C'est le cas de Tomcat lorsqu'on l'utilise comme moteur de Servlets externe coupl au serveur Web Apache. Les processus lancs par le serveur Web et qui reprsente autant de clients effectuant des requtes HTTP peuvent alors ce partager le processus correspondant la JVM externe. Suivant le choix de la solution, c'est aussi le cot en ressource processeur et mmoire qui va changer : plus le moteur de Servlets est externalis, plus les changements de contexte sont lourds. En effet, les informations spcifiques celle-ci pourront tre partages directement dans le cas des moteurs de Servlets indpendants (changement de contexte lger) ou devront tre pralablement copies en mmoire et ncessiter donc un traitement (changement de contexte lourd) dans le cas des moteurs de Servlets externes. Cependant, quelle que soit la solution adopte, chaque Servlet s'excute dans un thread de la machine virtuelle Java laquelle elle est associe. Cela implique que les Servlets peuvent communiquer entre elles facilement (changement de contexte lger) car elles fonctionnent dans le mme espace d'adressage et les donnes sont donc accessibles en lecture et en criture simplement. Le fait qu'elles constituent un thread excut dans la mme machine virtuelle que le moteur de Servlets qui les excute prsente aussi quelques particularits gnantes. En effet, le moteur de Servlets et les Servlets partagent le mme processus et une Servlet peut trs bien entreprendre une action affectant le processus complet (et donc le moteur de Servlets). Un des exemples critiques est l'emploi de l'instruction System.exit() dans le code d'une de vos Servlets qui cause l'arrt du moteur de Servlets jusqu' ce que l'administrateur le redmarre. Bien entendu, il existe des moyens tout fait classiques d'viter ce type de problme (voir le chapitre traitant de la scurit et plus particulirement le Security Manager). Ce type de comportement illustre trs bien un des aspects du fonctionnement des moteurs de Servlets. La ncessit de disposer du traitement de plusieurs requtes de manire simultane provient de l'utilisation mme des applications Web : plusieurs personnes peuvent demander le mme service en mme temps. Que se passe-t-il si plusieurs personnes demandent accder la mme Servlet en
- 30 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
mme temps ? Il existe deux solutions possibles (comme il est prcis dans la normalisation des Servlets) : Une seule instance de chaque servlet est charge en mmoire et chaque requte venant des clients Web sont autant de threads qui peuvent manipuler cette instance. A chaque requte HTTP correspond une instance diffrente pour chacune des servlets. Plus il y de requtes demandant l'accs une servlet, plus il y a d'instances de cette servlet charges en mmoire.
La premire solution constitue le comportement par dfaut, ainsi aucune particularit dans la syntaxe de votre code ne doit tre ajoute. Lorsqu'un client accde une Servlet, la mthode principale (doGet(), doPost() ou service() selon le choix de la mthode HTTP et de l'interface implmente) est appele et un nouveau thread est cr. C'est dans ce nouveau thread que le traitement correspondant au code de votre Servlet va tre excut. Cependant, c'est toujours la mme instance de la Servlet qui prend en charge la requte : les attributs de classes d'une mme Servlet modifis par un client sont donc modifis pour tous. Cela implique l'utilisation des smaphores via le mot clef synchronized afin de faire face aux ventuels problmes de synchronisation. Il faut donc prendre garde bien synchroniser la manipulation des attributs d'instance, mais aussi ne pas tout encadrer dans un bloc synchronis : le caractre simultan des requtes serait alors perdu. Par exemple, vous ne devez pas marquer la mthod e principale (doGet(), doPost() ou service() en gnral) avec le mot clef synchronized, l'instruction accdant en lecture ou en criture l'attribut en question doit elle seule tre encadre. Voici un exemple de code d'une mauvaise synchronisation, puis d'une bonne synchronisation : MauvaisThread
import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class MauvaisThread extends HttpServlet { private int compteur = 0; public synchronized void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { PrintWriter out = res.getWriter(); compteur++; out.println("Cette Servlet a t accde " + compteur + " fois."); } }
BonThread
import javax.servlet.*; import javax.servlet.http.*; import java.io.*;
http://java.developpez.com/cours/servlets/
BonThread
public class BonThread extends HttpServlet { private int compteur = 0; public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { synchronized(this) { int tmpCompteur = ++compteur; } PrintWriter out = res.getWriter(); out.println("Cette Servlet a t accde " + tmpCompteur + " fois."); } }
La ncessit d'apporter une attention particulire la synchronisation est une des principales charge de travail qu'impose l'attribution d'un thread spar pour chaque requte vers la mme Servlet. Par contre, l'amlioration au niveau de l'occupation mmoire et de la vitesse d'excution est perceptible : un seul ensemble de classes est charg en mmoire (les classes utilises par les Servlets qui ont t demandes au moins une fois) et lors d'une nouvelle requte, tout l'environnement de la Servlet n'est pas dupliqu, c'est un thread qui est cr : cela prend moins de temps. C'est un modle vraiment diffrent des applications utilisant la norme CGI car, dans ce cas l, chaque requte correspond un processus, ce qui pose d'vidents problmes d'occupation en mmoire et de vitesse d'excution (surtout pour le lancement du script). Les autres modes de dveloppement comme PHP (lorsqu'il est utilis en temps que module d'un serveur Web) ou ISAPI par exemple sont assez similaires au niveau du modle d'excuti on (une seule instance du programme, chaque requte est un thread diffrent). Bien entendu, la synchronisation n'est pas ncessaire si vous manipulez des variables locales seulement, qui sont propres chaque thread, et donc chaque requte. Ce modle d'excution permet aussi la persistance des Servlets : une Servlet peut trs bien conserver en mmoire des informations acquises au fur et mesure des nombreuses requtes, cela introduit de nombreuses facilits de programmation pour traiter des cas faisant appel des renseignements provenant des requtes antrieures, comme le compteur prcdent. Une autre consquence qui montre bien le mode de fonctionnement d'une Servlet utilisant un mode d'excution classique est la persistance des threads nouvellement crs l'intrieur du code d'une Servlet. En effet, lorsqu'un thread est cr et lanc lors du traitement d'une requte, celui-ci ne se termine pas lorsque la requte est termine ( moins qu'on prcise le contraire) mais lorsque l'instance de la Servlet est dtruite (c'est dire rarement dans des conditions normales d'utilisation : lors de l'arrt du moteur de Servlets). Cela permet d'effectuer des traitements de type batch trs intressant tout en manipulant les donnes de l'instance de la Servlet. On peut imaginer une Servlet lanant toutes les nuits la production d'un rapport en arrire plan L'autre modle d'excution est le modle mono-thread. Ici, chaque requte correspond une instance de Servlet. La totalit des instances cres pour une Servlet se nomme le pool de Servlets. Lors d'une nouvelle requte, le thread correspondant cette requte puise dans ce pool de Servlets et communique avec l'une d'entre elles. Il est impossible, lors de l'utilisation de ce modle d'excution, que deux requtes concurrentes soient lies la mme instance de Servlet. C'est important car c'est
- 32 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
cette impossibilit qui rend ce modle d'excution "Thread Safe", c'est dire sr par rapport aux threads, sans modification dans le code, et sans devoir prter attention quoi que ce soit de particulier (comme la synchronisation). La ou les Servlets dsirant bnficier de cette particularit doivent implmenter l'interface SingleThreadModel. Cela permet de bnficier de ce comportement pour certaines Servlets de votre choix, et de conserver un comportement multi-thread pour les autres. C'est la seule contrainte au niveau de l'criture du code source d'une Servlet utilisant un tel modle d'excution. Bien entendu, les possibilits et avantages voqus lors de la description du modle d'excution traditionnel ont disparus, mais d'autres sont apparus. D'une part vous tes vraiment sr que plusieurs requtes effectues en mme temps ne produiront pas de rsultats errons (ce que vous ne pouvez garantir moins d'tre un expert en programmation multi-thread). Ensuite cela vous permet d'exploiter plus efficacement le caractre multi-thread des applications utilises par vos Servlets. C'est un peu paradoxal mais prenons l'exemple d'une Servlet lie un SGBD : dans le cas d'une seule instance de Servlet, il n'est pas efficace de grer les multiples connexions avec des comptes utilisateurs diffrents (correspondant aux utilisateurs effectuant la requte ct client) tout en synchronisant les connexions et les requtes. C'est un peu le mme problme que de rinventer la roue : le travail effectu en temps normal par le SGBD pour synchroniser les connexions multiples serait alors effectu par la Servlet. De plus, le traitement ne serait pas le plus efficace dans le cas du modle d'excution traditionnel, alors qu'il le serait dans le cas d'un modle mono-thread, tout en dbarassant le programmeur de taches fastidieuses de synchronisation. En effet chaque instance de la Servlet utilise son environnement et les requtes envoyes la base n'ont pas besoin d'tre synchronises. Nous avons vu que, dans tous les cas, chaque Servlet tait matrialise par un thread lanc par une JVM, et qu'il existe deux modles d'excution : le modle multi-thread et le modle mono-thread. Le premier correspond trs bien une gestion centralise des ressources (comme pour un serveur de discussion en temps rel par exemple). En effet, la servlet agit alors comme un rpartiteur de messages entre les diffrentes personnes connectes, les informations doivent donc tre centralises. Le deuxime s'accorde trs bien avec l'utilisation de systmes grant dj le multithreading et ncessitant des traitements ponctuels efficaces qui ne se basent pas sur les requtes prcdentes. Ainsi l'absence de gestion de synchronisation permet de servir chaque requte au plus vite, alors que la concurrence des requtes gres par le SGBD est assure par ce dernier. La description du fonctionnement interne de la gestion des Servlets au sein d'un moteur de Servlets tant termine, je vais maintenant dcrire les diffrentes tapes du cycle de vie d'une Servlet.
3.2.1 - Le chargement
http://java.developpez.com/cours/servlets/
Afin qu'une Servlet puisse accueillir les requtes venant des clients, nous avons vu dans la section prcdente qu'une instance de cette Servlet doit tre prsente. Le processus de chargement de la Servlet est effectu par le moteur de Servlet. Ce chargement peut tre effectu au dmarrage du moteur de Servlets ou bien juste au moment o le moteur dtermine qu'il a besoin de la Servlet en question. Tout d'abord, le moteur de Servlets recherche une classe du type de la Servlet charger l'endroit o se trouvent les classes des Servlets pour chaque contexte (voir contextes). Si la Servlet n'est pas dej charge, le moteur de Servlets charge la Servlet en utilisant un chargeur de classe normal partir du systme de fichier local, ou de toutes autre ressource distante (cela dpend des contextes, pour plus de renseignements propos des contextes, voir contextes). Une fois que la Servlet est charge, elle est instancie et un objet du type de la Servlet charge est donc prsent en mmoire. Une Servlet peut tre charge une fois ou plus par le moteur de Servlets, cela dpend du modle d'excution choisi : si la Servlet implmente l'interface SingleThreadModel plusieurs instances peuvent tre cres en mesure du nombre de requtes faites par l'utilisateur, si rien n'est prcis par le programmeur (la classe de la servlet n'implmente pas SingleThreadModel) une seule instance de la Servlet peut tre prsent e. Plusieurs instances d'une mme Servlet peuvent tre cres galement si plusieurs Servlets identiques possdent des paramtres d'initialisation diffrents. L'initialisation est la dernire tape du chargement d'une Servlet. Une Servlet doit tre initialise avant de pouvoir rpondre aux requtes provenant du client. En effet, il est possible que certaines variables d'instance (ou toutes) de la classe correspondant la Servlet charger requirent des valeurs de dpart, dpendant de paramtres connus seulement au moment o elle sont charges ou enregistres lors de leur dernire destruction.Les valeurs de ces paramtres d'initialisation peuvent tre prcises par un outil de configuration pour certains moteurs de servlets (comme Java Web Server), par une balise spciale lorsque l'on utilise SSI (voir section ssi) ou par programme. Le moteur de Servlet effectue cette initialisation en appelant la mthode init(ServletConfig config) de l'interface Servlet. un paramtre de type ServletConfig est pass lors de l'appel de cette mthode. Ainsi, il est possible d'accder dans le code source de la Servlet aux paramtres d'initialisation employ pour cette dernire. L'ob jet de type ServletConfig pass en paramtre cette mthode permet galement d'accder un objet de type ServletContext (car il implmente l'interface ServletContext) qui dcrit l'environnement d'excution dans lequel tourne la Servlet. Il faut noter que si vous dsirez personnaliser l'initialisation de votre Servlet en redfinissant la mthode init de celle-ci, vous devez imprativement utiliser l'instruction
super.init(config);
en admettant que config soit l'identifiant de l'objet de type ServletConfig pass en paramtre la mthode init que vous redfinissez. Je vous ai dcrit le fonctionnement du chargement d'une Servlet dans le cas o tout se droule comme prvu. Mais qu'en est-il lorsqu'une erreur survient, ou que le chargement de la Servlet n'est pas dsir ? La mthode init peut gnrer une exception de type ServletException ou UnavailableException. Une fois l'exception gnre, le processus de chargement est abandonn et l'instance de la Servlet est immdiatement dtruite. La mthode destroy que nous allons dcouvrir d'ici peu n'est pas appele dans ce cas. Une fonctionnalit intressante est fournie par le constructeur de l'exception de type UnavailableException. En effet, il est possible, via un paramtre pass au constructeur de l'exception, d'imposer au moteur de Servlets de respecter un dlai avant une nouvelle tentative de chargement de la Servlet dont le chargement vient d'chouer. L'instruction suivante :
- 34 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
permet de respecter un dlai de deux minutes avant la prochaine tentative de chargement cause d'un taux d'occupation de la machine serveur trop lev. Le rechargement d'une servlet Il existe une fonctionnalit mise disposition des dveloppeurs de servlets lorsqu'ils se trouvent dans une phase de dveloppement soutenue. En effet, plutt que d'effectuer des manipulations impliquant une interruption de service (le redmarrage du serveur) pour recharger une servlet afin de prendre en compte les modifications apportes au code, c'est le moteur de servlets qui recharge la servlet de faon automatique s'il pense que cela est ncessaire. Ainsi, il suffit de recompiler le code source d'une servlet pour qu'une nouvelle instance de celle-ci remplace l'ancienne instance. On peut galement utiliser la commande touch sous Unix en lui passant comme paramtre le fichier de la classe recharger pour effectuer la mme chose (sans le cot d'une recompilation). Pour dterminer s'il est ncessaire de recharger une classe, le moteur de servlets dtermine si le fichier de classe a chang (en dterminant si la date de dernire modification du fichier de classe est bien gale la date de modification du fichier de classe au moment de son dernier chargement par exemple). S'il a chang, le moteur de servlets arrte le chargeur de classe utilis pour charger la classe prcdente et effectue le chargement de la nouvelle classe avec un nouveau chargeur de classe. Il est ncessaire de passer par cette astuce car il est impossible de charger deux fois la mme classe avec le mme ClassLoader. Cette fonctionnalit peut tre fort intressante pour acclrer la mise jour du code et ne pas interrompre le service pour cette manoeuvre. Cependant, l'utilisation d'un ClassLoader diffrent de celui utilis par les autres classes de la mme application Web peut poser des problmes lis au contexte et la rcupration d'lments partags car les rfrences utilises par les autres classes de l'application peuvent ne plus tre valides. Si la notion de contexte est importante pour votre application, je vous conseille de dsactiver la possibilit du rechargement de classe la vole ou de ne pas l'utiliser.
3.2.2 - L'excution
L'excution consiste, pour une Servlet, accueuilir les connexions inities par les clients et traiter leur demande. En ce qui concerne les Servlets, il est possible de programmer des applications destines servir exclusivement les requtes utilisant le protocole HTTP, ou bien tous types de requtes. Dans le premier cas, la Servlet doit hriter de la classe HttpServlet, dans l'autre, elle hrite de la classe GenericServlet, toutes deux appartenant au package javax.servlet . Pour rpondre une requte gnrique, le moteur de Servlets appelle la mthode service pralablement redfinie dans le code de votre Servlet. Il est possible d'effectuer tous les traitements que vous dsirez partir de l'appel de cette mthode et de renvoyer la rponse. A cette fin, un objet de type ServletRequest possdant toutes les informations sur la requte et un objet de type ServletResponse permettant de transmettre les donnes produites au cours des traitements effectus par la Servlet au client sont passs en paramtres cette mthode service.
http://java.developpez.com/cours/servlets/
Cependant, dans la plupart des cas vous utiliserez une classe hritant de la classe HttpServlet pour programmer vos Servlets. Lorsqu'une requte est reue par le moteur de Servlet, celui-ci examine d'abord de quel type de requte (on parle de mthode) il s'agit . Il en existe peu en ce qui concerne le protocole HTTP. Ce sont : GET : afin de demander au serveur de nous transmettre un flux d'information. Cela peut tre un fichier statique ou des informations cres dynamiquement (c'est le cas des servlets ou tout autre solution de programmation web ct serveur). POST : mme utilit que GET mais les paramtres de la requte sont passs directement au serveur au lieu d'tre concatns l'URL qui identifie la ressource laquelle on dsire accder. HEAD : afin de s'informer sur l'entte renvoye par le serveur lors d'une requte donne. OPTIONS : permet de connatre les services disponibles sur un serveur. PUT : permet de dposer un fichier dans l'arborescence du systme de fichier localis sur la machine faisant tourner le serveur Web. DELETE : permet de supprimer un fichier de l'arborescence du systme de fichier localis sur la machine faisant tourner le serveur Web. TRACE : permet de "pister" une requte afin de voir ce que voit le serveur.
Une fois que la mthode de la requte est identifie, le moteur de Servlet appelle la mthode adquate pour la Servlet laquelle la requte tente d'accder. Pour cela il appelle d'abord la mthode service de la classe qui se charge alors d'appeler la mthode adquate. Voici la table de correspondance entre la mthode HTTP et la mthode appele par le moteur de Servlets :
Mthode appele par le moteur de Servlets doGet() doPost() doHead() doOptions() doPut() doDelete() doTrace()
Deux objets sont passs ces mthodes lorsqu'elles sont appeles : un objet de type HttpServletRequest : il possde tous les renseignements sur les paramtres passs la requte. un objet de type HttpServletResponse : il permet d'obtenir un flux de sortie pour communiquer la rponse au client.
Vous pouvez dfinir plusieurs de ces mthodes dans une servlet. Par exemple dans le cas o une servlet soit appele par un formulaire qui peut utiliser soit la mthode POST soit la mthode GET pour transmettre sa requte, vous dfinirez le code de la mthode doGet et de la mthode doPost. Les mthodes prsentes dans le tableau constituent l'quivalent de la mthode main pour une application classique ou la mthode start pour une applet. En fait la mthode main est la mthode service mais
- 36 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
elle appelle automatiquement la mthode de votre classe correspondant la mthode HTTP utilise par le client qui effectue la requte si vous ne la surchargez pas, ce qui est le cas le plus courant. On peut donc dire que du point de vue du programmeur, la mthode service est ngligeable (dans le cas de servlets HTTP). On remarque galement que chacune de ces mthodes peut gnrer une exception, ce qui suppose que des erreurs peuvent survenir. Que se passe-t-il ce moment l ? Tout dpend de l'exception qui est gnre. Si c'est une exception du type ServletException, c'est le signe d'une erreur lors du traitement de la requte effectu par la mthode en question (doXXX ou service) et le moteur de servlets doit prendre les mesures appropries l'annulation de la requte (terminer le thread cr pour l'occasion, etc.). Si l'erreur produite ncessite une suspension du service fourni par la servlet, c'est une exception du type UnavailableException qu'il faut gnrer. Si l'on dclare que cette suspension est permanente, grce au paramtre entier du constructeur de l'exception, le moteur de servlets supprime la servlet des servlets actives, appelle sa mthode destroy et libre l'espace mmoire allou l'instance de la servlet. Si le dlai pass en paramtre au constructeur de l'exception de type UnavailableException est positif, alors le moteur de servlets peut choisir de ne plus router les requtes dont la servlet est la cible durant la priode passe en argument par le programmeur. Durant la priode de l'indisponibilit, le moteur de servlets tablit une rponse contenant le code HTTP 503 (service non disponible) pour toute requte dont la cible est la servlet qui a gnr l'exception. Il est utile d'adopter ce type de comportement lorsque, par exemple, le SGBD utilis par la servlet pour enregistrer les donnes et qui est situ sur une autre machine n'est plus disponible. Lors de l'apparition d'une erreur, il peut tre utile d'informer le serveur web et l'administrateur de celui-ci qu'une erreur s'est produite. Il est galement pratique, en vue d'un dbogage, de disposer de la trace prcise des erreurs qui sont survenues. Les serveurs disposent en gnral d'un systme de fichiers journaux pour cela, et les moteurs de servlets ne font pas exception la rgle. Pour utiliser ces fichiers journaux, il est recommand d'utiliser la mthode log(String message) ou log(Exception e, String message) de l'interface ServletContext. La premire crit le message message dans le journal du serveur, la deuxime ajoute ce message la trace de la pile (le rsultat de e.printStackTrace()).
3.2.3 - La destruction
Pour certaines raisons, le moteur de servlets peut dcider s'il doit conserver ou non l'instance (ou les instances) de la Servlet au sein de la machine virtuelle. L'instance d'une Servlet peut tre dtruite quelques millisecondes aprs sa cration ou aprs l'arrt du moteur de Servlets. Rien ne peut contraindre le moteur de Servlets ne pas dtruire l'instance d'une Servlet. Une fois que le moteur de Servlets a dtermin qu'il n'est plus ncessaire de conserver une instance de la Servlet (par exemple quand le serveur doit librer de l'espace mmoire, ou lorsque l'excution du moteur de Servlets est arrte), il doit permettre la Servlet de librer les ressources qu'elle a acquises au cours de son excution (que ce soient les buffers utiliss pour l'criture en sortie, les fichiers lus et cris ou encore les objets instancis) et de sauvegarder ce qui doit tre persistant. C'est pour cela que le moteur de Servlets appelle la mthode destroy de l'interface Servlet, implmente par toutes vos Servlets (voir ecrire_premiere_servlet). Avant cela, tous les threads qui ont t crs au sein de la mthode service de la Servlet doivent soit tre termins, soit dpasser un temps dfini par le moteur de Servlets. Une fois la mthode destroy() appele, le moteur de Servlets ne doit plus router les requtes provenant des utilisateurs vers la Servlet concerne. Dans le cas o le moteur de servlets pense que l'instance de la servlet puisse tre utile nouveau, il doit crer une nouvelle instance de celle-ci et
http://java.developpez.com/cours/servlets/
poursuivre la destruction de la prcdente. Une fois que la fin du corps de la mthode destroy() est atteinte, le moteur de servlets doit dtruire l'instance de la servlet et rendre l'objet elligible par le ramasse-miettes de la machine virtuelle. Vous disposez maintenant d'une vue d'ensemble suffisante pour comprendre les diffrentes tapes que devront emprunter les servlets que vous programmerez. Je vais maintenant aborder un autre concept important qui influe sur le fonctionnement des servlets que vous programmerez au sein du moteur de servlets que vous utilisez : les contextes.
Dans le code source d'une servlet, un contexte est reprsent par un objet de type ServletContext qui peut tre obtenu par l'intermdiaire d'un objet de type ServletConfig, par exemple de la faon suivante :
public void init(ServletConfig config) { ServletContext contexte = config.getServletContext(); /* suite du code */ }
Grce ce contexte, il est possible d'accder chacune des ressources de l'application web
- 38 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
correspondant au contexte. Il faut noter qu' une application correspond un et un seul contexte, et qu' un contexte correspond une et une seule application. On peut donc en dduire que chaque contexte est propre une application et qu'il n'est pas possible de partager des ressources entre applications diffrentes. Par exemple la servlet ServletLogin de l'application de commerce en ligne ne peut pas accder aux instances de servlets de l'application de configuration du serveur web. Les ressources qu'il est possible de partager sont : des documents statiques. Vous pouvez accder n'importe quel document statique d'un contexte grce la mthode getRessource ou getRessourceAsStream.Le chemin pass en paramtre est interprt de faon relative la racine de l'application correspondant au contexte en cours. Cela rejoint ce que j'ai dis prcdemment : une servlet ne peut accder qu'aux ressources de l'application laquelle elle appartient quand elle utilise un contexte. des instances de servlets : en utilisant la mthode getServlet des paramtres d'initialisation pour toute l'application. En utilisant la mthode getInitParameter, il est possible de connatre la valeur d'un paramtre d'initialisation si on possde son nom. Pour connatre tous les paramtres d'initialisations dfinis, il faut utiliser la mthode getInitParameterNames. des attributs d'instance de servlets. Il est ainsi possible de partager des donnes au sein d'une mme application. Pour cela, utilisez les mthodes setAttribute et getAttribute, en fournissant chacune de ces mthodes le nom que devra avoir l'attribut au sein de l'application. Pour obtenir le nom de tous les attributs partags, vous devez utiliser la mthode getAttributeNames et pour retirer un attribut, il suffit d'utiliser la mthode removeAttribute.
Vous devriez maintenant comprendre ce qu'est un contexte. C'est une abstraction supplmentaire qui permet de matrialiser les relations privilgis que connaissent les modules d'une mme application et le fait que chaque application est diffrente. Je vais maintenant dcrire comment mettre en place plusieurs contextes diffrents avec le moteur de servlets Tomcat.
Toute cette arborescence peut tre regroupe dans une archive (compresse ou non) de la mme
http://java.developpez.com/cours/servlets/
manire qu'une application Java classique, en utilisant l'utilitaire jar (pour Java ARchive tool). De cette faon il n'y a plus qu'un seul fichier manipuler et votre application peut-tre signe, afin de la rendre digne de confiance auprs des gens qui utiliseront votre application web. En gnral, avant de procder l'archivage de l'arborescence de tout un contexte, il faut crer sa racine un rpertoire META-INF et y placer un fichier MANIFEST.MF contenant les informations ncessaires l'outil jar, afin qu'il puisse trouver tous les composants de l'application au moment voulu (lors d'une requte par exemple). Il est dit dans les spcifications des servlets que ce rpertoire ne doit pas tre mis disposition du client par le serveur Web qui transmet les requtes au moteur de servlets (ou par le moteur de servlets lui-mme s'il est utilis comme serveur web en mme temps). Le contenu de ce rpertoire ne sera donc pas visible de l'extrieur moins que vous en dcidiez autrement. Pour archiver une application, il suffit d'entrer la commande :
jar cfvm application.war META-INF/ MANIFEST.MF -C /usr/local/tomcat/webapps/appli/
ce qui produira le fichier application.war archivant l'application dont la racine est situe dans le rpertoire /usr/local/tomcat/webapps/appli/ et les informations sur l'archive contenues dans le fichier MANIFEST.MF situ dans le rpertoire META-INF de la racine de cette application. Vous savez maintenant que le fichier web.xml prsent dans $APP/WEB-INF/ (o $APP correspond au rpertoire de votre application web, par exemple /usr/local/tomcat/commerce) permet de spcifier les directives de configuration de l'application web. Voyons les concepts de base de la configuration d'une application web (et donc d'un contexte).
Les informations donnes par le fichier de configuration sont : les paramtres d'initialisation du contexte. la configuration de la session. les dfinitions des servlets et des JSPs. les correspondances entre servlets et entre JSPs. les correspondances entre types MIME. la liste des fichiers de bienvenue. les pages d'erreur. la scurit.
Je ne vais pas aborder tous ces aspects de la configuration, mais sachez qu'il est possible de rgler tous ces paramtres au sein d'un contexte. Je vous prsente maintenant la configuration d'un contexte de base correspondant notre application de configuration du serveur Web distance.
- 40 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
<webapp> <!-- nom de l'application --> <display-name> Application de configuration d'un serveur Web distance </display-name> <!-- paramtres disponibles dans le contexte de l'application --> <context-param> <param-name>Webmaster</param-name> <param-value>darktigrou@bigfoot.com</param-value> </context-param> <!-- dfinition de la servlet de login --> <servlet> <servlet-name>login</servlet-name> <servlet-class>ServletLogin.class</servlet-class> <!-- paramtres d'initialisation de la servlet --> <init-param> <pram-name>maxlogin</param-name> <param-value>1</param-value> </init-param> </servlet> <!-- fin de la dfinition de la servlet --> <!-- correspondance entre URLs et servlets appeles --> <servlet-mapping> <!-- toutes requte effectue vers une URL comprenant "/catalog/" est redirige vers la servlet login --> <servlet-name>login</servlet-name> <url-pattern>/login/*</url-pattern> </servlet-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> <mime-mapping> <extension>pdf</extension> http://java.developpez.com/cours/servlets/
<mime-type>application/pdf</mime-type> </mime-mapping> <!-- dfinition des fichiers utiliss par dfaut lors d'une requte concernant un URL ne spcifiant pas de fichier --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> </welcome-file-list> <!-- dfinition des pages d'erreur --> <error-page> <!-- pour une erreur de code HTTP 404, c'est le fichier 404.html prsent la racine du contexte qui est transmis au client --> <error-code>404</error-code> <location>/404.html</location> </error-page> <!-- fin de la configuration du contexte --> </web-app>
- 42 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
http://java.developpez.com/cours/servlets/
ne donnera pas la bonne information alors qu'apparemment tout est correct (mme si vous avez remarqu l'erreur, ce dont je ne doute pas, faites semblant ou imaginez un code source de quelques milliers de lignes), et ceci sans aucun message d'erreur ( moins que l'on utilise des options comme le module strict, mais ce n'est pas le comportement par dfaut). Par contre, dans une servlet :
- 44 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
int port_serveur = requete.getServerPrt(); out.println("Le serveur coute sur le port " + port_serveur + "\n");
ce code gnrera une erreur de compilation, et vous corrigerez alors l'erreur sans aucun dlai. Voici juste une illustration de ce que peut apporter le typage fort du langage Java par rapport d'autres. A chaque variable d'environnement disponible avec CGI correspond une mthode associe la requte pour obtenir des informations. Celles qui concernent le serveur sont : getServerName() : donne le nom du serveur, tel qu'il est donn dans la directive ServerName du fichier de configuration d'Apache (httpd.conf). getServletContext().getServerInfo() : retourne le nom du logiciel utilis pour prendre en charge la requte , par exemple Tomcat/3.2.1. getServletContext().getAttribute(String nom_attribut) : permet de rcuprer les diffrentes parties de l'information sur le logiciel serveur. Chaque moteur de servlets ou serveur Web possde ses propres noms d'attribut, les numrer tous ici serait inutile. Je vous conseille donc de vous reportez la documentation spcifique votre moteur de servlets pour connatre les noms de ces attributs et leur signification. getServerPort() : retourne le port sur lequel coute le serveur Web qui a pris en charge la requte. getRealPath(String nom_fichier) : retourne le chemin rel vers le fichier nom_fichier. En principe, ce chemin doit correspondre getRealPath("/") + nom_fichier. C'est assez utile lorsque vous dsirez effectuer des entres/sorties vers des fichiers prsents sur votre serveur. getPathTranslated() : cette mthode permet de connatre le chemin rel vers le fichier sur le systme de fichier du serveur lorsqu'un fichier est pass la servlet. Par exemple, pour une URL comme celle-ci : http://www.monserveur.com/mon_application/servlet/MaServlet/index.html, getPathTranslated() renverra la mme chose que getRealPath("/index.html").
Voici ci-dessous un programme classique affichant toutes les informations intressantes d'un serveur et quelques autres informations utilisant les mthodes que nous venons de voir :
import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class ServeurInfo extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOExcepption { res.setContentType("text/plain"); // on produit du texte ASCII PrintWriter out = res.getWriter(); out.println("Nom du serveur : " + req.getServerName() + " ."); out.println("Logiciel utilis : " + req.getServletContext().getServerInfo() + " ."); out.println("Port du serveur : " + req.getServerPort() + " ."); out.println("Port du serveur : " + req.getServerPort() + " .");
http://java.developpez.com/cours/servlets/
out.println("Chemin vers le fichier " + req.getPathInfo() + " : " + req.getPathTranslated(req.getPathInfo()) + " ."); } }
Une autre servlet se servant de ces mthodes pourrait servir retourner n'importe quel fichier pass en paramtre de la requte :
import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class FileServer extends HttpServlet { // on peut tre amen envoyer des fichiers binaires, donc on utilise // un ServletOutputStream au lieu d'un PrintWriter ServletOutputStream out = res.getOutputStream(); // rcupration d'une rfrence sur le fichier demand File fichier = new File(req.getPathTranslated(); if (fichier == null) // si le fichier est introuvable on envoie un code d'erreur 404 res.sendError(HttpServletResponse.SC_NOT_FOUND); // sinon le type de contenu de la rponse correspond au type MIME // du fichier res.setContentType(getServletContext().getMimeType(fichier)); try { // on utilise un tampon de 4 ko pour lire le fichier // ce qui est plus rapide qu'un lecture ligne par ligne char[] tampon = new char[4 * 1024]; FileInputStream in = new FileInputStream(fichier); while (in.read(tampon) >= 0) { out.write(tampon); } } catch (IOEXception e) { // si une erreur se produit au milieu de la rponse // on envoie le code d'erreur HTTP adquat - 46 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
Vous avez pris connaissance avec les principales mthodes permettant de connatre des informations relatives au serveur sur lequel tourne une servlet. Pour en savoir plus, je vous invite consulter les mthodes de l'API de J2EE contenues dans l'interface ServletResponse pour en connatre d'autres.
Ces requtes permettent d'identifier une machine sur le rseau Internet et de disposer ainsi d'une mthode d'authentification au niveau de la machine. Cependant, ces mthodes restent basiques et ne permettent pas de disposer d'un systme d'authentification robuste. Pour cela, il est ncessaire de mettre en place des systmes plus srs et fiables bass par exemple sur le protocole HTTPS par exemple, et qui peuvent se servir des mthodes sus-cites. Voici une servlet basique qui, en s'inspirant de la servlet qui sert les fichiers, met en place un mcanisme basique de contrle des accs :
import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class FileServer extends HttpServlet { private final static String fichierIP = "ip.txt"; private final static String fichierhotes = "hotes.txt";
http://java.developpez.com/cours/servlets/
public void doGet(Httpservletrequest req, Httpservletresponse res) throws ServletException, IOException { // on peut tre amen envoyer des fichiers binaires, donc on utilise // un ServletOutputStream au lieu d'un PrintWriter ServletOutputStream out = res.getOutputStream(); if (verifieIp(req.getRemoteAddr()) || verifieHote(req.getRemoteHost()) { // la machine cliente est autorise accder la servlet // rcupration d'une rfrence sur le fichier demand File fichier = new File(req.getPathTranslated(); if (file == null) // si le fichier est introuvable on envoie un code d'erreur 404 res.sendError(HttpServletResponse.SC_NOT_FOUND); // sinon le type de contenu de la rponse correspond au type MIME // du fichier res.setContentType(getServletContext().getMimeType(file)); try { // on utilise un tampon de 4 ko pour lire le fichier // ce qui est plus rapide qu'un lecture ligne par ligne char[] tampon = new char[4 * 1024]; FileInputStream in = new FileInputStream(file); while (in.read(tampon) >= 0) { out.write(tampon); } } catch (IOEXception e) { // si une erreur se produit au milieu de la rponse // on envoie le code d'erreur HTTP adquat res.sendError(HttpServletResponse.SC_PARTIAL_CONTENT); } finally { if (file != null) file.close(); }
} else { - 48 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
} public int verifieIP(String ipRequete) { File f = new File(fichierIP); FileInputStream in = new FileInputStream(f); String s; while ((s = in.readLine()) != null) { // l'ip du client est-elle autorise ? if (s.equals(ipRequete)) return 1; return 0; } } public int verifieHote(String hoteRequete) { File f = new File(fichierHotes); FileInputStream in = new fileInputStream(f); String s; while ((s = in.readLine()) != null) { // l'hote est-il autoris ? if (s.equals(hoteRequete)) return 1; return 0; } }
Gardez bien en tte que cette Servlet ne constitue en aucun cas un mcanisme de scurit valable. Elle illustre modestement l'emploi des mthodes relatives aux informations sur la machine cliente. En effet, toute vulnrabilit applicable au protocole IP est exploitable ici, comme le "spoofing".
http://java.developpez.com/cours/servlets/
Nous allons maintenant aborder l'analyse de la principale source d'information : la requte elle-mme. Plusieurs catgories d'informations sont importantes au niveau de la requte. Ces catgories correspondent aux diffrentes caractristiques d'une requte HTTP. Nous pouvons avoir besoin d'informations sur : l'URL sur lequel porte la requte. Par extension on peut obtenir l'URI, qui n'est qu'un concept plus abstrait que celui d'URL4.1. le schma utilis par la requte. Je considre que la mthode HTTP (GET, POST, etc.), le protocole utilis et sa version (HTTP/1.0, HTTP/1.1) et enfin l'entte (http://, https://, etc.) font partie de ce que j'appellerai le schma. les paramtres passs la requte. Ce sont les donnes envoyes par le client avec la requte qui peuvent servir prciser l'objet de la requte ou envoyer des donnes au serveur (dans le cas de l'envoi de fichier par exemple). l'entte de la requte : le client peut apporter diverses prcisions avec la requte, comme le format de donnes qu'il accepte, le logiciel du client (le nom du navigateur web par exemple) ou encore l'URL d'o provient la requte (si l'utilisateur a cliqu sur un lien pour effectuer la requte).
Pour obtenir l'URL de la requte, il est ncessaire d'utiliser la mthode getRequestURL() de la classe HttpUtils du package javax.servlet.http. Cette mthode reconstruit l'URL complte de la requte, sous une forme telle que http://www.monserveur.com/MaServlet par exemple. Cet URL est renvoy sous forme d'objet de type StringBuffer et est donc facilement modifiable. L'URL qui est retourn peut tre diffrent de celui entr dans le navigateur web du client car tout y est :le nom du serveur, le port, l'entte (http://), alors qu'un utilisateur ne prcise pas le port sur lequel tourne le serveur si celui ci coute sur le port 80 (ou sur d'autres ports selon la configuration des navigateurs). Les caractres spciaux prsents dans les paramtres de la requte (aprs le "?" par exemple pour une requte utilisant la mthode GET) peuvent aussi tre diffrents par rapport ceux prsents dans le champ de saisie de l'URL du navigateur : les "%20" seront par exemple remplacs par des espacements. Parfois cependant, il n'est pas ncessaire d'avoir des informations sur l'URL entier, mais seulement sur la partie concernant la ressource demande. Pour cela vous pouvez utiliser la mthode getRequestURI() de l'interface HttpServletRequest. Cette mthode retourne donc l'Uniform Ressource Identifier de la requte. Pour des requtes portant sur des ressources statiques (pages HTML par exemple), l'URI correspond exactement l'URL sans l'entte (http:// par exemple), le nom du serveur et le numro de port. Par exemple, pour l'URL suivant : http://www.monserveur.com/index.html, l'URI correspondant est /index.html. Pour des URLs rfrenant un contenu dynamique (des servlets par exemple), le procd de traduction entre URL et URI est parfois plus subtil. Voici une liste d'exemples qui vous permettra de mieux cerner ces subtilits : l'URL http://www.monserveur.com/MaServlet correspond l'URI /MaServlet. l'URL http://www.monserveur.com/MaServlet?param1=valeur1 correspond l'URI /MaServlet. l'URL http://www.monserveur.com/MaServlet/info_chemin?param1=valeur1 correspond l'URI /MaServlet/info_chemin. l'URL http://www.monserveur.com/index.html correspond l'URI /index.html.
Pour tre encore plus prcis, il est possible de connatre le chemin de la servlet correspondant un URL donn. Il suffit d'utiliser la mthode getServletPath() de l'interface HttpServletRequest. Cette mthode retourne sous la forme d'un objet de type String la partie de l'URL qui appelle la Servlet, ou la valeur null si l'URL ne fait pas rfrence une servlet. Lorsqu'une servlet fait partie d'une chane de servlets, la valeur renvoye par getServletPath() correspond celui qui aurait t renvoy par la
- 50 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
premire servlet de la chane (tant donn que ce n'est pas l'URL qui dcide quelles servlets doivent faire partie de la chane, et que cette URL ne connat donc que le premier maillon de cette chane). Voici une liste d'exemples qui illustre ce que je viens de dire : Si l'URL est http://www.monserveur.com/MaServlet, la mthode getServletPath() renvoie "/servlet/MaServlet". Si l'URL est http://www.monserveur.com/MaServlet?param=valeur, la mthode getServletPath() renvoie "/servlet/MaServlet". Si l'URL est http://www.monserveur.com/MaServlet/info_chemin?param=valeur, la mthode getServletPath() renvoie "/servlet/MaServlet". Si l'URL est http://www.monserveur.com/index.html, la mthode getServletPath() renvoie null. Si l'URL est http://www.monserveur.com/alias_servlet.html, la mthode getServletPath() /alias_servlet.html. Ici alias_servlet.html est un alias sur une servlet. C'est dire que l'on prcise au serveur web que toute requte demandant le document alias_servlet.html de la racine de son arborescence doit tre traduite en une requte vers la servlet associe.
Pour une Servlet invoque via SSI (voir section ssi), getServletPath() renvoie null si la servlet a t incluse dans un document statique, ou le chemin vers la premire servlet d'une chane si elle fait partie de cette chane de servlets. En ce qui concerne le schma utilis par la requte, il existe de nombreuses mthodes permettant d'obtenir des informations. La mthode getSheme() permet de rcuprer l'entte de la requte : par exemple "https" si le client a demand une connexion scurise. La mthode getProtocol() permet de rcuprer le protocole utilis par la requte (par exemple "HTTP/1.0"). La mthode getMethod() permet de connatre la mthode HTTP utilise. La valeur renvoye peut tre soit "GET", "POST" ou toute autre mthode HTTP (voir protocole_http). Les paramtres d'une requte sont compris dans celle-ci. Chaque paramtre possde un nom et une valeur. Les paramtres sont passs diffremment au serveur selon que la requte utilise la mthode HTTP GET ou POST. Dans le cas de l'utilisation de la mthode POST, les paramtres sont directement envoys au serveur comme des donnes classiques, et le serveur les rcupre sur son entre standard. Dans le cas o la requte utilise la mthode HTTP GET, les paramtres ainsi que leur valeur sont passs au serveur en ajoutant ces informations l'URL. Par exemple, pour passer un paramtre "nom " qui aura pour valeur "gilli" une servlet nomme MaServlet, l'URL correspondante sera : http://www.monserveur.com/servlet/MaServlet?nom=gilli . Chaque paire nom=valeur est spare par un "&" de la paire suivante. Pour passer deux paramtres nom et prnom, l'URL prendra la forme suivante (toujours si la requte utilise la mthode HTTP GET) :
http://www.monserveur.com/servlet/MaServlet?nom=gilli&prenom=julien
Afin de pouvoir coder les caractres comme l'espace ou le signe "%", ils sont remplacs par leur code hexadcimal correspondant, ou "+" pour l'espace. Il faut alors bnficier d'une mthode permettant d'assurer le dcodage de ces caractres spciaux pour recueillir des informations correctes. Ces paramtres peuvent tre rcuprs de plusieurs faons. Tout dpend de la connaissance que l'on peut avoir des paramtres passs. Dans une requte utilisant la mthode HTTP POST, l'utilisateur ne peut entrer " la main" des paramtres dont on ne pourrait connatre l'avance le nom et la valeur. Dans ce cas il n'est pas utile de pouvoir rcuprer le nom des paramtres passs la requte. Au contraire, pour une requte utilisant la mthode HTTP GET, les paramtres sont modifiables par le client puisque ajouts l'URL qui est visible dans le champ de saisie de l'adresse au niveau du
http://java.developpez.com/cours/servlets/
navigateur web. Il peut tre alors utile des rcuprer le nom de ces paramtres. Ceci est effectu par la mthode getParameterNames() de l'interface ServletRequest. Cette mthode renvoie un objet de type Enumeration que vous devriez savoir manipuler si vous satisfaites les connaissances requises (voir connaissances). Pour obtenir les valeurs de tous les paramtres, vous devez utiliser la mthode getParameterValues() qui renv oie un objet de type String[] contenant les valeurs de chaque paramtre. Enfin, la mthode getParameter(String nomParametre) permet de connatre la valeur du paramtre nomParametre reprsente par un objet de type String. Ci-dessous se trouve une servlet permettant d'afficher toutes les informations sur tous les paramtres de la requte :
import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.util.*; public class ServeurInfo extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOExcepption { res.setContentType("text/plain"); // on produit du texte ASCII PrintWriter out = res.getWriter(); Enumeration parametres = req.getParameterNames(); out.println("Affichage des informations sur les paramtres de la requte"); while (parametres.hasMoreElements()) { String nomParametre = (String) parametres.nextElement(); out.println("Le paramtre " + nomParametre + " a la valeur : " + getParameter(nomParametre) + " ."); } } }
Il faut noter qu'il existe une mthode permettant de rcuprer tous les paramtres passs la requte la fois, c'est dire toutes les paires paramtre=valeur sans dcodage des caractres spciaux pralable. Ceci n'est pas d'une utilit renversante mon got, et je ne pense pas que vous l'utiliserez beaucoup. Sachez cependant que c'est la mthode getQueryString() de l'interface HttpServletRequest qui peut vous rendre ce service. Toutes les autres mthodes vues au dessus dcode les paramtres pour vous avant de les renvoyer. Les enttes de la requte prcisant diverses choses comme : le logiciel utilis par le client. les types MIME des formats de donnes accepts.
- 52 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
le type d'authentification utilis dans le cas d'une connexion scurise. la date de dernire requte du client pour la ressource demande. le jeu de caractres utilis par le navigateur. la valeur du cookie associ au domaine auquel appartient la servlet demande. le langage utilis par le client.
Comme pour la rcupration des paramtres associs la requte, il existe plusieurs faons de rcuprer la valeur et le nom des en-ttes de requte. A chaque en-tte correspond une mthode distincte qui permet de rcuprer la valeur de cette entte en particulier. Ces mthodes sont mentionnes dans la liste ci-dessus. Ensuite il est possible de rcuprer une liste des noms des enttes passs par le client lors de la requte avec la mthode getHeaderNames() de l'interface HttpServletRequest. Cette mthode renvoie un objet de type Enumeration. Une fois le nom de tous les en-ttes rcuprs, il suffit de rcuprer la valeur de chaque entte avec la mthode getHeader(String nomEntete) de la mme interface pour obtenir toutes les en-ttes correspond une requte. La servlet suivante affiche toutes les en-ttes passes au serveur avec la requte :
import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.util.*; public class ServeurInfo extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOExcepption { res.setContentType("text/plain"); // on produit du texte ASCII PrintWriter out = res.getWriter(); out.println("Affichage des informations sur les en-ttes de la requte"); Enumeration entetes = req.getHeaderNames(); while (entetes.hasMoreElements()) { String nomEntete = (String) entetes.nextElement(); out.println("a l'entte " + nomEntete + " correspond la valeur " + getHeader(nomEntete) + "."); } } }
Le rsultat est diffrent pour la mme requte avec des navigateurs diffrents, car de nombreuses en-ttes dpendent du navigateur, comme "User-Agent" ou "Accept". Cette dernire dfinit le type de fichiers accepts par un navigateur. Certaines des valeurs d'en-ttes peuvent tre mieux traites en tant rcupres comme un entier ou
http://java.developpez.com/cours/servlets/
un objet de type Date. Les mthodes getIntHeader() et getDateHeader() servent respectivement cela. Si le format de l'en-tte ne correspond pas au type retourn par l'une de ces mthodes, une IllegalNumberException sera gnre pour getIntHeader et une IllegalArgumentException sera gnre pour la mthode getDateHeader() Le langage utilis par le client (correspondant l'en-tte "Accept-Language") est disponible via la mthode getLocale() de l'interface ServletRequest. La mthode getLocales() de la mme interface permet de rcuprer dans l'ordre dcroissant de prfrence les langages accepts. Ces informations peuvent tre utilise si vous grez des servlets internationalises. Pour plus d'informations ce sujet, consultez la section "internationalisation" du tutoriel Java l'URL suivants : http://java.sun.com/docs/books/tutorial/i18n/index.html. En ce qui concerne les connexions dites "scurises", il est possible d'en connatre plus grce la mthode isSecure() de l'interface ServletRequest qui renvoie un boolen prcisant si la requte a t fate en utilisant un canal scuris ou non (comme le protocole HTTPS qui utilise la mthode de cryptage SSL, qui signifie Secure Socket Layer). La mthode utilise pour tablir une connexion scurise est obtenue par la mthode getAuthType() de la mme interface. Cette mthode retourne un objet de type String qui peut prendre des valeurs comme "BASIC" lorsque les fonctionnalits d'identification du serveur web sont utilises ou "SSL" par exemple. Pour plus de renseignements propos de la scurisation des accs HTTP au niveau utilisateur, vous pouvez consulter le document disponible l'URL http://www.apacheweek.com/features/userauth. En ce qui concerne la mise en place du protocole SSL, je vous conseille de consulter le document accessible l'URL http://www.apacheweek.com/features/ssl. Il existe galement des attributs spciaux qui peuvent tre mis en place par le moteur de servlets lui mme en plus des attributs dont vous pouvez rcuprer le nom avec la mthode getHeaderNames() vue juste au-dessus. Chaque moteur de servlets peut dcider de mettre en place des attributs spciaux, mais ce n'est pas obligatoire. Ils sont accessibles via la mthode getAttributeName(String nomParametre) de l'interface ServletRequest, qui ressemble la mthode du mme nom de l'interface ServletContext. Le serveur Java Web Server dfinit par exemple trois attributs supplmentaires qui ont pour nom javax.net.ssl.cipher_suite, javax.net.ssl.peer-certificates et javax.net.ssl.session. Ils permettent de rcuprer des informations sur une requte scurise utilisant le protocole HTTPS (et donc SSL). Cette mthode permet galement de partager des donnes au sein du mme contexte (voir contextes). Une seule valeur peut tre associe un seul nom d'attribut. Il est recommand que les noms d'attributs suivent une conve ntion similaire aux packages du JDK (voir la spcification du langage Java l'URL http://java.sun.com/docs/books/jls pour plus de renseignements). Enfin, nous terminerons cette section concernant la requte en dcrivant comment traiter celles qui permettent d'envoyer des donnes brutes au serveur. Je vous ai dit prcdemment que les requtes de type HTTP POST taient passes au serveur web par son flux d'entre standard (plus communment appel STDIN, pour STanDard INput). Ce flux d'entre peut tre utile pour d'autres choses : chaner plusieurs servlets en associant le flux de sortie standard d'une servlet au flux d'entre standard d'une autre, passer une servlet non HTTP des donnes brutes. Par "donnes brutes", il faut comprendre donnes binaires comme des fichiers graphiques au format jpeg par exemple. Pour traiter ce flux il est ncessaire de connatre le type de contenu transmis et la longueur du flux. pour connatre le type MIME du flux disponible sur l'entre standard, il faut utiliser la mthode getContentType() de l'interface ServletRequest. Cette mthode renvoie un objet de type String qui correspond un type MIME, comme par exemple ``"t ext/html" ou "image/png". Pour connatre la longueur des donnes passes l'entre standard, il suffit d'employer la mthode getContentLength() de la mme interface, qui retourne un entier correspondant la longueur des donnes en entre.
- 54 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
Vous devriez maintenant tre en mesure de traiter n'importe quel type de requte. Il faut maintenant ragir cette requte en envoyant une rponse. Nous tudierons tout d'abord les moyens mis notre disposition pour mettre une rponse conforme aux caractristiques d'une rponse HTTP, et nous verrons ensuite les diffrentes faons de produire du contenu HTML et multimdia (images, animations).
4.2 - La rponse
Comme nous l'avons vu en protocole_http, la rponse est organise en plusieurs sections. Les mthodes de l'interface ServletResponse (et donc de HttpServletResponse puisqu'elle drive de la prcdente) permettent de contrler chacune des ces sections. En ce qui concerne le code d'tat, l'interface HttpservleResponse possde un nombre assez impressionnant d'attribut de classes (statiques) de type entier reprsentant chacun un code d'tat. Afin de transmettre la bonne en-tte, il suffit donc d'utiliser la mthode setStatus(int etat) en passant comme paramtre un des attributs statique de l'interface. Par exemple, pour notre servlet qui permet de servir des fichiers, nous aurions pu utiliser l'instruction setStatus(HttpServletRequest.SC_NOT_FOUND) dans le cas d'un fichier introuvable. Le code d'tat HttpServletRequest.SC_NOT_FOUND correspond au code d'tat HTTP 404. Vous pourrez trouver tout l'inventaire des attributs de l'interface HttpServletRequest avec leur code d'tat HTTP correspondant dans la documentation de l'API des servlets disponible http://java.sun.com/j2ee/j2sdkee/techdocs/api/index.html.
permet de signaler au client web que le contenu produit est du texte au format HTML. Un autre exemple d'en-tte est "Location", qui permet de rediriger l'utilisateur. Il est possible de prciser cette en-tte grce la mthode setHeader(String name, String valeurEntete) de l'interface HttpServletResponse. Cette mthode correspond l'accesseur en lecture des en-ttes de requte venant du client : la mthode getHeader(String name). Il est possible de spcifier chaque en-tte HTTP via cette mthode, il suffit juste de connatre le nom de l'entte. Pour cela, je vous invite consulter DOCUMENT REFERENCE HTTP. Comme pour la mthode getHeader(String name), il est possible de spcifier la valeur d'une en-tte avec un autre type de donnes que la classe String. Pour cela il suffit d'utiliser les paramtres de type long ou entier des autres mthodes setHeader(). Pour
http://java.developpez.com/cours/servlets/
connatre toutes les versions de la mthode setHeader possibles, reportez vous la documentation de rfrence de l'API des servlets, disponible http://java.sun.com/j2ee/j2sdkee/techdocs/api/index.html. Afin de ne pas devoir se rappeler de la signification des codes d'tats et de leurs en-ttes correspondantes, quelques mthodes sont disponibles et permettent l'envoi de ces deux informations la fois. Par exemple la mthode sendRedirect(String nouvelleUrl) permet d'effectuer le mme traitement que les deux instructions :
res.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); res.setHeader("Location", "http://www.monserveur.com/autreUrl.html");
Je vous invite consulter la documentation de rfrence sur l'API des servlets disponible ici http://java.sun.com/j2ee/j2sdkee/techdocs/api/index.html pour connatre les autres mthodes de ce type (comme sendError). Quelques conventions sont respecter pour utiliser les en-ttes correctement. Tout d'abord, vous ne pouvez pas avoir deux valeurs diffrentes pour la mme en-tte. C'est pour cela qu'un autre appel la mthode setHeader concernant le mme nom d'en-tte crasera l'ancienne valeur. Ensuite vous devez absolument envoyer les en-ttes avant le corps de la rponse, c'est dire que l'instruction
out.println("envoi de donnes");
suivie de l'instruction
res.setHeader("Location", "http://www.monserveur.com/bidule.html");
n'est pas correct. Il n'est pas certain que cette incorrection gnre une erreur. Cela dpend du moteur de servlets qui fait tourner votre servlet. Par exemple le Java Web Server possde un tampon qui stocke une petite quantit de donnes (quatre kilo octets) avant de les envoyer. Cela vous laisse un peu de temps pour envoyer les en-ttes. Enfin, il vaut mieux dfinir le type de contenu envoyer avent d'obtenir le flux de sortie (dont je parle un peu plus tard), ceci afin d'obtenir un flux de sortie correctement configur en fonction du type de contenu envoyer, sans avoir effectuer aucune manipulation. Vous pouvez maintenant produire une en-tte de rponse conforme au protocole HTTP de faon ce que tous les navigateurs comprennent les donnes que vous fournissez. Voyons maintenant le corps de la rponse.
- 56 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
caractres, destin tre lu et supportant l'internationalisation. Le deuxime type est conu pour crire des donnes au format binaire. Si vous appelez tentez d'obtenir un flux de type ServletOutputStream aprs avoir obtenu un flux de type PrintWriter ou inversement, une exception de type IllegalStateException sera gnre. Pour envoyer du contenu au client, il suffit alors d'utiliser les mthodes disponibles selon le flux choisi, par exemple la mthode println(String contenu) pour un flux de type PrintWriter ou ServletOutputStream. Il faut savoir que la sortie peut tre gre de deux manires : tamponne ou directe. Une sortie tamponne permet d'accrotre les performances d'criture sur le flux de sortie. Par contre, les besoins en mmoire vive peuvent s'accrotre car une plus grosse quantit de donnes est garde en mmoire plus longtemps, et les servlets ne fournissant qu'une ressource (par exemple un seul fichier HTML sans image) trs grand (la connexion dure longtemps) ne bnficierait pas de cette mthode. La mthode directe quand elle envoie les donnes au fur et mesure qu'elles sont gnres ( chaque retour la ligne). Aucun moteur de servlets n'est tenu de fournir un mcanisme de tampon, vous devrez donc consulter la documentation du moteur de servlets que vous utilisez pour savoir s'il est possible d'utiliser un tel mcanisme. Pour obtenir des informations sur la sortie tamponne, plusieurs mthodes existent : getBufferSize() : fournit la taille du tampon utilis actuellement pour l'criture. setBufferSize(int tailleTampon) : ajuste la taille du tampon tailleTampon. Le moteur de servlets dfinit alors un tampon au moins gal la taille donne. Le fait de disposer d'un peu de libert pour dfinir la taille relle du tampon permet au moteur de servlets de rutiliser un ventuel tampon dont la taille serait suprieure ou gale la taille demande. Outre l'acclration des performances en criture, une taille de tampon suprieure zro permet la mise en place des en-ttes un peu aprs l'envoi des premires donnes. Cette mthode doit tre appele avant l'envoi des premires donnes (les en-ttes et le code d'tat font partie des donnes ici). isComitted() : permet de savoir si des donnes ont dj t envoye au client. Vous pouvez encore spcifier le code d'tat et les en-ttes de la rponse si cette mthode renvoie faux. reset() : efface toutes les donnes prsentes dans le tampon si aucun lment de la rponse n'a t encore envoy. Les en-ttes seront aussi effaces, vous devrez donc en spcifier de nouvelles (mais qui peuvent tre identique). Si vous appelez cette mthode alors que des lments de la rponse ont t envoy, une exception du type IllegalStateException est gnre. flushBuffer() : permet de forcer l'envoi des donnes lorsque le tampon n'est pas encore plein. Aprs l'appel de cette mthode, le code d'tat et l'en-tte HTTP ont t communiques au client et un appel la mthode isCommitted() renverra la valeur "faux".
Comme tout tampon utilis en programmation, lorsqu'il est plein, les donnes prsentes dans ce dernier sont envoyes sur la sortie, et la mthode isComitted() renverra la valeur "vrai" partir de ce moment. Les donnes sont envoyes au travers d'une connexion tablie entre le client (navigateur web) et le serveur. Or vous savez que tout navigateur est dot d'un bouton "stop" qui arrte le chargement de la page web demande. Que se passe-t-il ce moment l ?
http://java.developpez.com/cours/servlets/
La connexion est alors coupe et le flux ouvert en sortie par la servlet vers le naviagetur n'est plus valide. Deux cas sont possible : Vous utilisez un flux de type PrintWriter. Vous utilisez un flux de type ServletOutputStream.
Dans le premier cas, l'criture sur un flux non valide ne gnre aucune exception. Pour savoir si le flux est toujours valide, vous devrez utiliser la mthode checkError() de la classe PrintWriter. Cette mthode retourne le boolen true si le flux de sortie n'est plus valable. Dans le deuxime cas, l'criture sur un flux non valide gnre une exception de type IOException. Il suffit donc d'utiliser un bloc try { } catch (IOException e) { } pour grer le problme. Il est important d'utiliser ces mcanismes de contrle lorsque des tratitements coteux en temps processeur peuvent tre lancs par votre servlet. Un test avant le dbut d'un tel traitement permet d'viter un gaspillage dans le cas o l'utilisateur aurait press le bouton "stop".
- 58 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html");
// cration du tampon contenant les donnes envoyer // ce tampon s'tend au fur et mesure que des donnes y // sont crites ByteArrayOutputStream tampon = new ByteArrayOutputStream(); // cration du flux d'crire de texte sans vidage automatique // du tampon utilis PrintWriter out = new PrintWriter(tampon); out.println("Ceci est une servlet utilisant une connexion persistante."); // rcupration de la taille du tampon // afin de dterminer la valeur de l'en-tte // Content-length res.setContentLength(tampon.size()); // envoi des donnes tampon.writeTo(res.getOutputStream()); } }
Vous connaissez dsormais les mcanismes fondamentaux qui grent la diffusion du contenu vers un client utilisant le protocole HTTP. Nous n'avons cependant pas considr la forme du contenu. tant donn que des pages web peuvent vite devenir consquentes et que leur esthtique est importante, nous allons voir deux choses diffrentes. Tout d'abord vous tudierez les diffrentes faons de produire du code HTML, et ensuite les possibilits d'intgration de contenu multimdia (images, sons, animations).
http://java.developpez.com/cours/servlets/
Il existe plusieurs manires d'envoyer du code HTML vers un client utilisant le protocole HTTP. Nous en verrons trois d'entre elles, qui me semblent couvrir les bases reprises par d'ventuelles mthodes diffrentes. Comme vous le verrez, le choix de ces mthodes dpend essentiellement de la quantit de contenu fournir, de la structure de votre document et du service fourni par celui-ci. En effet, si tous les documents d'un site possdent la mme forme, il sera intressant de "factoriser" le code HTML en utilisant des modles.Par contre si le site web contient un code HTML trs simple il sera plus simple et rapide d'utiliser des fonctionalits basiques. Nous avons dej vu, tout au long du document, la cration d'un contenu HTML classique. Il suffit pour cela d'utiliser un flux de type PrintWriter et de spcifier l'en-tte "Content-type" adquate comme ceci :
res.setContentType("text/html");
Les donnes au format HTML sont alors passes la mthode println de classe PrintWriter comme des chanes de caractres classiques de la manire suivante :
out.println("<b>voici une phrase en police grasse.</b>");
Il n'apparat aucune limitation particulire sur cet exemple prcis, mais il faut songer l'utilisation de cette mthode pour produire un contenu complexe. Cela devient trs rapidement pnible pour plusieurs raisons : le code source de la servlet devient trs vite norme. la majeure partie de ce contenu est statique (pas gnr par un algorithme). les erreurs sont frquentes (oubli de fermeture d'une balise par exemple). on utilise pas la programmation oriente objet.
Pour remdier cela, nous allons tudier deux alternatives : la gnration HTML oriente objet et le systme de templates (ou modles). Ces deux techniques ne font pas partie de l'API des servlets et ne sont donc pas fournies par l'ensemble de classes que vous avez tlcharg lors de l'installation de Tomcat (voir installation_tomcat). Outre le fait que vous devrez les tlcharger, il vous sera srement ncessaire de vous re-habituer un mode de fonctionnement particulier cet ensemble de classes et sa documentation. tant donn que je ne ferais qu'aborder le sujet il vous sera probablement utile de fournir quelques efforts supplmentaires pour vous familiariser avec ces techniques, en lisant la documentation par exemple. La premire technique que nous alons tudier est la gnration HTML oriente objet. Les classes que j'utilise dans les exemples qui suivent sont tlchargeables l'URL http://www.weblogic.com/.Une fois ces classes tlcharges, il suffit d'ajouter leur chemin dans la variable environnement CLASSPATH comme ceci :
export CLASSPATH=$CLASSPATH:/chemin/vers/les/classes/leJar.jar
Cette instruction permet de pouvoir compiler et lancer les exemples. Appuyons nous sur un exemple pour dmarrer :
import javax.servlet.*; import javax.servlet.http.*;
- 60 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
public class BonjourMondeObjet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); ServletPage page = new ServletPage(); page.getHead().addElement(new TitleElement("Bonjour, monde !")); page.getBody().addElement(new BigElement("Bonjour monde !"));
page.output(res.getOuputStream()); } }
Compilez et effectuez une requte sur cette servlet et un message clbre apparatra. Vous pouvez dj vous apercevoir que plus aucune balise HTML n'est utilise. Cela vite dj les nombreuses erreurs d'critures qui peuvent tre rencontres lorsque l'on manipule directement ces balises. Les seules erreurs qu'il est possible de commettre au niveau de la structure HTML du document seront maintenant signale la compilation (nom de mthode inexistant par exemple), ce qui vite des sances fastidieuses de recherche d'erreur. Ensuite, on voit clairement que nous utilisons la programmation oriente objet. En effet, un objet de type ServletPage est cr et la production du code HTML se fait, en l'occurrence, par les deux instructions suivantes :
page.getHead().addElement(new TitleElement("Bonjour, monde !")); page.getBody().addElement(new BigElement("Bonjour monde !"));
La mthode getHead() de la classe ServletPage retourne une rfrence sur un objet dcrivant l'en-tte de la page HTML. Il est possible d'appeler d'autres mthodes sur cet objet, comme addElement. Cette mthode, comme vous pouviez vous en douter, ajoute un lment l'en-tte. Ici c'est un lment dcrivant le titre qui est ajout, mais on aurait pu ajouter d'autres lments appartenant d'autres types. L'utilisation d'une gnration oriente objet permet de changer les proprits de tout le code HTML gnr par toutes vos pages en changeant seulement des informations au niveau de l'objet utilis. Ainsi, il suffit de modifier la classe TitleElement pour en modifier la mise en forme. C'est un peu le mme principe que les feuilles de styles4.2 qui permettent de sparer le contenu de la forme. Les servlets produisant beaucoup de code HTML et utilisant cette mthode sont donc plus lisibles et faciles maintenir. Il est galement possible de rajouter ses propres types en crant des sous classes ou de nouvelles classes. Rien ne vous empche de crer vos propres classes de bases utilises par chacun de vos sites, puis pour chacun d'eux, crer des sous classes spcialises. Je vous laisse dcouvrir par vous mme cette mthode dans le chemin emprunt peut-tre diffrent selon les besoins. Cela dit vous ne devriez prouver aucune difficult, en
http://java.developpez.com/cours/servlets/
sachant que vous devez bien connatre la programmation oriente objet. Vous la connaissez n'est-ce pas ? Malgr l'utilisation de cette mthode intressante, comment peut on viter de voir prolifrer le contenu statique au sein d'une servlet, et comment permettre aux graphistes de votre site web de travailler en toute indpendance des programmeurs ? Une solution envisageable est l'utilisation de templates. Le mot "template" signifie "modle". En effet, de nombreux sites web utilisent un contenu dynamique qui suit des rgles prcises. En utilisant un systme de modles, il suffit simplement de prciser quelle partie du code HTML est dynamique, et de gnrer le contenu correspondant ces petites parties par vos servlets. Tout le reste de la page est statique et extrait par le moteur de modles partir du fichier HTML. Un moteur de modles est un ensemble de classe qui prend en charge la liaison entre les marqueurs dfinis dans les pages HTML pour distinguer le contenu dynamique du contenu statique et votre servlet. Puisque l'on parle de moteur de modles, il faut savoir qu'il en existe plusieurs. Chaque mote ur propose ses propres possibilits et sa manire de les implmenter. C'est vous de choisir celui qui vous correspond le mieux. Les principaux moteurs de modles sont : Enhydra : disponible http://www.enhydra.org/. Webmacro : disponible http://www.webmacro.org/. Freemarker : disponible http://freemarker.sourceforge.net/.
tous ces moteurs sont des logiciels libres, vous pouvez donc vous les procurer gratuitement, bnficier de nombreuses amliorations rapidement et participer au dveloppement. Voici ci dessous un exemple simple d'une servlet utilisant un modle pour produire le contenu. Cet exemple est programm avec le moteur de modles Enhydra :
<html> <body> <span id="MonTitre">Categorie Vide</span> <p> <span i="MaLigne"> <a id="MonUrl" href="#">Contenu Categorie</a></span> </p> </body> </html>
- 62 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
// instancier la page MaPageHTML p = new MaPageHTML(); // remplir le titre p.setTextMonTitre(cat.isEmpty()?"":cat.getName()); // retrouver les elements Element ligne = p.getElementMaLigne(); Element paragraph = ligne.getParentNode(); Element url = p.getElementMonUrl(); // retirer la ligne template et ajouter les lignes reelles paragraph.removeChild(ligne); for (int i=0; i < cat.size(); i++) { // changer le lien url.setHRef(encodeURL("/servlet/JTus?p=1&ca="+cat.refCateg)); // changer le texte url.removeChild(url.getFirstChild()); url.appendChild(p.createTextNode(cat.Nom)); // dupliquer et ajouter la ligne Node clonedNode = ligne.cloneNode(true); paragraph.appendChild(ligne); } // retourner la page au client response.setContentType("text/html"); java.io.PrintWriter writer = response.getWriter(); writer.print(p.toDocument()); writer.flush(); } }
On peut voir galement que pour une gestion des modles de base, l'utilisation d'un moteur de modles peut tre trop lourd utiliser. Pensez simplement que vous pouvez trs bien programmer vos classes reprsentant par exemple un pied de page standard. Cette classe contiendrait une mthode ecrireContenu(PrintWriter sortie) qui crirait son contenu sur le flux de sortie de la servlet. Vous pourriez alors crer autant de pied de pages spcifiques en drivant cette classe de base, tout en conservant la mme forme pour tous les
http://java.developpez.com/cours/servlets/
pieds de page du mm"e type utiliss dans vos pages web. En utilisant des conventions de nommage (pour vos mthodes et attributs) simples et en les respectant scrupuleusement, vous pourriez arriver disposer d'un systme de modles simple, utile et moins lourd que les tnors du genre. Maintenant que nous savons gnrer du contenu HTML, voyons ce qui est mis notre disposition pour gnrer un contenu multimdia.
- 64 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
import java.io.*; public class ImageServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // le contenu produit est une image au format jpeg res.setContentType("image/jpeg"); ServletOutputStream out = res.getOutputStream(); // l'objet enc va encoder les donnes et les envoyer sur // le flux de sortie de type ServletOutputStream JPEGImageEncoder enc = JPEGCodec.createJPEGEncoder(out); // cration d'une nouvelle image dune rolution de 1024 par // 768 BufferedImage image = new BufferedImage(1024,768,BufferedImage.TYPE_BYTE_INDEXED); // rcupration du contexte graphique li l'image Graphics2D g = image.createGraphics(); // la prochaine opration s'effectuera avec la couleur rouge g.setColor(Color.red); // affichage de la clbre phrase g.drawString("Bonjour monde !", 400, 500); // transformation des donnes au format jpeg et envoi // de celles-ci sur le flux standard de sortie (le navigateur) enc.encode(image); } }
Faites cependant attention un problme relativement difficile dceler. Une machine sous Unix, lorsqu'elle fournit des services au sein d'un rseau (comme un moteur de servlet par exemple) ne lance pas un environement graphique. Or, lorsque nous dcidons de crer une image, des classes du paquetage java.awt sont charges et des objets de type Image dcrivant les images afficher sont crs. C'est pour cela que vous rencontrerez une erreur si la machine sur laquelle tourne le moteur de servlets ne dispose pas d'un environement graphique et n'ajuste pas sa variable d'environement DISPLAY. Vous devez galement vous assurer que l'utilisateur sous lequel tourne le processus de la JVM est autoris utiliser le "display". Lisez la documentation sur la commande xhost en entrant
man xhost
http://java.developpez.com/cours/servlets/
- 66 Copyright (c) 2001 Gilli Julien. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being ``Document original produit par le projet JWebadmin (http://www.sourceforge.net/project/jwebadmin/)'', and with no Back-over Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
5 - Le mot de la fin
Voil, c'est dej termin pour cette version du document. Vous tes bien sr encourag le critiquer, contribuer son dveloppement et me faire part de toutes sortes de ractions. Pour favoriser cela et dbuter un projet destin crer un ensemble de documents a usujet des servlets, le projet jwebadmin a t cr. Vous pouvez y participer en me contactant darktigrou@bigfoot.com ou en vistant le site web http://sourceforge.net/projects/jwebadmin/. L'ensemble de documents sera constitu d'une documentation crite (qui sera une version plus complte de cette documentation) et d'une application d'administration de serveur web distance. Les prochaines versions de ce document aborderont les thmes suivants : La communication entre les applets et les servlets. La gestion des sessions. La scurit.
Les thmes abords actuellement seront tendus et corrigs et plus d'exemples seront mis disposition. Il serait aussi agrable de disposer d'un systme d'annotation, pour permettre aux lecteurs de complter les informations donnes par ce document. Je vous remercie d'avoir t attentif jusqu'au bout de cet apprentissage.
http://java.developpez.com/cours/servlets/