Version en ligne

Tutoriel : Créez votre application web avec Java EE

Table des matières

Créez votre application web avec Java EE
Introduction au Java EE
Pour commencer
Qu'est-ce que Java EE ?
Internet n'est pas le web !
Comment ça marche
Les langages du web
Le Java EE mis à nu !
Principes de fonctionnement
Le modèle MVC : en théorie
Le modèle MVC : en pratique
Outils et environnement de développement
L'IDE Eclipse
Le serveur Tomcat
Structure d'une application Java EE
La servlet
Derrière les rideaux
Création
Mise en place
Mise en service
Servlet avec vue…
Introduction aux JSP
Mise en place d'une JSP
Mise en relation avec notre servlet
Transmission de données
Données issues du serveur : les attributs
Données issues du client : les paramètres
Le JavaBean
Objectifs
Structure
Mise en place
La technologie JSP (1/2)
Les balises
Les directives
La portée des objets
Les actions standard
La technologie JSP (2/2)
Expression Language
Les objets implicites
Des problèmes de vue ?
Nettoyons notre exemple
Complétons notre exemple...
Le point sur ce qu'il nous manque
Documentation
TP Fil rouge - Étape 1
Objectifs
Conseils
Correction
Objectifs et configuration
C'est sa raison d'être…
Configuration
La bibliothèque Core
Les variables et expressions
Les conditions
Les boucles
Les liens
Les autres bibliothèques de la JSTL
JSTL core : exercice d'application
Les bases de l'exercice
Correction
La bibliothèque xml
La syntaxe XPath
Les actions de base
Les conditions
Les boucles
Les transformations
JSTL xml : exercice d'application
Les bases de l'exercice
Correction
Faisons le point !
Reprenons notre exemple
Quelques conseils
Documentation
TP Fil rouge - Étape 2
Objectifs
Conseils
Correction
Formulaires : le b.a.-ba
Mise en place
Contrôle : côté servlet
Affichage : côté JSP
Formulaires : à la mode MVC
Analyse de notre conception
Création du modèle
Reprise de la servlet
Reprise de la JSP
TP Fil rouge - Étape 3
Objectifs
Conseils
Correction
La session : connectez vos clients
Le formulaire
Le principe de la session
Le modèle
La servlet
Les vérifications
Derrière les rideaux
Le filtre : créez un espace membre
Restreindre l'accès à une page
Le principe du filtre
Restreindre l'accès à un ensemble de pages
Retour sur l'encodage UTF-8
Le cookie : le navigateur vous ouvre ses portes
Le principe du cookie
Souvenez-vous de vos clients !
À propos de la sécurité
TP Fil rouge - Étape 4
Objectifs
Conseils
Correction
Formulaires : l'envoi de fichiers
Création du formulaire
Récupération des données
Enregistrement du fichier
Problèmes et limites
Intégration dans MVC
Le téléchargement de fichiers
Une servlet dédiée
Une solution plus simple
L'état d'un téléchargement
Réaliser des statistiques
TP Fil rouge - Étape 5
Objectifs
Conseils
Correction
Introduction à MySQL et JDBC
Présentation des bases de données
Préparation de la base avec MySQL
Mise en place de JDBC dans le projet
Création d'un bac à sable
Communiquez avec votre BDD
Chargement du driver
Connexion à la base, création et exécution d'une requête
Mise en pratique
Les limites du système
Les requêtes préparées
Le modèle DAO
Objectifs
Principe
Création
Intégration
Vérifications
TP Fil rouge - Étape 6
Objectifs
Conseils
Correction
Gérer un pool de connexions avec BoneCP
Contexte
Principe
Mise en place
Les annotations
Présentation
Principe
Avec l'API Servlet 3.0
La persistance des données avec JPA
Généralités
Principe
Mise en place
Tests et vérifications
Aller plus loin
ORM, ou ne pas ORM ?
TP Fil rouge - Étape 7
Objectifs
Conseils
Correction
Introduction aux frameworks MVC
Généralités
Framework MVC basé sur les requêtes
Framework MVC basé sur les composants
Premiers pas avec JSF
Qu'est-ce que JSF ?
Facelets et composants
Premier projet
Les ressources
JSF, ou ne pas JSF ?
La gestion d'un formulaire avec JSF
Une inscription classique
Une inscription ajaxisée
Une inscription contrôlée
L'envoi de fichiers avec JSF
Le problème
Les bibliothèques de composants
L'envoi de fichier avec Tomahawk
Et plus si affinités...
Débugger un projet
Les fichiers de logs
Le mode debug d'Eclipse
Quelques outils de tests
Empaquetage et déploiement d'un projet
Mise en boîte du projet
Déploiement du projet

Créez votre application web avec Java EE

La création d'applications web avec Java EE semble compliquée à beaucoup de débutants. Une énorme nébuleuse de sigles en tout genre gravite autour de la plate-forme, un nombre conséquent de technologies et d'approches différentes existent : servlet, JSP, Javabean, MVC, JDBC, JNDI, EJB, JPA, JMS, JSF, Struts, Spring, Tomcat, Glassfish, JBoss, WebSphere, WebLogic... La liste n'en finit pas, et pour un novice ne pas étouffer sous une telle avalanche est bien souvent mission impossible !

Soyons honnêtes, ce tutoriel ne vous expliquera pas le fonctionnement et l'utilisation de toutes ces technologies. Car ça aussi, c'est mission impossible ! Il faudrait autant de tutos...

Non, ce cours a pour objectif de guider vos premiers pas dans l'univers Java EE : après quelques explications sur les concepts généraux et les bonnes pratiques en vigueur, vous allez entrer dans le vif du sujet et découvrir comment créer un projet web, en y ajoutant de la complexité au fur et à mesure que le cours avancera. À la fin du cours, vous serez capables de créer une application web qui respecte les standards reconnus dans le domaine et vous disposerez des bases nécessaires pour utiliser la plupart des technologies se basant sur Java EE.

Comment lire ce cours ?
Un contenu conséquent est prévu, mais je ne vais volontairement pas être exhaustif : les technologies abordées sont très vastes, et l'objectif du cours est de vous apprendre à créer une application. Si je vous réécrivais la documentation de la plate-forme Java EE en français, ça serait tout simplement imbuvable. Je vais ainsi fortement insister sur des points non documentés et des pratiques que je juge importantes, et être plus expéditif sur certains points, pour lesquels je me contenterai de vous présenter les bases et de vous renvoyer vers les documentations et sources officielles pour plus d'informations. Je vous invite donc à ne pas vous limiter à la seule lecture de ce cours, et à parcourir chacun des liens que j'ai mis en place tout au long des chapitres.

Enfin, avant d'attaquer sachez que ce cours ne part pas totalement de zéro : il vous faut des bases en Java afin de ne pas vous sentir largués dès les premiers chapitres. Ainsi, si vous n'êtes pas encore familier avec le langage, vous pouvez lire les parties 1 et 2 du tutoriel sur le Java du Site du Zéro. ;)

Introduction au Java EE

Pour commencer

Avant de nous plonger dans l'univers Java EE, commençons par faire une mise au point sur ce que vous devez connaître avant d'attaquer ce cours, et penchons-nous un instant sur ce qu'est le web, et sur ce qu'il n'est pas. Simples rappels pour certains d'entre vous, découverte pour d'autres, nous allons ici expliquer ce qui se passe dans les coulisses lorsque l'on accède à un site web depuis son navigateur. Nous aborderons enfin brièvement les autres langages existants, et les raisons qui nous poussent à choisir Java EE.

Pour commencer

Introduction au Java EE Qu'est-ce que Java EE ?

Comment lire ce cours ?

Un contenu conséquent est prévu dans ce cours, mais je ne vais volontairement pas être exhaustif : les technologies abordées sont très vastes, et l'objectif est avant tout de vous apprendre à créer une application. Si je vous réécrivais la documentation de la plate-forme Java EE en français, ça serait tout simplement imbuvable. Je vais ainsi fortement insister sur des points non documentés et des pratiques que je juge importantes, et être plus expéditif sur certains points, pour lesquels je me contenterai de vous présenter les bases et de vous renvoyer vers les documentations et sources officielles pour plus d'informations. Je vous invite donc à ne pas vous limiter à la seule lecture de ce cours, et à parcourir chacun des liens que j'ai mis en place tout au long des chapitres ; plus vous ferez preuve de curiosité et d'assiduité, plus votre apprentissage sera efficace.

Prérequis

Avant d'attaquer, sachez que ce cours ne part pas totalement de zéro :

Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Introduction au Java EE Qu'est-ce que Java EE ?

Qu'est-ce que Java EE ?

Pour commencer Internet n'est pas le web !

Pour commencer, tordons le coup à certaines confusions plutôt tenaces chez les débutants…

Java EE n'est pas Java

Le terme « Java » fait bien évidemment référence à un langage, mais également à une plate-forme : son nom complet est « Java SE » pour Java Standard Edition, et était anciennement raccourci « J2SE ». Celle-ci est constituée de nombreuses bibliothèques, ou API : citons par exemple java.lang, java.io, java.math, java.util, etc. Bref, toutes ces bibliothèques que vous devez déjà connaître et qui contiennent un nombre conséquent de classes et de méthodes prêtes à l'emploi pour effectuer toutes sortes de tâches.

Le terme « Java EE » signifie Java Enterprise Edition, et était anciennement raccourci en « J2EE ». Il fait quant à lui référence à une extension de la plate-forme standard. Autrement dit, la plate-forme Java EE est construite sur le langage Java et la plate-forme Java SE, et elle y ajoute un grand nombre de bibliothèques remplissant tout un tas de fonctionnalités que la plate-forme standard ne remplit pas d'origine. L'objectif majeur de Java EE est de faciliter le développement d'applications web robustes et distribuées, déployées et exécutées sur un serveur d'applications. Inutile de rentrer plus loin dans les détails, tout ceci étant bien entendu l'objet des chapitres à venir.

Si le cœur vous en dit, vous pouvez consulter les spécifications de la plate-forme Java EE actuelle, finalisées depuis décembre 2009.

Java EE n'est pas Javascript

S'il est vrai que Java EE permet la création d'applications web, il ne faut pas pour autant le confondre avec le langage Javascript, souvent raccourci en « JS », qui est lui aussi massivement utilisé dans les applications web. Ce sont là deux langages totalement différents, qui n'ont comme ressemblance que leur nom ! En d'autres termes, Java est au Javascript ce que le bal est à la balustrade… :euh:

Ne vous leurrez donc pas, et lorsque vous entendrez parler de scripts Java, rappelez-vous bien que cela désigne simplement du code Java, et surtout pas du code Javascript.

Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Pour commencer Internet n'est pas le web !

Internet n'est pas le web !

Qu'est-ce que Java EE ? Comment ça marche

Avant tout, il ne faut pas confondre l'internet et le web :

Un site web est un ensemble constitué de pages web (elles-mêmes faites de fichiers HTML, CSS, Javascript, etc.). Lorsqu'on développe puis publie un site web, on met en réalité en ligne du contenu sur internet. On distingue deux types de sites :

Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Qu'est-ce que Java EE ? Comment ça marche

Comment ça marche

Internet n'est pas le web ! Les langages du web

Lorsqu'un utilisateur consulte un site, ce qui se passe derrière les rideaux est un simple échange entre un client et un serveur (voir la figure suivante).

Echange dynamique client <-> serveur
Echange dynamique client <-> serveur

La communication qui s'effectue entre le client et le serveur est régie par des règles bien définies : le protocole HTTP (voir la figure suivante). Entrons donc un peu plus dans le détail, et regardons de quoi est constitué un échange simple :

  1. l'utilisateur saisit une URL dans la barre d'adresses de son navigateur ;

  2. le navigateur envoie alors une requête HTTP au serveur pour lui demander la page correspondante ;

  3. le serveur reçoit cette requête, l'interprète et génère alors une page web qu'il va renvoyer au client par le biais d'une réponse HTTP ;

  4. le navigateur reçoit, via cette réponse, la page web finale, qu'il affiche alors à l'utilisateur.

Echange dynamique HTTP client <-> serveur
Echange dynamique HTTP client <-> serveur

Ce qu'il faut comprendre et retenir de tout ça :

Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Internet n'est pas le web ! Les langages du web

Les langages du web

Comment ça marche Le Java EE mis à nu !

Nous venons de le voir dans le dernier paragraphe, le client ne fait que recevoir des pages web, les afficher à l'utilisateur et transmettre ses actions au serveur. Vous savez déjà que les langages utilisés pour mettre en forme les données et les afficher à l'utilisateur sont le HTML, le CSS et éventuellement le Javascript. Ceux-ci ont une caractéristique commune importante : ils sont tous interprétés par le navigateur, directement sur la machine client. D'ailleurs, le client est uniquement capable de comprendre ces quelques langages, rien de plus !

Eh bien le serveur aussi dispose de technologies bien à lui, que lui seul est capable de comprendre : une batterie complète ayant pour objectif final de générer les pages web à envoyer au client, avec tous les traitements que cela peut impliquer au passage : analyse des données reçues via HTTP, transformation des données, enregistrement des données dans une base de données ou des fichiers, intégration des données dans le design…

Seulement, à la différence du couple HTML & CSS qui est un standard incontournable pour la mise en forme des pages web, il existe plusieurs technologies capables de traiter les informations sur le serveur. Java EE est l'une d'entre elles, mais il en existe d'autres : PHP, .NET, Django et Ruby on Rails, pour ne citer que les principales. Toutes offrent sensiblement les mêmes possibilités, mais toutes utilisent un langage et un environnement bien à elles !

Comment choisir la technologie la mieux adaptée à son projet ?

C'est en effet une très bonne question : qu'est-ce qui permet de se décider parmi cet éventail de possibilités ? C'est un débat presque sans fin. Toutefois, dans la vie réelle le choix est bien souvent influencé, voire dicté par :

Quoi qu'il en soit, peu importent les raisons qui vous ont poussés à lire ce cours, nous sommes bien là pour apprendre le Java EE ! ;)

Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Comment ça marche Le Java EE mis à nu !

Le Java EE mis à nu !

Les langages du web Principes de fonctionnement

Le Java Enterprise Edition, comme son nom l'indique, a été créé pour le développement d'applications d'entreprises. Nous nous y attarderons dans le chapitre suivant, mais sachez d'ores et déjà que ses spécifications ont été pensées afin, notamment, de faciliter le travail en équipe sur un même projet : l'application est découpée en couches, et le serveur sur lequel tourne l'application est lui-même découpé en plusieurs niveaux. Pour faire simple, Java EE fournit un ensemble d’extensions au Java standard afin de faciliter la création d’applications centralisées.

Voyons comment tout cela s'agence !

Principes de fonctionnement

Le Java EE mis à nu ! Le modèle MVC : en théorie

Nous venons de découvrir qu'afin de pouvoir communiquer entre eux, le client et le serveur doivent se parler via HTTP. Nous savons déjà que, côté client, le navigateur s'en occupe. Côté serveur, qui s'en charge ? C'est un composant que l'on nomme logiquement serveur HTTP. Son travail est simple : il doit écouter tout ce qui arrive sur le port utilisé par le protocole HTTP, le port 80, et scruter chaque requête entrante. C'est tout ce qu'il fait, c'est en somme une interface de communication avec le protocole.

À titre informatif, voici les deux plus connus : Apache HTTP Server et IIS (Microsoft).

Cependant, nous n'allons directement utiliser ni l'un ni l'autre. Pourquoi ?

Être capable de discuter via HTTP c'est bien, mais notre serveur doit permettre d'effectuer d'autres tâches. En effet, une fois la requête HTTP lue et analysée, il faut encore traiter son contenu et éventuellement renvoyer une réponse au client en conséquence. Vous devez probablement déjà savoir que cette responsabilité vous incombe en grande partie : c'est le code que vous allez écrire qui va décider ce qu'il faut faire lorsque telle requête arrive ! Seulement, comme je viens de vous l'annoncer, un serveur HTTP de base ne peut pas gérer votre application, ce n'est pas son travail.

Ainsi, nous avons besoin d'une solution plus globale : ce composant, qui va se charger d'exécuter votre code en plus de faire le travail du serveur HTTP, se nomme le serveur d'applications. Donner une définition exacte du terme est difficile : ce que nous pouvons en retenir, c'est qu'un tel serveur inclut un serveur HTTP, et y ajoute la gestion d'objets de diverses natures au travers d'un composant que nous allons pour le moment nommer le conteneur (voir la figure suivante).

Architecture serveur
Architecture serveur

Concrètement, le serveur d'applications va :

Là encore, il en existe plusieurs sur le marché, que l'on peut découper en deux secteurs :

Comment faire un choix parmi toutes ces solutions ?

Hormis les problématiques de coûts qui sont évidentes, d'autres paramètres peuvent influencer votre décision ; citons par exemple la rapidité de chargement et d’exécution, ainsi que la quantité de technologies supportées. En ce qui nous concerne, nous partons de zéro : ainsi, un serveur d'applications basique, léger et gratuit fera très bien l'affaire. Ça tombe bien, il en existe justement un qui répond parfaitement à tous nos besoins : Apache Tomcat.

Avant de découvrir et de prendre en main Tomcat, il nous reste encore quelques concepts clés à aborder !

Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Le Java EE mis à nu ! Le modèle MVC : en théorie

Le modèle MVC : en théorie

Principes de fonctionnement Le modèle MVC : en pratique

Qu'est-ce qu'un modèle de conception ?

En anglais design pattern, un modèle de conception (ou encore patron de conception) est une simple bonne pratique, qui répond à un problème de conception d'une application. C'est en quelque sorte une ligne de conduite qui permet de décrire les grandes lignes d'une solution. De tels modèles sont issus de l'expérience des concepteurs et développeurs d'applications : c'est en effet uniquement après une certaine période d'utilisation que peuvent être mises en évidence des pratiques plus efficaces que d'autres, pratiques qui sont alors structurées en modèles et considérées comme standard.

Maintenant que nous sommes au point sur ce qu'est un modèle, la seconde question à se poser concerne bien évidemment le Java EE.

Que recommandent les développeurs Java EE expérimentés ?

Il faut bien vous rendre compte qu'à l'origine, Java EE permet plus ou moins de coder son application comme on le souhaite : en d'autres termes, on peut coder n'importe comment ! Or on sait que dans Java EE, il y a « Entreprise », et que ça n'est pas là pour faire joli ! Le développement en entreprise implique entre autres :

Pour toutes ces raisons, il est nécessaire d'adopter une architecture plus ou moins standard, que tout développeur peut reconnaître, c'est-à-dire dans laquelle tout développeur sait se repérer.

Il a été très vite remarqué qu'un modèle permettait de répondre à ces besoins, et qu'il s'appliquait particulièrement bien à la conception d'applications Java EE : le modèle MVC (Modèle-Vue-Contrôleur).
Il découpe littéralement l'application en couches distinctes, et de ce fait impacte très fortement l'organisation du code ! Voici dans les grandes lignes ce qu'impose MVC :

Ce modèle peut être représenté par la figure suivante.

MVC
MVC

Ne vous faites pas de souci si c'est encore flou dans votre esprit : nous reviendrons à maintes reprises sur ces concepts au fur et à mesure que nous progresserons dans notre apprentissage.

Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Principes de fonctionnement Le modèle MVC : en pratique

Le modèle MVC : en pratique

Le modèle MVC : en théorie Outils et environnement de développement

Le schéma précédent est très global, afin de vous permettre de bien visualiser l'ensemble du système. Tout cela est encore assez abstrait, et c'est volontaire ! En effet, chaque projet présente ses propres contraintes, et amène le développeur à faire des choix. Ainsi, on observe énormément de variantes dès que l'on entre un peu plus dans le détail de chacun de ces blocs.

Prenons l'exemple du sous-bloc représentant les données (donc à l'intérieur la couche Modèle) :

La liste de questions est souvent longue, et réalisez bien que tous ces points sont autant de paramètres qui peuvent influencer la conception de votre application, et donc vos choix au niveau de l'architecture. Ainsi, détailler plus finement les blocs composant une application n'est faisable qu'au cas par cas, idem pour les relations entre ceux-ci, et dépend fortement de l'utilisation ou non de frameworks

Qu'est-ce qu'un framework ?

Il est encore bien trop tôt pour que nous nous penchions sur ce sujet. Toutefois, vous pouvez d'ores et déjà retenir qu'un framework est un ensemble de composants qui servent à créer l'architecture et les grandes lignes d'une application. Vous pouvez le voir comme une boîte à outils géante, conçue par un ou plusieurs développeurs et mise à disposition d'autres développeurs, afin de faciliter leur travail. Il existe des frameworks dans beaucoup de langages et plate-formes, ce n'est pas un concept propre à Java EE ni au développement web en particulier.

En ce qui concerne Java EE, nous pouvons par exemple citer JSF, Spring, Struts ou encore Hibernate. Toutes ces solutions sont des frameworks que les développeurs sont libres d'utiliser ou non dans leurs projets.

Bref, nous sommes encore loin d'être assez à l'aise avec la plate-forme Java EE pour étudier ces fameux frameworks, mais nous pouvons d'ores et déjà étudier les applications Java EE "nues", sans frameworks ni fioritures. Voici donc une courte introduction de chacune des couches composant une telle application web suivant le modèle MVC.

Modèle : des traitements et des données

Dans le modèle, on trouve à la fois les données et les traitements à appliquer à ces données. Ce bloc contient donc des objets Java d'une part, qui peuvent contenir des attributs (données) et des méthodes (traitements) qui leur sont propres, et un système capable de stocker des données d'autre part. Rien de bien transcendant ici, la complexité du code dépendra bien évidemment de la complexité des traitements à effectuer par votre application.

Vue : des pages JSP

Une page JSP est destinée à la vue. Elle est exécutée côté serveur et permet l'écriture de gabarits (pages en langage "client" comme HTML, CSS, Javascript, XML, etc.). Elle permet au concepteur de la page d'appeler de manière transparente des portions de code Java, via des balises et expressions ressemblant fortement aux balises de présentation HTML.

Contrôleur : des servlets

Une servlet est un objet qui permet d'intercepter les requêtes faites par un client, et qui peut personnaliser une réponse en conséquence. Il fournit pour cela des méthodes permettant de scruter les requêtes HTTP. Cet objet n'agit jamais directement sur les données, il faut le voir comme un simple aiguilleur : il intercepte une requête issue d'un client, appelle éventuellement des traitements effectués par le modèle, et ordonne en retour à la vue d'afficher le résultat au client.

Rien que dans ces quelques lignes, il y a beaucoup d'informations. Pas de panique, nous reviendrons sur tout cela en long, en large et en travers dans les parties suivantes de ce cours ! ;) Afin de bien visualiser qui fait quoi, reprenons notre schéma en mettant des noms sur nos blocs (voir la figure suivante).

MVC avec Java EE
MVC avec Java EE
Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Le modèle MVC : en théorie Outils et environnement de développement

Outils et environnement de développement

Le modèle MVC : en pratique L'IDE Eclipse

La création d'une application web avec Java EE s'effectue généralement à l'aide d'un Environnement de Développement Intégré, très souvent raccourci à l'anglaise en IDE. C'est un logiciel destiné à faciliter grandement le développement dans son ensemble. S'il est possible pour certains projets Java de s'en passer, en ne se servant que d'un éditeur de texte pour écrire le code et d'une invite de commandes pour mettre en place l'application, ce n'est sérieusement plus envisageable pour la création d'une application web complexe. Nous allons donc dans ce chapitre apprendre à en utiliser un, et y intégrer notre serveur d'applications.

Si malgré mes conseils, votre côté « extrémiste du bloc-notes » prend le dessus et que vous souhaitez tout faire à la main, ne vous inquiétez pas, je prendrai le temps de détailler ce qui se trame en coulisses lorsque c'est important ! ;)

L'IDE Eclipse

Outils et environnement de développement Le serveur Tomcat

Présentation

J'utiliserai l'IDE Eclipse tout au long de ce cours. Ce n'est pas le seul existant, c'est simplement celui que je maîtrise le mieux. Massivement utilisé en entreprise, c'est un outil puissant, gratuit, libre et multiplateforme. Les avantages d'un IDE dans le développement d'applications web Java EE sont multiples, et sans toutefois être exhaustif en voici une liste :

Téléchargement et installation

Comme vous pouvez le constater en vous rendant sur la page de téléchargements du site, Eclipse est décliné en plusieurs versions. Nous avons bien entendu besoin de la version spécifique au développement Java EE (voir la figure suivante).

Page de téléchargement d'Eclipse pour Java EE
Page de téléchargement d'Eclipse pour Java EE

Cliquez sur "Eclipse IDE for Java EE Developers", puis choisissez et téléchargez la version correspondant à votre système d'exploitation, comme indiqué à la figure suivante.

Choix de la version correspondant à votre système d'exploitation
Choix de la version correspondant à votre système d'exploitation

Une fois le logiciel téléchargé, installez-le de préférence dans un répertoire situé directement à la racine de votre disque dur, et dont le titre ne contient ni espaces ni caractères spéciaux. Typiquement, évitez les dossiers du genre "Program Files" et consorts. Ce n'est pas une obligation mais un simple conseil, qui vous évitera bien des ennuis par la suite. Je l'ai pour ma part installé dans un répertoire que j'ai nommé eclipse et placé à la racine de mon disque dur : on peut difficilement faire plus clair. :)

Pour ceux d'entre vous qui ont déjà sur leur poste une version "Eclipse for Java developers" et qui ne souhaitent pas télécharger et installer la version pour Java EE, sachez qu'il est possible - mais bien moins agréable - d'y ajouter des plugins afin d'y reproduire l'intégration de l'environnement Java EE. Si vous y tenez, voici les étapes à suivre depuis votre fenêtre Eclipse :

  1. Allez dans Help > Install New Software.

  2. Choisissez le site "Indigo - http://download.eclipse.org/releases/indigo".

  3. Déroulez "Web, XML, and Java EE Development".

  4. Cochez alors "JST Server Adapters" et "JST Server Adapters Extentions".

Ça résoudra une partie des problèmes que vous pourriez rencontrer par la suite en suivant ce cours.
Notez bien toutefois que je vous conseille de ne pas procéder ainsi, et de repartir d'une version vierge d'Eclipse pour Java EE.

Configuration

Ci-dessous, je vous donne quelques conseils pour configurer votre Eclipse efficacement. Je ne vais pas vous expliquer en détail pourquoi ces réglages sont importants, faites-moi simplement confiance et suivez le guide !

Modification de l'encodage par défaut

Si vous ouvrez Eclipse pour la première fois, commencez par fermer l'onglet de bienvenue qui s'affiche. Rendez-vous alors dans la barre de menus supérieure, et cliquez sur Window, puis Preferences. Dans la fenêtre qui s'affiche alors, il y a un champ vous permettant de taper du texte en haut à gauche. Saisissez-y le mot "encoding", et dans chaque section qui apparaît alors dans le volet de gauche, changez l'encodage par défaut (il est généralement réglé à Cp1252 ou ISO-8859-1) par la valeur UTF-8, comme indiqué à la figure suivante.

Image utilisateurImage utilisateurImage utilisateurImage utilisateur

Validez pour finir en cliquant sur Ok afin d'appliquer les modifications.

Désactivation de la vérification de l'orthographe

Rendez-vous à nouveau dans le menu Window > Preferences, puis dans le volet de gauche rendez-vous dans General > Editors > Text Editors, et dans le volet de droite cochez la case "Show line numbers". Dans le volet de gauche, cliquez alors sur le sous-menu Spelling, et dans le nouveau volet de droite qui apparaît, décochez la case "Enable spell checking" (voir la figure suivante).

Image utilisateurImage utilisateur

Validez pour finir en cliquant sur Ok afin d'appliquer les modifications.

Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Outils et environnement de développement Le serveur Tomcat

Le serveur Tomcat

L'IDE Eclipse Structure d'une application Java EE

Présentation

Nous l'avons découvert dans le second chapitre : pour faire fonctionner une application web Java EE, nous avons besoin de mettre en place un serveur d'applications. Il en existe beaucoup sur le marché : j'ai, pour le début de ce cours, choisi d'utiliser Tomcat, car c'est un serveur léger, gratuit, libre, multiplateforme et assez complet pour ce que nous allons aborder. On le rencontre d'ailleurs très souvent dans des projets en entreprise, en phase de développement comme en production.

Si vous souhaitez vous renseigner sur les autres serveurs existants et sur leurs différences, vous savez où chercher. Wikipédia en propose par ailleurs une liste non exhaustive.

Installation

Nous allons utiliser la dernière version en date à ce jour, à savoir Tomcat 7.0. Rendez-vous sur la page de téléchargement de Tomcat, puis choisissez et téléchargez la version correspondant à votre système d'exploitation, comme indiqué à la figure suivante.

Page de téléchargement de Tomcat
Page de téléchargement de Tomcat

Sous Windows

Récupérez la dernière version Core au format zip, puis décompressez son contenu dans le répertoire où vous souhaitez installer Tomcat. Au sujet du répertoire d'installation, même conseil que pour Eclipse : choisissez un chemin dont les noms de dossiers ne comportent pas d'espaces : pour ma part, je l'ai placé dans un dossier nommé tomcat7 à la racine de mon disque. Un dossier nommé apache-tomcat-7.0.xx (les deux derniers numéros changeant selon la version que vous utiliserez) contient alors l'installation. Pour information, ce dossier est souvent référencé dans les cours et documentations sous l’appellation Tomcat Home. Voici à la figure suivante ce que j'obtiens sur mon poste.

Répertoire d'installation de Tomcat
Répertoire d'installation de Tomcat

Dans ce répertoire d'installation de Tomcat, vous trouverez un dossier nommé webapps : c'est ici que seront stockées par défaut vos applications. Pour ceux d'entre vous qui souhaiteraient jeter un œil à ce qui se passe derrière les rideaux, vous trouverez dans le dossier conf les fichiers suivants :

Sous Linux

Récupérez la dernière version Core au format tar.gz : une archive nommée apache-tomcat-7.0.xx.tar.gz est alors enregistrée sur votre poste, où xx correspond à la sous-version courante. Au moment où j'écris ces lignes, la version est la 7.0.20 : pensez à adapter les commandes qui suivent à la version que vous téléchargez. Décompressez ensuite son contenu dans le répertoire où vous souhaitez installer Tomcat. Par exemple :

cd /usr/local
mkdir tomcat
cd /usr/local/tomcat
cp ~/apache-tomcat-7.0.20.tar.gz .
tar -xvzf apache-tomcat-7.0.20.tar.gz

Un dossier nommé apache-tomcat-7.0.20 contient alors l'installation. Pour information, ce dossier est souvent référencé dans les cours et documentations sous l’appellation Tomcat Home. Vérifiez alors que l'installation s'est bien effectuée :

cd /usr/local/tomcat/apache-tomcat-7.0.20
cd bin
./version.sh

Ce script montre que Tomcat 7.0 a été installé avec succès sur votre distribution Linux :

Server version: Apache Tomcat/7.0.20
Server built:   Aug 28 2011 15:13:02
Server number:  7.0.20.0
OS Name:        Linux

Sous Mac OS

Je n'ai malheureusement pas à ma disposition de machine tournant sous Mac OS. Si vous êtes un aficionado de la marque à la pomme, voici deux liens qui expliquent comment installer Tomcat 7 sur OS X :

Bonne lecture, et n'hésitez pas à me prévenir d'éventuelles erreurs ou changements dans le procédé présenté, je modifierai cette section du chapitre en conséquence.

Création du projet web avec Eclipse

Depuis Eclipse, suivez le chemin suivant : File > New > Project... (voir la figure suivante).
Ceci peut d'ailleurs être raccourci en tapant au clavier Ctrl + N.

Nouveau projet web sous Eclipse
Nouveau projet web sous Eclipse

Sélectionnez alors Dynamic Web Project comme le montre l'image ci-dessus, puis cliquez sur Next >. J'appelle ici mon projet test. Remarquez ensuite à la figure suivante le passage concernant le serveur.

Mise en place de Tomcat - Étape 1
Mise en place de Tomcat - Étape 1

Cliquez sur le bouton New Runtime... et sélectionnez alors Apache Tomcat 7.0 dans la liste des possibilités, comme indiqué à la figure suivante.

Mise en place de Tomcat - Étape 2
Mise en place de Tomcat - Étape 2

Cochez la case comme indiqué ci-dessus, ce qui signifie que nous allons en plus du projet créer localement une nouvelle instance d'un serveur, instance que nous utiliserons par la suite pour déployer notre application. Cliquez ensuite sur Next > et remplissez correctement les informations relatives à votre installation de Tomcat en allant chercher le répertoire d'installation de Tomcat sur votre poste. Les champs devraient alors ressembler à ceux de la figure suivante, le répertoire d'installation et le numéro de version de Tomcat 7 pouvant être différents chez vous selon ce que vous avez choisi et installé.

Mise en place de Tomcat - Étape 3
Mise en place de Tomcat - Étape 3

Validez alors en cliquant sur Finish, puis cliquez deux fois sur Next >, jusqu'à obtenir cette fenêtre (voir la figure suivante).

Mise en place de Tomcat - Étape 4
Mise en place de Tomcat - Étape 4

Avant d'aller plus loin, il est nécessaire de parler contexte !

Souvenez-vous, je vous ai déjà parlé d'un fichier context.xml associé à toutes les applications. Pour permettre plus de souplesse, il est possible de spécifier un contexte propre à chaque webapp. Comme je vous l'ai déjà dit, ces applications web sont empiriquement contenues dans le dossier… webapps de votre Tomcat Home. C'est ici que, par défaut, Tomcat ira chercher les applications qu'il doit gérer et déployer. Jusque-là, vous suivez…

Le souci, et certains d'entre vous l'auront peut-être déjà compris, c'est que notre projet à nous, créé depuis Eclipse, se trouve dans un répertoire de notre workspace Eclipse : il n'est pas du tout dans ce fameux répertoire webapps de Tomcat. Pour que notre serveur prenne en compte notre future application, il va donc falloir arranger le coup ! Plusieurs solutions s'offrent à nous :

Étant donné la dernière fenêtre qui s'est affichée, vous avez probablement deviné sur quelle solution notre choix va se porter. Je vous conseille bien évidemment ici d'utiliser la quatrième et dernière solution. Conservez le nom de votre projet sous Eclipse comme contexte de déploiement sur votre serveur Tomcat ("Context root" sur l'image précédente), afin de rester cohérent. Utiliser les paramètres ci-dessus permet alors de ne pas avoir à modifier vous-mêmes le contexte de votre serveur, ou encore de ne pas avoir à utiliser le dossier webapps de votre serveur Tomcat en guise de workspace. Toute modification sur vos futures pages et classes sera ainsi automatiquement prise en compte par votre serveur Tomcat, qui s'occupera de recharger le contexte à chaque modification sauvegardée, lorsque le serveur sera lancé.

Comme diraient les têtes à claques, isn't it amazing? ;)

Voici maintenant à la figure suivante ce à quoi doit ressembler votre fenêtre Eclipse.

Mise en place de Tomcat - Étape 5
Mise en place de Tomcat - Étape 5

Vous noterez l'apparition d'une entrée Tomcat v7.0 dans l'onglet Servers, et de l'arborescence de votre projet test dans le volet de gauche.
Faites maintenant un clic droit sur le titre de votre projet dans l'arborescence Eclipse, et suivez Run As > Run on Server, comme indiqué à la figure suivante.

Mise en place de Tomcat - Étape 6
Mise en place de Tomcat - Étape 6

Dans la fenêtre qui s'ouvre alors (voir la figure suivante), nous allons sélectionner le serveur Tomcat que nous venons de mettre en place lors de la création de notre projet web, et préciser que l'on souhaite associer par défaut notre projet à ce serveur.

Mise en place de Tomcat - Étape 7
Mise en place de Tomcat - Étape 7

Cliquez alors sur Next >, puis vérifiez que votre nouveau projet est bien pris en compte par votre serveur (voir la figure suivante).

Mise en place de Tomcat - Étape 8
Mise en place de Tomcat - Étape 8

Validez enfin en cliquant sur Finish, et voilà la mise en place de votre projet et de son serveur terminée ! :)

Pour la petite histoire, une section est ajoutée dans le fichier server.xml de votre instance de Tomcat, qui est maintenant accessible depuis le dossier Servers de votre arborescence Eclipse, comme vous pouvez le voir sur la figure suivante.

Mise en place de Tomcat - Étape 9
Mise en place de Tomcat - Étape 9

Si vous êtes curieux, éditez-le ! Vous verrez qu'il contient effectivement en fin de fichier une section de ce type :

<Context docBase="test" path="/test" reloadable="true" source="org.eclipse.jst.jee.server:test"/>

Dorénavant, pour piloter votre serveur Tomcat il vous suffira de vous rendre dans l'onglet Servers en bas de votre fenêtre Eclipse, et d'utiliser un des boutons selon le besoin (redémarrage, arrêt, debug), comme indiqué à la figure suivante.

Mise en place de Tomcat - Étape 10
Mise en place de Tomcat - Étape 10

Si vous êtes arrivés jusqu'ici, c'est que votre instance de serveur Tomcat est fonctionnelle et que vous pouvez la piloter depuis Eclipse. Voyons maintenant où placer notre premier essai, et comment y accéder.

Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

L'IDE Eclipse Structure d'une application Java EE

Structure d'une application Java EE

Le serveur Tomcat La servlet

Structure standard

Toute application web Java EE doit respecter une structure de dossiers standard, qui est définie dans les spécifications de la plate-forme. Vous en trouverez le schéma à la figure suivante.

Structure des fichiers d'une application web JSP/Servlet
Structure des fichiers d'une application web JSP/Servlet

Quelques précisions :

(*) Nous reviendrons en temps voulu sur le caractère privé du dossier WEB-INF, et sur la distinction avec les dossiers publics.

Votre première page web

Eclipse, ce fourbe !

Ce que vous devez savoir avant de continuer, c'est qu'Eclipse joue souvent au fourbe, en adaptant certaines spécificités à son mode de fonctionnement. En l'occurrence, Eclipse modifie comme suit la structure d'une application Java EE (voir la figure suivante).

Structure des fichiers d'une application web sous Eclipse
Structure des fichiers d'une application web sous Eclipse

Comme vous pouvez le voir en vert sur le schéma, Eclipse déplace la structure standard de l'application vers un dossier nommé WebContent, et ajoute sous la racine un dossier src qui contiendra le code source de vos classes (les fichiers .java). En outre (je ne les ai pas représentés ici), sachez qu'Eclipse ajoute également sous la racine quelques fichiers de configuration qui lui permettront, via une tambouille interne, de gérer correctement l'application !

Attendez... Je viens de vous dire que si notre application n'était pas correctement structurée, notre serveur d'applications ne saurait pas la gérer. Si Eclipse vient mettre son nez dans cette histoire, comment notre application va-t-elle pouvoir fonctionner ?

Eh bien comme je viens de vous l'annoncer, Eclipse se débrouille via une tambouille interne pour que la structure qu'il a modifiée soit, malgré tout, utilisable sur le serveur d'applications que nous lui avons intégré. Ceci implique donc deux choses très importantes :

Création d'une page web

Vous avez maintenant en mains toutes les informations pour bien débuter. Votre projet dynamique fraîchement créé, vous pouvez maintenant placer votre première page HTML dans son dossier public, c'est-à-dire sous le dossier WebContent d'Eclipse (voir le bloc bleu sur notre schéma). Pour cela, tapez une nouvelle fois Ctrl + N au clavier, puis cherchez HTML File dans le dossier Web de l'arborescence qui apparaît alors. Sélectionnez ensuite le dossier parent, en l'occurrence le dossier WebContent de votre projet, puis donnez un nom à votre page et enfin validez. Je nomme ici ma page test.html (voir les figures suivantes).

Création d'une page HTML dans votre projet
Création d'une page HTML dans votre projet
Saisie du dossier parent et du nom de la page HTML
Saisie du dossier parent et du nom de la page HTML

Une page HTML est donc apparue dans votre projet, sous le répertoire WebContent. Remplacez alors le code automatiquement généré par Eclipse dans votre page par ce code HTML basique :

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Test</title>
    </head>
    <body>
        <p>Ceci est une page HTML.</p>
    </body>
</html>

Vous pouvez maintenant tenter d'accéder à votre page web fraîchement créée. Pour ce faire, lancez le serveur Tomcat, via le bouton

Image utilisateur

si vous avez bien suivi les instructions que je vous ai présentées précédemment. Ouvrez ensuite votre navigateur préféré, et entrez l'URL suivante afin d'accéder à votre serveur :

http://localhost:8080/test/test.html

Votre page s'affiche alors sous vos yeux… déçus !? o_O

C'est quoi toute cette histoire ? Tout un flan pour afficher trois mots ?

Patience, patience… Notre serveur étant maintenant fonctionnel, nous voici prêts à entrer dans le vif du sujet.

Nous sommes maintenant prêts pour développer notre première application web. Allons-y !

Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Le serveur Tomcat La servlet

La servlet

Structure d'une application Java EE Derrière les rideaux

Nous y voilà enfin ! Nous allons commencer par découvrir ce qu'est une servlet, son rôle au sein de l'application et comment elle doit être mise en place.
J'adopte volontairement pour ce chapitre un rythme assez lent, afin que vous preniez bien conscience des fondements de cette technologie.

Pour ceux qui trouveraient cela barbant, comprenez bien que c'est important de commencer par là et rassurez-vous, nous ne nous soucierons bientôt plus de tous ces détails ! ;)

Derrière les rideaux

La servlet Création

Retour sur HTTP

Avant d'étudier le code d'une servlet, nous devons nous pencher un instant sur le fonctionnement du protocole HTTP. Pour le moment, nous avons simplement appris que c'était le langage qu'utilisaient le client et le serveur pour s'échanger des informations. Il nous faudrait idéalement un chapitre entier pour l'étudier en détail, mais nous ne sommes pas là pour ça ! Je vais donc tâcher de faire court…

Si nous observions d'un peu plus près ce langage, nous remarquerions alors qu'il ne comprend que quelques mots, appelés méthodes HTTP. Ce sont les mots qu'utilise le navigateur pour poser des questions au serveur. Mieux encore, je vous annonce d'emblée que nous ne nous intéresserons qu'à trois de ces mots : GET, POST et HEAD.

GET

C'est la méthode utilisée par le client pour récupérer une ressource web du serveur via une URL. Par exemple, lorsque vous tapez www.siteduzero.com dans la barre d'adresses de votre navigateur et que vous validez, votre navigateur envoie une requête GET pour récupérer la page correspondant à cette adresse et le serveur la lui renvoie. La même chose se passe lorsque vous cliquez sur un lien.

Lorsqu'il reçoit une telle demande, le serveur ne fait pas que retourner la ressource demandée, il en profite pour l'accompagner d'informations diverses à son sujet, dans ce qui s'appelle les en-têtes ou headers HTTP : typiquement, on y trouve des informations comme la longueur des données renvoyées ou encore la date d'envoi.

Enfin, sachez qu'il est possible de transmettre des données au serveur lorsque l'on effectue une requête GET, au travers de paramètres directement placés après l'URL (paramètres nommés query strings) ou de cookies placés dans les en-têtes de la requête : nous reviendrons en temps voulu sur ces deux manières de faire. La limite de ce système est que, comme la taille d'une URL est limitée, on ne peut pas utiliser cette méthode pour envoyer des données volumineuses au serveur, par exemple un fichier.

POST

La taille du corps du message d'une requête POST n'est pas limitée, c'est donc cette méthode qu'il faut utiliser pour soumettre au serveur des données de tailles variables, ou que l'on sait volumineuses. C'est parfait pour envoyer des fichiers par exemple.

Toujours selon les recommandations d'usage, cette méthode doit être utilisée pour réaliser les opérations qui ont un effet sur la ressource, et qui ne peuvent par conséquent pas être répétées sans l'autorisation explicite de l'utilisateur. Vous avez probablement déjà reçu de votre navigateur un message d'alerte après avoir actualisé une page web, vous prévenant qu'un rafraîchissement de la page entraînera un renvoi des informations : eh bien c'est simplement parce que la page que vous souhaitez recharger a été récupérée via la méthode POST, et que le navigateur vous demande confirmation avant de renvoyer à nouveau la requête. :)

HEAD

Cette méthode est identique à la méthode GET, à ceci près que le serveur n'y répondra pas en renvoyant la ressource accompagnée des informations la concernant, mais seulement ces informations. En d'autres termes, il renvoie seulement les en-têtes HTTP ! Il est ainsi possible par exemple de vérifier la validité d'une URL ou de vérifier si le contenu d'une page a changé ou non sans avoir à récupérer la ressource elle-même : il suffit de regarder ce que contiennent les différents champs des en-têtes. Ne vous inquiétez pas, nous y reviendrons lorsque nous manipulerons des fichiers.

Pendant ce temps-là, sur le serveur…

Rappelez-vous notre schéma global : la requête HTTP part du client et arrive sur le serveur.
L'élément qui entre en jeu est alors le serveur HTTP (on parle également de serveur web), qui ne fait qu'écouter les requêtes HTTP sur un certain port, en général le port 80.

Que fait-il lorsqu'une requête lui parvient ?

Nous savons déjà qu'il la transmet à un autre élément, que nous avons jusqu'à présent qualifié de conteneur : il s'agit en réalité d'un conteneur de servlets, également nommé conteneur web (voir la figure suivante). Celui-ci va alors créer deux nouveaux objets :

Conteneur et paire d'objets requête/réponse
Conteneur et paire d'objets requête/réponse

Et ensuite ? Que fait-il de ce couple d'objets ?

Eh bien à ce moment précis, c'est votre code qui va entrer en jeu (représenté par la série de rouages sur le schéma). En effet, le conteneur de servlets va les transmettre à votre application, et plus précisément aux servlets et filtres que vous avez éventuellement mis en place. Le cheminement de la requête dans votre code commence à peine, et nous devons déjà nous arrêter : qu'est-ce qu'une servlet ? :)

Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

La servlet Création

Création

Derrière les rideaux Mise en place

Une servlet est en réalité une simple classe Java, qui a la particularité de permettre le traitement de requêtes et la personnalisation de réponses. Pour faire simple, dans la très grande majorité des cas une servlet n'est rien d'autre qu'une classe capable de recevoir une requête HTTP envoyée depuis le navigateur de l'utilisateur, et de lui renvoyer une réponse HTTP. C'est tout ! :)

Un des avantages de la plate-forme Java EE est sa documentation : très fournie et offrant un bon niveau de détails, la Javadoc permet en un rien de temps de se renseigner sur une classe, une interface ou un package de l'API Java EE. Tout au long de ce cours, je mettrai à votre disposition des liens vers les documentations des objets importants, afin que vous puissiez facilement, par vous-mêmes, compléter votre apprentissage et vous familiariser avec ce système de documentation.

Regardons donc ce qu'elle contient au chapitre concernant le package servlet : on y trouve une quarantaine de classes et interfaces, parmi lesquelles l'interface nommée Servlet. En regardant celle-ci de plus près, on apprend alors qu'elle est l'interface mère que toute servlet doit obligatoirement implémenter.

Mieux encore, on apprend en lisant sa description qu'il existe déjà des classes de base qui l'implémentent, et qu'il nous suffit donc d'hériter d'une de ces classes pour créer une servlet (voir la figure suivante).

Javadoc de l'interface ServletJavadoc de l'interface Servlet

Nous souhaitons traiter des requêtes HTTP, nous allons donc faire hériter notre servlet de la classe HttpServlet !
De retour sur votre projet Eclipse, faites un clic droit sur le répertoire src, puis choisissez New > Class. Renseignez alors la fenêtre qui s'ouvre comme indiqué sur les figures suivantes.

text
text
Création d'une servlet
Création d'une servlet

Renseignez le champ package par un package de votre choix : pour notre projet, j'ai choisi de le nommer com.sdzee.servlets !
Renseignez le nom de la servlet, puis cliquez ensuite sur le bouton Browse... afin de définir de quelle classe doit hériter notre servlet, puis allez chercher la classe HttpServlet et validez. Voici le code que vous obtenez alors automatiquement :

package com.sdzee.servlets;

import javax.servlet.http.HttpServlet;

public class Test extends HttpServlet {
    
}

Rien d'extraordinaire pour le moment, notre servlet étant absolument vide. D'ailleurs puisqu'elle ne fait encore rien, sautons sur l'occasion pour prendre le temps de regarder ce que contient cette classe HttpServlet héritée, afin de voir un peu ce qui se passe derrière. La Javadoc nous donne des informations utiles concernant le fonctionnement de cette classe : pour commencer c'est une classe abstraite, ce qui signifie qu'on ne pourra pas l'utiliser telle quelle et qu'il sera nécessaire de passer par une servlet qui en hérite. On apprend ensuite que la classe propose les méthodes Java nécessaires au traitement des requêtes et réponses HTTP ! Ainsi, on y trouve les méthodes :

Comment la classe fait-elle pour associer chaque type de requête HTTP à la méthode Java qui lui correspond ?

Vous n'avez pas à vous en soucier, ceci est géré automatiquement par sa méthode service() : c'est elle qui se charge de lire l'objet HttpServletRequest et de distribuer la requête HTTP à la méthode doXXX() correspondante.

Ce qu'il faut retenir pour le moment :

Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Derrière les rideaux Mise en place

Mise en place

Création Mise en service

Vous le savez, les servlets jouent un rôle très particulier dans une application. Je vous ai parlé d'aiguilleurs en introduction, on peut encore les voir comme des gendarmes : si les requêtes étaient des véhicules, les servlets seraient chargées de faire la circulation sur le gigantesque carrefour qu'est votre application ! Eh bien pour obtenir cette autorité et être reconnues en tant que telles, les servlets nécessitent un traitement de faveur : il va falloir les enregistrer auprès de notre application.

Revenons à notre exemple. Maintenant que nous avons codé notre première servlet, il nous faut donc un moyen de faire comprendre à notre application que notre servlet existe, à la fois pour lui donner l'autorité sur les requêtes et pour la rendre accessible au public ! Lorsque nous avions mis en place une page HTML statique dans le chapitre précédent, le problème ne se posait pas : nous accédions directement à la page en question via une URL directe pointant vers le fichier depuis notre navigateur.

Mais dans le cas d'une servlet qui, rappelons-le, est une classe Java, comment faire ?

Concrètement, il va falloir configurer quelque part le fait que notre servlet va être associée à une URL. Ainsi lorsque le client la saisira, la requête HTTP sera automatiquement aiguillée par notre conteneur de servlet vers la bonne servlet, celle qui est en charge de répondre à cette requête. Ce "quelque part" se présente sous la forme d'un simple fichier texte : le fichier web.xml.

C'est le cœur de votre application : ici vont se trouver tous les paramètres qui contrôlent son cycle de vie. Nous n'allons pas apprendre d'une traite toutes les options intéressantes, mais y aller par étapes. Commençons donc par apprendre à lier notre servlet à une URL : après tous les efforts que nous avons fournis, c'est le minimum syndical que nous sommes en droit de lui demander ! :D

Ce fichier de configuration doit impérativement se nommer web.xml et se situer juste sous le répertoire /WEB-INF de votre application. Si vous avez suivi à la lettre la procédure de création de notre projet web, alors ce fichier est déjà présent. Éditez-le, et supprimez le contenu généré par défaut. Si jamais le fichier est absent de votre arborescence, créez simplement un nouveau fichier XML en veillant bien à le placer sous le répertoire /WEB-INF et à le nommer web.xml. Voici la structure à vide du fichier :

<?xml version="1.0" encoding="UTF-8"?>
<web-app 
  xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0">

</web-app>

L'intégralité de son contenu devra être placée entre les balises <web-app> et </web-app>.

La mise en place d'une servlet se déroule en deux étapes : nous devons d'abord déclarer la servlet, puis lui faire correspondre une URL.

Définition de la servlet

La première chose à faire est de déclarer notre servlet : en quelque sorte il s'agit de lui donner une carte d'identité, un moyen pour le serveur de la reconnaître. Pour ce faire, il faut ajouter une section au fichier qui se présente ainsi sous sa forme minimale :

<servlet>
	<servlet-name>Test</servlet-name>
	<servlet-class>com.sdzee.servlets.Test</servlet-class>
</servlet>

La balise responsable de la définition d'une servlet se nomme logiquement <servlet>, et les deux balises obligatoires de cette section sont très explicites :

Il est par ailleurs possible d'insérer au sein de la définition d'une servlet d'autres balises facultatives :

<servlet>
	<servlet-name>Test</servlet-name>
	<servlet-class>com.sdzee.servlets.Test</servlet-class>

	<description>Ma première servlet de test.</description>

	<init-param>
		<param-name>auteur</param-name> 
		<param-value>Coyote</param-value> 
	</init-param>

	<load-on-startup>1</load-on-startup>
</servlet>

On découvre ici trois nouveaux blocs :

Mapping de la servlet

Il faut ensuite faire correspondre notre servlet fraîchement déclarée à une URL, afin qu'elle soit joignable par les clients :

<servlet-mapping>
	<servlet-name>Test</servlet-name>
	<url-pattern>/toto</url-pattern>
</servlet-mapping>

La balise responsable de la définition du mapping se nomme logiquement <servlet-mapping>, et les deux balises obligatoires de cette section sont, là encore, très explicites.

Pourquoi un "pattern" et pas simplement une URL ?

En effet il s'agit bien d'un pattern, c'est-à-dire d'un modèle, et pas nécessairement d'une URL fixe. Ainsi, on peut choisir de rendre notre servlet responsable du traitement des requêtes issues d'une seule URL, ou bien d'un groupe d'URL. Vous n'imaginez pour le moment peut-être pas de cas qui impliqueraient qu'une servlet doive traiter les requêtes issues de plusieurs URL, mais rassurez-vous nous ferons la lumière sur ce type d'utilisation dans la partie suivante de ce cours. De même, nous découvrirons qu'il est tout à fait possible de déclarer plusieurs sections <servlet-mapping> pour une même section <servlet> dans le fichier web.xml.

Que signifie "URL relative" ?

Cela veut dire que l'URL ou le pattern que vous renseignez dans le champ <url-pattern> sont basés sur le contexte de votre application. Dans notre cas, souvenez-vous du contexte de déploiement que nous avons précisé lorsque nous avons créé notre projet web : nous l'avions appelé test. Nous en déduisons donc que notre <url-pattern>/toto</url-pattern> fait référence à l'URL absolue /test/toto.

Nous y voilà, notre servlet est maintenant joignable par le client via l'URL http://localhost:8080/test/toto.

Pour information, le code final de notre fichier web.xml est donc :

<?xml version="1.0" encoding="UTF-8"?>
<web-app 
  xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0">
	<servlet>
		<servlet-name>Test</servlet-name>
		<servlet-class>com.sdzee.servlets.Test</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>Test</servlet-name>
		<url-pattern>/toto</url-pattern>
	</servlet-mapping>
</web-app>
Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Création Mise en service

Mise en service

Mise en place Servlet avec vue…

Do you « GET » it?

Nous venons de créer un fichier de configuration pour notre application, nous devons donc redémarrer notre serveur pour que ces modifications soient prises en compte. Il suffit pour cela de cliquer sur le bouton "start" de l'onglet Servers, comme indiqué à la figure suivante.

Bouton de redémarrage du serveur Tomcat dans Eclipse
Bouton de redémarrage du serveur Tomcat dans Eclipse

Faisons le test, et observons ce que nous affiche notre navigateur lorsque nous tentons d'accéder à l'URL http://localhost:8080/test/toto que nous venons de mapper sur notre servlet (voir la figure suivante).

Méthode HTTP non supportée
Méthode HTTP non supportée

Nous voici devant notre premier code de statut HTTP. En l'occurrence, c'est à la fois une bonne et une mauvaise nouvelle :

Par qui a été générée cette page d'erreur ?

Tout est parti du conteneur de servlets. D'ailleurs, ce dernier effectue pas mal de choses dans l'ombre, sans vous le dire ! Dans ce cas précis, il a :

  1. reçu la requête HTTP depuis le serveur web ;

  2. généré un couple d'objets requête/réponse ;

  3. parcouru le fichier web.xml de votre application à la recherche d'une entrée correspondant à l'URL contenue dans l'objet requête ;

  4. trouvé et identifié la servlet que vous y avez déclarée ;

  5. contacté votre servlet et transmis la paire d'objets requête/réponse.

Dans ce cas, pourquoi cette page d'erreur a-t-elle été générée ?

Nous avons pourtant bien fait hériter notre servlet de la classe HttpServlet, notre servlet doit pouvoir interagir avec HTTP ! Qu'est-ce qui cloche ? Eh bien nous avons oublié une chose importante : afin que notre servlet soit capable de traiter une requête HTTP de type GET, il faut y implémenter une méthode… doGet() ! Souvenez-vous, je vous ai déjà expliqué que la méthode service() de la classe HttpServlet s'occupera alors elle-même de transmettre la requête GET entrante vers la méthode doGet() de notre servlet… Ça vous revient ? :)

Maintenant, comment cette page d'erreur a-t-elle été générée ?

C'est la méthode doGet() de la classe mère HttpServlet qui est en la cause. Ou plutôt, disons que c'est grâce à elle ! En effet, le comportement par défaut des méthodes doXXX() de la classe HttpServlet est de renvoyer un code d'erreur HTTP 405 ! Donc si le développeur a bien fait son travail, pas de problème : c'est bien la méthode doXXX() de la servlet qui sera appelée. Par contre, s'il a mal fait son travail et a oublié de surcharger la méthode doXXX() voulue, alors c'est la méthode de la classe mère HttpServlet qui sera appelée, et un code d'erreur sera gentiment et automatiquement renvoyé au client. Ainsi, la classe mère s'assure toujours que sa classe fille - votre servlet ! - surcharge bien la méthode doXXX() correspondant à la méthode HTTP traitée ! ;)

Nous voilà maintenant au courant de ce qu'il nous reste à faire : il nous suffit de surcharger la méthode doGet() de la classe HttpServlet dans notre servlet Test. Voici donc le code de notre servlet :

package com.sdzee.servlets;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Test extends HttpServlet {
	public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException{
		
	}
}

Comme vous pouvez le constater, l'ajout de cette seule méthode vide fait intervenir plusieurs imports qui définissent les objets et exceptions présents dans la signature de la méthode : HttpServletRequest, HttpServletResponse, ServletException et IOException.

Réessayons alors de contacter notre servlet via notre URL : tout se passe comme prévu, le message d'erreur HTTP disparaît.
Cela dit, notre servlet ne fait strictement rien de la requête HTTP reçue : le navigateur nous affiche alors une page… blanche !

Comment le client sait-il que la requête est arrivée à bon port ?

C'est une très bonne remarque. En effet, si votre navigateur vous affiche une simple page blanche, c'est parce qu'il considère la requête comme terminée avec succès : si ce n'était pas le cas, il vous afficherait un des codes et messages d'erreur HTTP… (voir la figure suivante). Si vous utilisez le navigateur Firefox, vous pouvez utiliser l'onglet Réseau de l'outil Firebug pour visualiser qu'effectivement, une réponse HTTP est bien reçue par votre navigateur (si vous utilisez le navigateur Chrome, vous pouvez accéder à un outil similaire en appuyant sur F12 ).

En-têtes de la réponse HTTP avec Firebug
En-têtes de la réponse HTTP avec Firebug

On y observe :

Eh bien encore une fois, c'est le conteneur de servlets qui a fait le boulot sans vous prévenir ! Quand il a généré la paire d'objets requête/réponse, il a initialisé le statut de la réponse avec une valeur par défaut : 200. C'est-à-dire que par défaut, le conteneur de servlets crée un objet réponse qui stipule que tout s'est bien passé. Ensuite, il transmet cet objet à votre servlet, qui est alors libre de le modifier à sa guise. Lorsqu'il reçoit à nouveau l'objet en retour, si le code de statut n'a pas été modifié par la servlet, c'est que tout s'est bien passé. En d'autres termes, le conteneur de servlets adopte une certaine philosophie : pas de nouvelles, bonne nouvelle ! :D

Cycle de vie d'une servlet

Quand une servlet est demandée pour la première fois ou quand l'application web démarre, le conteneur de servlets va créer une instance de celle-ci et la garder en mémoire pendant toute l'existence de l'application. La même instance sera réutilisée pour chaque requête entrante dont les URL correspondent au pattern d'URL défini pour la servlet. Dans notre exemple, aussi longtemps que notre serveur restera en ligne, tous nos appels vers l'URL /test/toto seront dirigés vers la même et unique instance de notre servlet, générée par Tomcat lors du tout premier appel.

En fin de compte, l'instance d'une servlet est-elle créée lors du premier appel à cette servlet, ou bien dès le démarrage du serveur ?

Ceci dépend en grande partie du serveur d'applications utilisé. Dans notre cas, avec Tomcat, c'est par défaut au premier appel d'une servlet que son unique instance est créée.

Toutefois, ce mode de fonctionnement est configurable. Plus tôt dans ce chapitre, je vous expliquais comment déclarer une servlet dans le fichier web.xml, et j'en ai profité pour vous présenter une balise facultative : <load-on-startup>N</load-on-startup>, où N doit être un entier positif. Si dans la déclaration d'une servlet vous ajoutez une telle ligne, alors vous ordonnez au serveur de charger l'instance de la servlet en question directement pendant le chargement de l'application.

Le chiffre N correspond à la priorité que vous souhaitez donner au chargement de votre servlet. Dans notre projet nous n'utilisons pour le moment qu'une seule servlet, donc nous pouvons marquer n'importe quel chiffre supérieur ou égal à zéro, ça ne changera rien. Mais dans le cas d'une application contenant beaucoup de servlets, cela permet de définir quelle servlet doit être chargée en premier. L'ordre est établi du plus petit au plus grand : la ou les servlets ayant un load-on-startup initialisé à zéro sont les premières à être chargées, puis 1, 2, 3, etc.

Voilà tout pour cet aparté. En ce qui nous concerne, nous n'utiliserons pas cette option de chargement dans nos projets, le chargement des servlets lors de leur première sollicitation nous ira très bien ! ^^

Envoyer des données au client

Avec tout cela, nous n'avons encore rien envoyé à notre client, alors qu'en mettant en place une simple page HTML nous avions affiché du texte dans le navigateur du client en un rien de temps. Patience, les réponses vont venir… Utilisons notre servlet pour reproduire la page HTML statique que nous avions créée lors de la mise en place de Tomcat. Comme je vous l'ai expliqué dans le paragraphe précédent, pour envoyer des données au client il va falloir manipuler l'objet HttpServletResponse. Regardons d'abord ce qu'il est nécessaire d'inclure à notre méthode doGet(), et analysons tout cela ensuite :

public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException{
	response.setContentType("text/html");
	response.setCharacterEncoding( "UTF-8" );
	PrintWriter out = response.getWriter();
	out.println("<!DOCTYPE html>");
	out.println("<html>");
	out.println("<head>");
	out.println("<meta charset=\"utf-8\" />");
	out.println("<title>Test</title>");
	out.println("</head>");
	out.println("<body>");
	out.println("<p>Ceci est une page générée depuis une servlet.</p>");
	out.println("</body>");
	out.println("</html>");
}

Comment procédons-nous ?

  1. Nous commençons par modifier l'en-tête Content-Type de la réponse HTTP, pour préciser au client que nous allons lui envoyer une page HTML, en faisant appel à la méthode setContentType() de l'objet HttpServletResponse.

  2. Par défaut, l'encodage de la réponse envoyée au client est initialisé à ISO-8859-1. Si vous faites quelques recherches au sujet de cet encodage, vous apprendrez qu'il permet de gérer sans problème les caractères de notre alphabet, mais qu'il ne permet pas de manipuler les caractères asiatiques, les alphabets arabes, cyrilliques, scandinaves ainsi que d'autres caractères plus exotiques. Afin de permettre une gestion globale d'un maximum de caractères différents, il est recommandé d'utiliser l'encodage UTF-8 à la place. Voilà pourquoi nous modifions l'encodage par défaut en réalisant un appel à la méthode setCharacterEncoding() de l'objet HttpServletResponse. Par ailleurs, c'est également pour cette raison que je vous ai fait modifier les encodages par défaut lors de la configuration d'Eclipse !

  3. Nous récupérons ensuite un objet PrintWriter qui va nous permettre d'envoyer du texte au client, via la méthode getWriter() de l'objet HttpServletResponse. Vous devrez donc importer java.io.PrintWriter dans votre servlet. Cet objet utilise l'encodage que nous avons défini précédemment, c'est-à-dire UTF-8.

  4. Nous écrivons alors du texte dans la réponse via la méthode println() de l'objet PrintWriter.

Enregistrez, testez et vous verrez enfin la page s'afficher dans votre navigateur : ça y est, vous savez maintenant utiliser une servlet et transmettre des données au client. :)

Rien que pour reproduire ce court et pauvre exemple, il nous a fallu 10 appels à out.println() ! Lorsque nous nous attaquerons à des pages web un peu plus complexes que ce simple exemple, allons-nous devoir écrire tout notre code HTML à l'intérieur de ces méthodes println() ?

Non, bien sûr que non ! Vous imaginez un peu l'horreur si c'était le cas ?! Si vous avez suivi le topo sur MVC, vous vous souvenez d'ailleurs que la servlet n'est pas censée s'occuper de l'affichage, c'est la vue qui doit s'en charger ! Et c'est bien pour ça que je ne vous ai rien fait envoyer d'autre que cette simple page d'exemple HTML… Toutefois, même si nous ne procéderons plus jamais ainsi pour la création de nos futures pages web, il était très important que nous découvrions comment cela se passe.

Pour le moment, voici à la figure suivante ce que nous avons réalisé.

Servlet seule
Servlet seule

Note : dorénavant et afin d'alléger les schémas, je ne représenterai plus le serveur HTTP en amont du conteneur. Ici, le bloc intitulé "Serveur" correspond en réalité au conteneur de servlets.

La leçon à retenir en cette fin de chapitre est claire : le langage Java n'est pas du tout adapté à la rédaction de pages web ! Notre dernier exemple en est une excellente preuve, et il nous faut nous orienter vers quelque chose de plus efficace.

Il est maintenant grand temps de revenir au modèle MVC : l'affichage de contenu HTML n'ayant rien à faire dans le contrôleur (notre servlet), nous allons créer une vue et la mettre en relation avec notre servlet.

Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Mise en place Servlet avec vue…

Servlet avec vue…

Mise en service Introduction aux JSP

Le modèle MVC nous conseille de placer tout ce qui touche à l'affichage final (texte, mise en forme, etc.) dans une couche à part : la vue. Nous avons rapidement survolé dans la première partie de ce cours comment ceci se concrétisait en Java EE : la technologie utilisée pour réaliser une vue est la page JSP. Nous allons dans ce chapitre découvrir comment fonctionne une telle page, et apprendre à en mettre une en place au sein de notre embryon d'application.

Introduction aux JSP

Servlet avec vue… Mise en place d'une JSP

À quoi ressemble une page JSP ?

C'est un document qui, à première vue, ressemble beaucoup à une page HTML, mais qui en réalité en diffère par plusieurs aspects :

L'intérêt est de rendre possible la création de pages dynamiques : puisqu'il y a une étape de génération sur le serveur, il devient possible de faire varier l'affichage et d’interagir avec l'utilisateur, en fonction notamment de la requête et des données reçues !

Ne vous fiez pas au titre de ce sous-chapitre, nous n'allons pas pour le moment nous intéresser à la technologie JSP en elle-même, ceci faisant l'objet des chapitres suivants. Nous allons nous limiter à l'étude de ce qu'est une JSP, de la manière dont elle est interprétée par notre serveur et comment elle s'insère dans notre application.

Nature d'une JSP

Quoi ?

Les pages JSP sont une des technologies de la plate-forme Java EE les plus puissantes, simples à utiliser et à mettre en place. Elles se présentent sous la forme d'un simple fichier au format texte, contenant des balises respectant une syntaxe à part entière. Le langage JSP combine à la fois les technologies HTML, XML, servlet et JavaBeans (nous reviendrons sur ce terme plus tard, pour le moment retenez simplement que c'est un objet Java) en une seule solution permettant aux développeurs de créer des vues dynamiques.

Pourquoi ?

Pour commencer, mettons noir sur blanc les raisons de l'existence de cette technologie.

Comment ?

On peut résumer la technologie JSP en une technologie offrant les capacités dynamiques des servlets tout en permettant une approche naturelle pour la création de contenus statiques. Ceci est rendu possible par :

Bon, assez gambergé ! Maintenant que nous avons une bonne idée de ce que sont les pages JSP, rentrons dans le concret en étudiant leur vie au sein d'une application !

Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Servlet avec vue… Mise en place d'une JSP

Mise en place d'une JSP

Introduction aux JSP Mise en relation avec notre servlet

Création de la vue

Le contexte étant posé, nous pouvons maintenant créer notre première page JSP. Pour ce faire, depuis votre projet Eclipse faites un clic droit sur le dossier WebContent de votre projet, puis choisissez New > JSP File, et dans la fenêtre qui apparaît renseignez le nom de votre page JSP, ainsi qu'indiqué aux figures suivantes.

Création d'une page JSP - Étape 1
Création d'une page JSP - Étape 1
Création d'une page JSP - Étape 2
Création d'une page JSP - Étape 2

Une page JSP par défaut est alors générée par Eclipse : supprimez tout son contenu, et remplacez-le par notre modèle d'exemple :

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Test</title>
    </head>

    <body>
        <p>Ceci est une page générée depuis une JSP.</p>
    </body>
</html>

Rendez-vous ensuite dans la barre d'adresses de votre navigateur, et entrez l'URL correspondant à la page que vous venez de créer :

http://localhost:8080/test/test.jsp

Nous obtenons alors le résultat de la figure suivante.

Image utilisateur

Qu'est-ce que c'est que cette horreur ? Que s'est-il passé ?

Le problème que vous voyez ici, c'est l'encodage ! Eh oui, dans le chapitre précédent nous avions modifié l'encodage par défaut directement depuis notre servlet, et je ne vous avais alors pas expliqué pourquoi c'était vraiment nécessaire de procéder ainsi, je vous avais uniquement expliqué l'intérêt d'utiliser UTF-8. Cette fois dans notre JSP, nous n'avons rien modifié. Par conséquent, la réponse créée par notre page utilise la valeur par défaut, c'est-à-dire l'encodage latin ISO-8859-1.

Si l'encodage latin est utilisé par défaut, alors pourquoi les lettres accentuées ne s'affichent-elles pas correctement ? Ce sont bien des caractères de notre alphabet !

Nous y voilà, vous devez bien comprendre comment le principe d'encodage fonctionne. Il s'agit d'un processus en deux étapes, avec d'une part la manière dont sont encodés et gérés les caractères sur le serveur, et d'autre part la manière dont les données contenues dans la réponse envoyée vont être interprétées par le navigateur :

Or, comme je viens de vous le dire, votre page JSP a par défaut envoyé la réponse au client en spécifiant l'encodage latin dans l'en-tête HTTP. Voilà donc l'explication de l'affreux micmac observé : votre navigateur a essayé d'afficher des caractères encodés en UTF-8 en utilisant l'encodage latin ISO-8859-1, et il se trouve que l'encodage des caractères accentués en ISO n'a rien à voir avec celui des caractères accentués en UTF ! D'où les symboles bizarroïdes observés⁢…

Comment modifier l'en-tête HTTP depuis notre page JSP, afin de faire savoir au navigateur qu'il doit utiliser l'encodage UTF-8 pour interpréter les données reçues ?

Pour cela, il va falloir ajouter une instruction en tête de votre page JSP. Je ne vais pas vous l'expliquer dès maintenant, je reviendrai sur son fonctionnement dans un chapitre à venir. Contentez-vous simplement d'ajouter cette ligne tout en haut du code de votre page pour le moment :

<%@ page pageEncoding="UTF-8" %>

Une fois la modification effectuée et enregistrée, actualisez la page dans votre navigateur et vous constaterez qu'il vous affiche maintenant correctement le texte attendu.
Tout va bien donc, notre JSP est fonctionnelle !

Cycle de vie d'une JSP

En théorie

Tout tient en une seule phrase : quand une JSP est demandée pour la première fois, ou quand l'application web démarre, le conteneur de servlets va vérifier, traduire puis compiler la page JSP en une classe héritant de HttpServlet, et l'utiliser durant l'existence de l'application.

Cela signifie-t-il qu'une JSP est littéralement transformée en servlet par le serveur ?

C'est exactement ce qui se passe. Lors de la demande d'une JSP, le moteur de servlets va exécuter la classe JSP auparavant traduite et compilée et envoyer la sortie générée (typiquement, une page HTML/CSS/JS) depuis le serveur vers le client à travers le réseau, sortie qui sera alors affichée dans son navigateur !

Pourquoi ?

Je vous l'ai déjà dit, la technologie JSP consiste en une véritable abstraction de la technologie servlet : cela signifie concrètement que les JSP permettent au développeur de faire du Java sans avoir à écrire de code Java ! Bien que cela paraisse magique, rassurez-vous il n'y a pas de miracles : vous pouvez voir le code JSP écrit par le développeur comme une succession de raccourcis en tous genres qui, dans les coulisses, appellent en réalité des portions de code Java toutes prêtes !

Que se passe-t-il si le contenu d'une page JSP est modifié ? Que devient la servlet auto-générée correspondante ?

C'est une très bonne question ! ;) Voici ce qui se passe au sein du conteneur de servlets lorsqu'une requête HTTP est destinée à une JSP :

J'ai représenté cette suite de décisions sur la figure suivante, afin de vous faciliter la compréhension du cycle.

Cycle de vie d'une JSP
Cycle de vie d'une JSP

En pratique

Avant de passer à la suite, revenons sur cette histoire de traduction en servlet. Je vous ai dit que le conteneur de servlets, en l'occurrence ici Tomcat, générait une servlet à partir de votre JSP. Eh bien sachez que vous pouvez trouver le code source ainsi généré dans le répertoire de travail du serveur : sous Tomcat, il s'agit du répertoire /work.

Qu'en est-il de notre première JSP ? Existe-t-il une servlet auto-générée depuis nos quelques lignes de texte ?

La réponse est oui bien entendu, à partir du moment où vous avez appelé au moins une fois cette JSP depuis votre navigateur ! Cette servlet est bien présente dans le répertoire de travail de Tomcat, seulement comme nous gérons notre serveur directement depuis Eclipse, par défaut ce dernier va en quelque sorte prendre la main sur Tomcat, et mettre tous les fichiers dans un répertoire à lui ! Le fourbe... ^^ Bref, voilà où se trouve ma servlet pour cet exemple :

C:\eclipse\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\test\org\apache\jsp\test_jsp.java
C:\eclipse\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\test\org\apache\jsp\test_jsp.class

Elle doit se situer sensiblement au même endroit chez vous, à un ou deux noms de dossier près selon la configuration que vous avez mise en place et bien entendu selon le système d'exploitation que vous utilisez. Vous remarquerez que Tomcat suffixe les servlets qu'il auto-génère à partir de pages JSP avec "_jsp".

Sans surprise, au milieu du code généré par Tomcat nous retrouvons bien des instructions très semblables à celles que nous avions dû écrire dans notre servlet dans le chapitre précédent, et qui correspondent cette fois à ce que nous avons écrit dans notre JSP :

out.write("<!DOCTYPE html>\r\n");
out.write("<html>\r\n");
out.write("    <head>\r\n");
out.write("        <meta charset=\"utf-8\" />\r\n");
out.write("        <title>Test</title>\r\n");
out.write("    </head>\r\n");
out.write("    <body>\r\n");
out.write("        <p>Ceci est une page générée depuis une JSP.</p>\r\n");
out.write("    </body>\r\n");
out.write("</html>");
Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Introduction aux JSP Mise en relation avec notre servlet

Mise en relation avec notre servlet

Mise en place d'une JSP Transmission de données

Garder le contrôle

Dans l'exemple que nous venons de réaliser, nous nous sommes contentés d'afficher du texte statique, et avons visualisé le résultat en appelant directement la page JSP depuis son URL. C'était pratique pour le coup, mais dans une application Java EE il ne faut jamais procéder ainsi ! Pourquoi ? La réponse tient en trois lettres : MVC. Ce modèle de conception nous recommande en effet la mise en place d'un contrôleur, et nous allons donc tâcher de toujours associer une servlet à une vue.

Mais je viens de vous montrer qu'une JSP était de toute façon traduite en servlet… Quel est l'intérêt de mettre en place une autre servlet ?

Une JSP est en effet automatiquement traduite en servlet, mais attention à ne pas confondre : les contrôleurs du MVC sont bien représentés en Java EE par des servlets, mais cela ne signifie pas pour autant que toute servlet joue le rôle d'un contrôleur dans une application Java EE. En l'occurrence, les servlets résultant de la traduction des JSP dans une application n'ont pour rôle que de permettre la manipulation des requêtes et réponses HTTP. En aucun cas elles n'interviennent dans la couche de contrôle, elles agissent de manière transparente et font bien partie de la vue : ce sont simplement des traductions en un langage que comprend le serveur (le Java !) des vues présentes dans votre application (de simples fichiers textes contenant de la syntaxe JSP).

Nous allons même pousser le vice plus loin, et déplacer notre page JSP dans le répertoire /WEB-INF. Si vous vous souvenez de ce que je vous ai dit dans le chapitre sur la configuration de Tomcat, vous savez que ce dossier a une particularité qui nous intéresse : il cache automatiquement les ressources qu'il contient. En d'autres termes, une page présente sous ce répertoire n'est plus accessible directement par une URL côté client ! Il devient alors nécessaire de passer par une servlet côté serveur pour donner l'accès à cette page… Plus d'oubli possible ! ;)

Faites le test. Essayez depuis une URL de joindre votre page JSP après l'avoir déplacée sous /WEB-INF : vous n'y arriverez pas !

Nous devons donc associer notre servlet à notre vue. Cette opération est réalisée depuis la servlet, ce qui est logique puisque c'est elle qui décide d'appeler la vue.
Reprenons notre servlet, vidons la méthode doGet() du contenu que nous avons depuis fait migrer dans la JSP, et regardons le code à mettre en place pour effectuer l'association :

...

public void doGet( HttpServletRequest request, HttpServletResponse response )	throws ServletException, IOException {
	this.getServletContext().getRequestDispatcher( "/WEB-INF/test.jsp" ).forward( request, response );
}

Analysons ce qui se passe :

De cette manière notre page JSP devient accessible au travers de la servlet ; d'ailleurs, notre servlet ne faisant actuellement rien d'autre, son seul rôle est de transférer le couple requête reçue et réponse vers la JSP finale.

Ne soyez pas leurrés : comme je vous l'ai déjà dit lorsque je vous ai présenté la structure d'un projet, le dossier WebContent existe uniquement dans Eclipse ! Je vous ai déjà expliqué qu'il correspondait en réalité à la racine de l'application, et c'est donc pour ça qu'il faut bien écrire /WEB-INF/test.jsp en argument de la méthode getRequestDispatcher(), et non pas /WebContent/WEB-INF/test.jsp !

Faites à nouveau le test, en essayant cette fois d'appeler l'URL correspondant à votre servlet (souvenez-vous, c'est celle que nous avons mise en place dans le fichier web.xml, à savoir /test/toto) : tout fonctionne, notre requête est bien acheminée jusqu'à notre JSP, et en retour notre navigateur nous affiche bien le contenu de la page !

Voici à la figure suivante ce que nous venons de réaliser.

Servlet + JSP
Servlet + JSP
Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Mise en place d'une JSP Transmission de données

Transmission de données

Mise en relation avec notre servlet Données issues du serveur : les attributs

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

Données issues du serveur : les attributs

Transmission de données Données issues du client : les paramètres

Transmettre des variables de la servlet à la JSP

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

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

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

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

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

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

<%@ page pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Test</title>
    </head>
    <body>
        <p>Ceci est une page générée depuis une JSP.</p>
        <p>
            <% 
            String attribut = (String) request.getAttribute("test");
            out.println( attribut );
            %>
        </p>
    </body>
</html>

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

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

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

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

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

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

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

Fatigué(e) de lire sur un écran ? Découvrez ce cours en livre.

Transmission de données Données issues du client : les paramètres

Données issues du client : les paramètres

Données issues du serveur : les attributs Le JavaBean

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

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

La forme de l'URL

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

<!-- URL sans paramètres -->
/page.jsp

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

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

Il y a peu de choses à retenir :

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

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

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

Que signifie "avoir un impact sur la ressource" ?

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

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

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

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

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

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

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

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

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

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

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

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

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Test</title>
    </head>
    <body>
        <p>Ceci est une page générée depuis une JSP.</p>
        <p>
            Transmission de variables : OK ! Coyote
        </p>
    </body>
</html>

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

<%@ page pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Test</title>
    </head>
    <body>
        <p>Ceci est une page générée depuis une JSP.</p>
        <p>
            <% 
            String attribut = (String) request.getAttribute("test");
            out.println( attribut );

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

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

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

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

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

Il ne faut pas faire de confusion ici :