Présentation/résumé

Transcription

Présentation/résumé
Date création :
21/05/08
Référence:
-
Dernière modif. :
25/06/08
Pages
44
Conception
Pascal Cauquil
Modifications
Fabrice Benedet
Support de formation de l'initiation Java web
Diffusion : IS, formateurs et participants à la formation Bases de données scientifiques
Présentation/résumé
Ce fichier (support_cours_v1.2.odt) est le support de cours de l'initation Java/web
pour la formation IS/DSI Bases de données scientifiques.
Durée : ½ journée.
Il aborde :
•
une présentation de Java
•
les méthodes de développement d'applications web avec Java
•
un TP d'initiation au framework Struts 2
Note : Certaines définitions sont tirées de Wikipédia.
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
1/44
1. Découverte de Java
1. Qu'est-ce que Java ?
Java est un langage de programmation mis au point par Sun Microsystems dans les années
90. La première version sort en 1995.
A présent, il est plus juste de considérer que Java est non seulement un langage de programmation, mais surtout une sphère autour de laquelle gravitent des concepts, des technologies, des acteurs industriels, des serveurs, dont le but est de permettre l'application du langage Java à un ensemble très varié de contextes d'utilisation.
2. Particularités
Comparé à d'autres langages, Java présente les caractéristiques suivantes.
1. Indépendance vis-à-vis de la plate-forme d'exécution
Le code compilé par le compilateur, appelé bytecode Java, est indépendant de la plateforme d'exécution (du matériel comme du système d'exploitation).
Cette caractéristique n'est rendue possible que par l'entremise d'une machine virtuelle
(JVM), à savoir un programme qui s'intercale entre le programme Java à exécuter et le système d'exploitation, et dont le rôle est de traduire le bytecode Java dans un code compréhensible par le système cible.
Illustration 1: Pricincipe d'exécution du bytecode Java
La machine virtuelle, quant à elle, reste évidemment spécifique à chaque couple
machine/système d'exploitation. Cependant, cette dépendance est à relativiser car des machines virtuelles existent pour une grande variété de systèmes :
–
PC sous Windows et Linux
–
Macintosh : architectures PPC et x86
–
Systèmes Unix : IBM AIX, HP-UX, Sun Solaris...
–
Périphériques mobiles sous Symbian, Linux, Windows Mobile...
–
et bien d'autres...
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
2/44
La contrepartie de cette architecture est une vitesse d'exécution notablement inférieure à
celle d'un code natif.
2. Un environnement libéré
Initialement, Java n'est pas une technologie libre. Jusqu'en novembre 2006, les codes
sources du compilateur et de la machine virtuelle HotSpot VM, machine de référence, sont la
propriété de Sun Microsystems. Pour autant, leur utilisation est gratuite, même en environnement professionnel ou à but commercial.
Par ailleurs, s'il est vrai que le code source de la JVM de Sun est privé, Sun publie l'ensemble des spécifications qui permettent à des tiers la conception de leur propre machine
virtuelle.
Ces deux facteurs ont permis l'émergence d'un marché décentralisé et même d'une communauté autour de cette technologie, malgré ses aspects propriétaires.
En novembre 2006, Sun annonce qu'il va progressivement libérer tous les aspects de la
plate-forme : codes sources du compilateur, de sa JVM, du serveur J2EE GlassFish et tout
le code Java son désormais sous licence GNU GPL1. Ceci laisse espérer un accroissement
de la communauté.
3. Développement exclusivement orienté objet
Certains langages, comme le PHP, permettent de programmer en objet, sans y contraindre.
L'objet lui est une surcouche. D'autres, comme le C++, sont une évolution objet d'un langage
procédural. A l'inverse, l'approche objet a dicté la conception de Java, et il n'est pas envisageable de programmer avec ce langage dans le style procédural.
3. Les applications possibles
Java est un langage versatile. Il s'applique à une grande variété d'utilisations.
1. Les applications web
C'est actuellement le domaine dans lequel Java se développe le plus. Beaucoup de sites
web d'envergure fonctionnent avec cette technologie.
En programmation Internet se pose toujours la question de la plate-forme d'hébergement,
souvent imposée par le fournisseur de service. Par son indépendance vis-à-vis de la plateforme d'exécution, Java répond bien à cette problématique.
2. Les application graphiques dites "lourdes"
Java permet de construire des applications fenêtrées traditionnelles, avec le principe d'indépendance par rapport au système hôte.
Néanmoins, l'utilisation de Java pour le développement d'application fenêtrées est toujours
restée, jusqu'à présent, assez limitée.
Sun propose depuis longtemps deux librairies graphiques :
•
AWT : c'est la bibliothèque historique. Elle exploite les composants2 natifs de la plateforme d'exécution. L'avantage est que la réactivité de l'interface est bonne, comparable aux autres types d'interfaces. Mais comme l'application doit pouvoir s'exécuter
1
L'extension ClassPath à la licence GNU GPL permet d'utiliser cette JVM GPL sans pour autant que les applications soient elles aussi nécessairement sous licence GPL
2
boutons, listes déroulantes, champs texte...
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
3/44
sur toutes les systèmes, on ne peut utiliser que les composants graphiques représentant le dénominateur commun à toutes les plates-formes : on est donc très limité.
•
Swing : Au lieu de faire appel aux éléments graphiques (widgets) proposés par le
système hôte, Swing les dessine elle-même3. Il n'y a donc plus de limite à la créativié.
Par contre cela induit une lourdeur et des temps d'affichage qui grèvent les performances de façon non négligeable. Par ailleurs, Swing n'est pas esthétiquement très
flatteur.
Illustration 2: Exemple d'application Swing s'exécutant sous
Linux : PDFSAM
Depuis quelques années, IBM propose une alternative intéressante : SWT. SWT réunit le
meilleur des deux mondes en utilisant les composants natifs lorsqu'ils existent, et en dessinant elle-même les widgets lorsque c'est nécessaire. Les applications SWT sont esthétiques
et performantes. Le frein à la démocratisation de SWT est à imputer à Sun qui refuse toujours d'inclure SWT comme bibliothèque standard dans les spécifications Java.
L'environnement de développement Eclipse est bâti sur SWT4.
3. Les applications mobiles
Des JVM existent pour les terminaux de petite taille. On distingue deux types de terminaux :
•
Ceux dont la puissance est suffisante pour implémenter la totalité des spécifications
Java, comme les PDA ou les téléphones portables évolués (smart phones)5. Dans ce
cas la portabilité des applications entre ces terminaux et le reste des plates-formes
plus conventionnelles est assurée.
•
Ceux dont la puissance est limitée et qui n'implémentent qu'une partie des spécifications Java6. Ces terminaux ne peuvent exécuter que des applications de type CLDC.
A titre d'exemple, les jeux pour téléphones portables, de même que le navigateur
OperaMini ou GoogleEarth Mobile sont développés en Java CLDC.
3
On parle de composants pur Java
C'est d'ailleurs pour réaliser Eclispe qu'IBM a développé SWT
5
plates-formes dites CDC
6
plates-formes dites CLDC
4
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
4/44
4. Les applications en ligne de commande
Il est tout à fait possible de réaliser des applications de type console, qui peuvent s'exécuter
sur des systèmes sans interface graphique, voir même sans système d'affichage (modem,
robot...).
5. Convergence des technologies
Quelque soit le média visé, on emploie le même langage de programmation. Ainsi, en développement web, on programme la couche métier des applications web avec le même langage et les mêmes bibliothèques de fonctions que l'on utiliserait pour développer une application fenêtrée traditionnelle.
Illustration 3: Schéma d'une application web Java
Un corollaire intéressant est que l'on peut réutiliser pour le web les bibliothèques de fonctions qui ont été développées pour une application fenêtrée, et vice-et-versa.
Autre atout intéressant : on dispose pour le web de toutes bibliothèques de fonctions Java
existantes7. Quelques exemples :
•
statistiques : Apache Common Math
•
création de graphiques : jFreeCharts
•
mapping objet-relationnel : Hibernate, Oracle Toplink
•
tous les pilotes de bases de données JDBC
Par exemple, un organisme en charge d'un système d'information peut bâtir sa stratégie de
développement sur ce principe de réutilisabilité. Imaginons que nous ayons une base de
données destinée à la gestion d'enquêtes :
7
•
Nous développons dans un premier temps un logiciel de saisie pour cette base, sur
poste de travail. En bons développeurs, nous adoptons une architecture modulaire et
externalisons les fonctions qui le méritent dans des bibliothèques externes, particulièrement les composants de la couche d'accès au données.
•
Puis se fait sentir la nécessité de publier les résultats des enquêtes sur le web. Nous
développons la couche de présentation, spécifique au web. Mais la couche d'accès à
la base de données est déjà prête. Il suffit de l'importer dans le projet web et de la
connecter aux composants de présentation.
•
Enfin, pour optimiser la collecte de données, nous développons une application sur
ordinateur de poche (PDA). Là aussi, la couche d'accès aux données est réutilisée.
Seule l'interface graphique doit être adaptée à la petite surface d'affichage du terminal.
le plus souvent libres, parfois commerciales
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
5/44
•
Pour finir, ce système d'information doit être amélioré par la mise en place de contrôles d'intégrité à la saisie. Les algorithmes de vérification peuvent être implémentés
au sein d'une librairie qui sera mise à profit sur les trois interfaces.
4. La sphère Java
L'agitateur principal du monde Java reste, pour le moment, Sun Microsystems, géniteur de la
technologie. Il publie régulièrement :
•
une nouvelle version des spécifications Java
•
assortie d'une nouvelle JVM8 qui l'implémente
•
et d'un nouveau kit de développement : le JDK. Ces trois éléments constituent, à
chaque nouvelle version, l'implémentation de référence.
•
un environnement de développement intégré : NetBeans
•
un serveur d'applicartions J2EE libre et gratuit : GlassFish
•
bien d'autres pièces s'ajoutant à ce puzzle
Depuis quelques années, IBM est aussi devenu un acteur incontournable. Il propose :
•
une JVM : nommée J9
•
un serveur web/conteneur de servlets et EJB de haute volée : WebSphere
•
deux environnements de développement : Eclipse et sa déclinaison commerciale Rational Application Developer for WebSphere Software
•
des services commerciaux dont l'offre est basée sur Java
Vient ensuite BEA qui fournit essentiellement :
•
une JVM réputée pour ses performances
•
un serveur web/conteneur de servlets et EJB haut de gamme : WebLogic
La Fondation Apache contribue intensément à la sphère Java par ses contributions toujours
libres et Open Source9 :
•
Conteneur de servlets Tomcat (souvent couplé au serveur web Apache HTTP Server
de la même origine). Il fait toujours office de référence en matière d'implémentation
des spécifications Java.
•
Serveur J2EE Geronimo
•
Multiples cadriciels de développement Java :
•
8
9
•
Struts 1&2
•
Cocoon
•
Wicket
•
Tapestry
•
MyFaces
•
Velocity
Multiples bibliothèques Java librement réutilisables :
•
Lucene
•
Commons
JRE en anglais pour Java Runtime Environment
Liste des projets Apache sur http://www.apache.org/
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
6/44
•
•
Jackrabbit
CMS
•
Lenya
Cette liste n'est pas exhaustive. Les acteurs Java sont nombreux.
5. La programmation objet
Java ne peut pas être utilisé autrement qu'en manipulant des objets. Voici quelques rappels
sur cette méthode de programmation.
1. Les objets
Un objet en POO10 a le même sens qu'un objet matériel. C'est une entité qui a des propriétés
(les attributs) et des fonctions (les méthodes).
Exemple : Diadromus est un insecte parasitoïde d'environ 1 cm. Il s'agit d'une femelle en position de ponte sur son hôte (une chrysalide).
Illustration 4: Un diadromus
En POO, cet objet peut être décrit de la façon suivante :
Illustration 5: Un diadromus en POO
Plus précisément, un objet est une structure de données. La POO est donc un moyen de
structurer un programme avec les unités de données que sont les objets.
Un objet ne doit jamais manipuler directement les données internes d'un autre objet, pas
plus qu'il ne doit rendre accessible directement ses données aux autres objets. Toute communication se fait par l'intermédiaire d'appels de méthodes. L'encapsulation joue alors le rôle
de garde-fou.
10
acronyme de Programmation Orientée Objet
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
7/44
2. Les classes
Un objet matériel est toujours construit à partir d'une définition :
–
Une voiture est construite à partir d'un cahier des charges
–
Un organisme vivant est créé à partir d'une code génétique
Il en est de même pour un objet mémoire, qui est toujours construit d'après une définition
d'objet : la classe.
La classe est la description abstraite d'un objet. Inversement, on dit qu'un objet est l'instanciation d'une classe.
Une classe n'occupe pas de place en mémoire. Au contraire, un objet occupe un certain
espace mémoire.
Une classe définit les attributs et des méthodes communs à un ensemble d'objets.
Une classe représente donc une catégorie d'objets. On peut l'assimiler à un moule ou à une
usine à partir de laquelle il est possible de créer des objets. On parle alors d'un objet en tant
qu'instance d'une classe.
Voici la syntaxe de déclaration d'une classe :
public class Insecte {
// Attributes
private String nomLatin = null;
private String famille = null;
private String ordre = null;
private Float taille = null;
private String sexe = null;
private String regimeAlimentaire = null;
// Constructors
public Insecte() {
}
public Insecte(String nomLatin, String famille, String ordre,
Float taille, String sexe, String regimeAlimentaire) {
this.nomLatin = nomLatin;
this.famille = famille;
this.ordre = ordre;
this.taille = taille;
this.sexe = sexe;
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
8/44
}
this.regimeAlimentaire = regimeAlimentaire;
// Getters & Setters
public String getNomLatin() {
return nomLatin;
}
public void setNomLatin(String nomLatin) {
this.nomLatin = nomLatin;
}
public String getFamille() {
return famille;
}
public void setOrdre(String ordre) {
this.ordre = ordre;
}
public Float getTaille() {
return taille;
}
public void setTaille(Float taille) {
this.taille = taille;
}
public String getSexe() {
return sexe;
}
public void setSexe(String sexe) {
this.sexe = sexe;
}
public String getRegimeAlimentaire () {
return regimeAlimentaire;
}
public void setRegimeAlimentaire(String regimeAlimentaire) {
this.regimeAlimentaire = regimeAlimentaire;
}
}
Définition d'une classe
C'est à partir de cette déclaration que l'on peut créer une infinité d'objets de type Insecte.
En Java, le mot réservé "new" permet de fabriquer un objet à partir d'une classe :
Insecte diadromus = new Insecte();
Insecte dinarmus = new Insecte();
3. L'encapsulation
L’encapsulation est l'idée de cacher l'information contenue dans un objet et de ne proposer
que des méthodes de manipulation de cet objet. Ainsi, les propriétés et axiomes associés
aux informations contenues dans l'objet seront assurés/validés par les méthodes de l'objet et
ne seront plus de la responsabilité de l'utilisateur extérieur. L'utilisateur extérieur ne pourra
pas modifier directement l'information et risquer de mettre en péril les axiomes et les propriétés comportementales de l'objet.
L'objet est ainsi vu de l'extérieur comme une boîte noire ayant certaines propriétés et ayant
un comportement spécifié. La manière dont ces propriétés ont été implémentées est alors
cachée aux utilisateurs de la classe. On peut changer cette implémentation sans changer le
comportement extérieur de l'objet. Cela permet donc de séparer la spécification du comportement d'un objet de l'implémentation pratique de ces spécifications.
4. Relations entre classes : l'exemple de l'héritage
L’héritage est un principe permettant entre autre la réutilisabilité et l'adaptabilité des objets.
Elle se nomme ainsi car le principe est en quelque sorte le même que celui d’un arbre généalogique. Ce principe est basé sur des classes dont les "filles" héritent des caractéristiques de leur(s) "mère(s)".
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
9/44
Les classes possèdent des attributs et/ou des méthodes qui leurs sont propres, et qui pourront être transmis aux classes filles découlant des classes mères.
Chacune des classes filles peut donc posséder les mêmes caractéristiques que ses classes
mères et bénéficier de caractéristiques supplémentaires à celles de ces classes mères.
Chaque classe fille peut, si le programmeur n'a pas défini de limitation, devenir à son tour
classe mère.
Illustration 6: Exemples d'héritage entre classes
2. Les bonnes pratiques du développement web en Java
1. L'architecture de base
Pour le développement web, Java propose plusieurs outils11 :
•
les servlets : ce sont des classes Java (écrites en Java pur) qui ont la particularité
d'admettre en entrée une requête HTTP, émise par un navigateur, et de lui renvoyer
une réponse HTTP. Une servlet ne peut s'exécuter que sur un conteneur (serveur) de
servlets, puisque qu'il est le seul à pouvoir lui fournir la requête HTTP dont elle a besoin pour fonctionner.
•
les JSP : Une Java Server Page est l'équivalent Java d'une page PHP. Elle porte l'extension .jsp. C'est un fichier qui mêle du code HTML et des morceaux de code Java
(les scriplets). Lorsqu'une JSP est appelée pour la première fois par un client :
11
Nous passons sous silence les notions d'EJB et de conteneur d'EJB qui dépassent le cadre
de ce cours.
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
10/44
•
•
elle est compilée par le serveur et devient alors une servlet12
•
la servlet résultante est exécutée et renvoie son résultat sous forme d'un flux
HTML compréhensible par le navigateur du client.
•
Lors des appels suivants, l'opération de compilation n'est plus nécessaire puiqu'elle a déjà été réalisée. Seule l'exécution a lieu. La compilation ne se produit à
nouveau que si la JSP a été modifiée par un développeur entre temps.
le conteneur de servlets : les servlets s'exécutent dans un moteur (ou serveur, ou
conteneur) de servlet. C'est un programme couplé au serveur web, exactement de la
même façon que le moteur PHP est couplé au serveur web. Là où PHP prend en
charge les fichiers *.php que lui envoie le serveur web, le conteneur de servlets assure le traitement des fichiers Java (JSP et servlets) et retourne leur résultat au serveur web.
Illustration 7: Principe d'exécution des servlets
A partir de ces éléments de puzzle, plusieurs architectures techniques sont possibles :
•
une application basée exclusivement sur des JSP. Le fonctionnement s'apparente
alors à celui d'une application PHP.
•
une application basée exclusivement sur des servlets. Tout la code HTML se retrouve encapsulé dans des classes Java.
•
une application qui fait interagir servlets et JSP.
Dans les deux premiers cas, le code métier (accès aux données de la base de données, algorithmes de calcul...) et le code de présentation graphique (HTML et CSS) se retrouvent
mêlés dans les mêmes fichiers.
Avec la troisième méthode, on commence à entrevoir la notion de séparation des couches
métier et présentation. Et c'est dans ce but que Sun a proposé, dès le début, ces deux outils
qui, au demeurant, peuvent paraître redondants. L'idée est la suivante : Le code métier est
encapsulé dans des servlets, alors que le code de présentation se retrouve dans les JSP,
entités plus facilement manipulables13. Des mécanismes permettent de faire communiquer
les deux.
En réalité, développer une application qui sépare les traitements et la présentation avec les
seuls outils de base proposés par Java (servlets et JSP), est un véritable sacerdoce. C'est la
12
Il est possible de forcer la compilation de toutes les JSP d'un projet dès son déploiement
sur le serveur, de sorte que la réactivité du site soit maximum dès sa première consutation.
13
puisque leur compilation est transparente et leur modification peut se faire à chaud
sur le serveur.
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
11/44
raison pour laquelle sont apparus assez rapidement des frameworks14 de développement
MVC, venus pour faciliter et rationaliser le développement web.
2. Utilisation de frameworks
Un framework est un ensemble de bibliothèques, d'outils et de conventions qui jouent le rôle
de guide architectural. Il impose un découpage en modules, un cadrage rigoureux des flux
de données entre ces modules et propose des facilités pour mettre en place des fonctionnalités récurrentes dans beaucoup de systèmes d'information :
•
séparation des couches métier et présentation
•
internationalisation de l'interface
•
validation des formulaires
•
composants graphiques prêts à l'emploi
•
pools de connexion
•
etc...
De même qu'il existe en construction plusieurs styles d'architecture, il existe en génie logiciel
plusieurs modèles de conception. Chaque framework Java permet de suivre un ou plusieurs
de ces modèles. En voici quelques exemples :
•
Modèle-Vue-Contrôleur (MVC) : implémenté par Struts, Webwork (pour le web), JSF,
Swing (pour le client lourd)
•
Orienté composants : JSF, MyFaces
•
Orienté aspect : Spring
Nous allons nous focaliser sur le modèle le plus populaire – le MVC – et le mettre en œuvre
via le framework Struts 2.
3. Un modèle de développement éprouvé : le MVC
Le Modèle-Vue-Contrôleur est une architecture et une méthode de conception qui organise
l'interface Homme-machine d'une application logicielle. Ce modèle d'architecture impose la
séparation entre les données, la présentation et les traitements, ce qui donne trois parties
fondamentales dans l'application finale : le modèle, la vue et le contrôleur.
1. Le modèle
Le modèle représente le comportement de l'application : traitements des données, interactions avec la base de données, etc. Il décrit ou contient les données manipulées par l'application. Il assure la gestion de ces données et garantit leur intégrité. Dans le cas typique
d'une base de données, c'est le modèle qui la contient. Le modèle offre des méthodes pour
mettre à jour ces données (insertion, suppression, changement de valeur). Il offre aussi des
méthodes pour récupérer ces données. Les résultats renvoyés par le modèle sont dénués de
toute présentation.
2. La vue
La vue correspond à l'interface avec laquelle l'utilisateur interagit. Sa première tâche est de
présenter les résultats renvoyés par le modèle. Sa seconde tâche est de recevoir toutes les
actions de l'utilisateur (clic de souris, sélection d'une entrées, boutons, …). Ses différents
évènements sont envoyés au contrôleur. La vue n'effectue aucun traitement, elle se contente
14
francisé en cadriciel ou cadre de développement
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
12/44
d'afficher les résultats des traitements effectués par le modèle. Plusieurs vues, partielles ou
non, peuvent afficher des informations d'un même modèle.
La vue peut être conçue en HTML, ou tout autre « langage » de présentation.
3. Le contrôleur
Le contrôleur prend en charge la gestion des évènements de synchronisation pour mettre à
jour la vue ou le modèle et les synchroniser. Il reçoit tous les évènements de l'utilisateur et
enclenche les actions à effectuer. Si une action nécessite un changement des données, le
contrôleur demande la modification des données au modèle et ensuite avertit la vue que les
données ont changé pour qu'elle se mette à jour. Certains évènements de l'utilisateur ne
concernent pas les données mais la vue. Dans ce cas, le contrôleur demande à la vue de se
modifier. Le contrôleur n'effectue aucun traitement, ne modifie aucune donnée. Il analyse la
requête du client et se contente d'appeler le modèle adéquat et de renvoyer la vue correspondante à la demande.
Illustration 8: Principe du modèle de développement MVC
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
13/44
3. TP MVC avec Struts 2
1. Objectifs du TP
Cette introduction à Java/web n'a pas la prétention de vous apprendre à programmer en
Java. Son but est plutôt :
•
de vous offrir un panorama des possibilités de ce langage
•
de vous sensibiliser à de nouvelles méthodes de programmation web (le MVC en
l'occurence)
•
de vous montrer comment on peut les mettre en œuvre avec Java
Nous avons vu que la caractéristique fondamentale de la programmation MVC est de scinder
les développements en deux parties distinctes : la programmation des classes métier (le modèle) d'un côté et la réalisation de l'interface graphique (les vues) de l'autre.
Sur de gros projets, cela permet d'attribuer chaque tâche aux personnes les plus
compétentes :
•
le modèle aux informaticiens Java
•
la vue aux designers web
Dans le cadre de ce TP, nous allons nous mettre dans la peau du designer web et voir que,
mise à part la phase de démarrage d'un projet sous Eclipse15, nous pouvons développer les
interfaces de visualisation sans avoir de connaissances Java.
2. Présentation de Struts 2
Struts a été créé par Craig McClanahan et donné à la Fondation Apache en 2000. La Fondation en assure depuis la maintenance et l'évolution.
Struts fût le premier framework de qualité professionnelle mettant en œuvre le modèle MVC
pour développer des applications web en Java. Comme il était le seul, il est devenu de facto
le framework de référence.
Si un gros projet avait beaucoup à gagner à utiliser Struts, sa lourdeur et sa complexité obligeaientt à se poser la question de son utilité dans le cadre de projets plus réduits. Selon Wikipédia :
"En utilisant Struts, le développeur simplifie son travail au niveau des vues et des contrôleurs
du modèle MVC. Mais il serait inadapté d'utiliser ce framework dans des projets de petite
taille car il introduit une certaine complexité. Struts montre toute sa puissance dans des applications d'une certaine envergure."
Entre temps, quantité de frameworks se voulant plus simples sont apparus, mais l'inertie du
monde industriel a fait que Struts est resté pendant longtemps majoritaire. Les chefs de projet avaient trouvé en Struts un gage de stabilité, dans une sphère Java toujours en mouvement.
En ce moment, la page Struts 1 est en train de se tourner. Apache publie toujours des versions de Struts 1, mais les sorties se raréfient et ne concernent plus que les mises à jour de
15
qui ne revient normalement pas au designer
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
14/44
sécurité. Face aux critiques et à la concurrence d'autres frameworks, Apache concentre
maintenant tous ses efforts à la promotion de Struts 2, sorti en avril 2007.
Struts 2 est la réunion de deux projets : Struts 1 et Webwork, un autre framework MVC de
génération plus avancée.
Illustration 9: Origines de Struts 2
En réalité, Struts 2 ressemble beaucoup plus à Webwork qu'à Struts 1 : L'essentiel des
concepts de Webwork ont été adoptés, améliorés et regroupés sous l'appellation très populaire Struts, version 2.
Avec Struts 2, concevoir en MVC devient facile et s'applique à tous types de projets, même
les plus simples.
3. Démarrage d'un projet Struts 2 sous Eclipse
1. Prérequis :
•
Une installation d'un JDK Java 6 (kit de développement)
•
Une installation d'une machine virtuelle Java JRE 6 (incluse par défaut dans le JDK)
•
Eclipse Europa (v3.3), version pour J2EE
•
Tomcat 5.5 ou 6
•
un répertoire contenant les bibliothèques suivantes :

Pilote JDBC de PostgreSQL : postgresql-8.x-xxx.jdbc4.jar

Struts 2 et ses dépendances16 :

struts-2-core

xworks

freemarker

ognl

antlr

common-logging (ces 6 fichiers sont fournis dans l'archive de Struts 2)

commons-fileupload

commons-io (ces 2 fichiers sont fournis dans la paquet commons d'Apache)
2. Création du projet
1) File/New/Project...
2) Web/Dynamic Web Project...
16
Les versions des librairies ne sont pas indiquées. Les noms des fichiers sont de la forme
[nom-librairie]-[version].jar
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
15/44
Illustration 10: Création d'un projet web dynamique
3) "Project name" : BaseIsotopes
Illustration 11: Configuration du nouveau projet
3. Création d'une configuration d'exécution
Une configuration d'exécution met en relation une installation existante d'un serveur (comme
Tomcat) et l'environnement de développement Eclipse. C'est par cette configuration qu'Eclipse est en mesure de piloter directement le serveur : démarrage, arrêt, basculement en
mode normal/débogage, chargement de code à chaud, insertion de points d'arrêt et analyse
des variables sont les principales fonctions disponibles. Pour la créer :
1) Target Runtime : New...17
17
Nous profitons ici de la création d'un nouveau projet pour créer aussi une configuration
d'exécution. Cependant, cette configuration ne sera pas réservée à ce projet mais sera
disponible à tout projet web de cet espace de travail.
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
16/44
2) Choisissez "Apache/Apache Tomcat v5.5" ou "v6.0" (suivant ce qui est installé sur
votre poste de travail) comme type de serveur.
Illustration 12: Création d'une configuration d'exécution
3) Faites "Next"
Illustration 13: Création d'une nouvelle configuration de serveur
4) Name : On fournit ici un nom à la configuration : Nous choisissons arbitrairement
"Notre serveur Tomcat"
5) Tomcat installation directory : Ici, le but est de localiser le répertoire physique d'installation de Tomcat sur votre machine. Eclipse nécessite cette information pour pouvoir
le piloter.
6) JRE : choisissez la JRE (machine virtuelle) par défaut de l'environnement18
7) Next
18
On pourrait disposer de plusieurs JRE sur notre machine et décider de celle qui devrait être
utilisée.
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
17/44
Illustration 14: Réglage des options du projet
Laissez la configuration par défaut comme indiqué sur l'illustration.
4. Poursuite de la création du projet
1) Next
Illustration 15: Dernier écran de la création du projet
2) Finish
Le projet est créé. L'espace de travail ressemble maintenant à ceci :
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
18/44
Illustration 16: Espace de travail avec le nouveau projet
A ce stade :
–
Eclipse a créé un nouveau projet d'application web nommé "BaseIsotopes"
–
Eclipse a généré la structure (répertoires/fichiers de configuration) nécessaire pour
être en conformité avec les spécifications Java.
–
Le projet est associé à une configuration d'exécution (launch configuration), c'est-àdire à un serveur (conteneur) de servlets sur lequel il peut être exécuté via les commandes Start/Stop/Debug d'Eclipse.
5. Paramétrages supplémentaires
Par défaut, Eclipse place le code compilé dans le dossier BaseIsotopes/build/classes. Il
faut modifier cette destination et indiquer : BaseIsotopes/WebContent/WEB-INF/classes
Pour cela : [clic droit sur le projet]/Build path/Configure build path...
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
19/44
Illustration 17: Accès à l'écran de configuration de la compilation du projet
Modifiez le champ Default output folder :
Illustration 18: Ecran de configuration de la compilation du projet
4. Arborescence d'un projet web Java
Pour pouvoir être déployé sur un moteur de servlets, tel que Tomcat, tout projet web Java
doit, au minimum, se conformer aux règles suivantes :
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
20/44
Répertoire ou ficher
Contenu
<webapp>/WEB-INF/web.xml
fichier de configuration de l'application
<webapp>/WEB-INF/classes
classes compilées
<webapp>/WEB-INF/lib
librairies diverses sous forme de fichiers JAR
<webapp>/<autres_repertoires>
les vues : fichiers HTML, JSP...
les ressources : fichiers images, sons...
Illustration 19: Arborescence d'un projet web
Cette Arborescence est mise en place par Eclipse dès la phase de création du projet.
Évidemment, en phase de développement, le dossier du projet contient aussi un sous-dossier dans lequel sont stockés les fichiers sources.
Lors du déploiement sur un serveur, ce sous-dossier de sources pourra faire partie du dossier de l'application, mais les fichiers sources ne sont absolument pas nécessaires à l'exécution de l'application.
5. Inclusion de bibliothèques
Les bibliothèques de fonctions, en Java, sont toujours fournies sous forme de fichiers *.jar.
C'est un fichier ZIP respectant une arborescence donnée : l'arborescence des fichiers JAR
définie dans les spécifications Java.
Les librairies nécessaires au projet peuvent se trouver :
A) A l'extérieur du projet et y être reliées par des liens. Ces liens ou dépendances se
configurent dans l'écran Java Build Path (illustration suivante), onglet Libraries.
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
21/44
Illustration 20: Fenêtre de configuration des librairies
Il existe plusieurs méthodes pour lier des librairies JAR à un projet Eclipse :
•
Add JAR : L'archive JAR se trouve déjà dans l'espace de travail Eclipse (dans un
autre projet de l'espace de travail par exemple) : Dans ce cas, on peut créer un
lien pour cette librairie entre les deux projets, sans qu'elle ne soit recopiée.
•
Add External JAR : L'archive JAR se trouve à l'extérieur de l'espace de travail,
quelque part sur le disque dur. Dans ce cas on peut créer un lien entre le projet et
le système de fichiers, sans recopier le fichier.
•
Add Variable : Par ce bouton il est possible d'inclure dans le classpath (chemin
de compilation) des variables qui contiennent les chemins vers des répertoires.
Ces répertoires seront scrutés à chaque compilation, dans leur ordre d'apparition,
pour y trouver les bibliothèques requises.
•
Add Library : Fournit encore d'autres méthodes pour inclure des librairies au projet, comme les librairies utilisateurs (User libraries).
B) Physiquement dans l'arborescence du projet
Dans le cadre de ce TP, nous mettons en œuvre la seconde méthode (B) : copie des librairies dans l'arborescence du projet19.
1) Faites [clic droit sur WebContent/WEB-INF/lib]/Import...
19
Ceci facilite l'exportation et le déploiement du projet sur un serveur tiers puisque les
librairies seront automatiquement intégrées dans le fichier résultat de l'exportation :
le fichier WAR.
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
22/44
Illustration 21: Importation de librairies dans le projet
2) File System...
Illustration 23: Importation depuis le système de fichiers
Illustration 22: Sélection du JAR pilote JDBC de PostgreSQL
3) Next
4) Localisez et sélectionnez le pilote JDBC de PostgreSQL sur le disque dur et valider.
5) Attention à bien cocher le fichier JAR (fenêtre de droite), et non pas son répertoire
conteneur (fenêtre de gauche).
6) On fait de même pour les librairies de Struts 2 :
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
23/44
Illustration 24: Sélection des librairies de Struts 2 et de leurs dépendances
Après validation, l'arborescence du projet devient :
Illustration 25: Arborescence du projet
après adjonction des librairies
On peut retourner dans l'écran Java Build Path/Libraries pour s'assurer que ces librairies seront bien pries en compte lors de la compilation :
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
24/44
Illustration 26: Instructions de compilation après ajout des librairies
6. Mise en place du filtre Struts 2 dans le fichier web.xml
WEB-INF/web.xml est le fichier de configuration général de toute application web Java.
C'est lui qui indique au serveur Tomcat comment gérer l'application.
Par défaut, Eclipse génère ce fichier avec le contenu suivant :
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/webapp_2_4.xsd">
<display-name>
BaseIsotopes
</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
La première ligne est l'entête XML classique.
<display-name> correspond au nom du projet.
<welcome-file-list> indique quelle doit être la page affichée si un utilisateur se présente sur le
serveur sans requêter de page particulière. C'est le fichier d'accueil. Les fichiers sont recherchés les uns après les autres, dans l'ordre de la liste, jusqu'à ce que l'un d'eux soit trouvé.
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
25/44
Nous commençons par épurer cette section en ne laissant que le fichier suivant :
<welcome-file>webpages/index.jsp</welcome-file>
Notez l'adaptation du chemin d'accès à ce fichier.
Puis nous mettons en place le filtre Struts 2 dont le but est de rediriger toutes les requêtes
vers le contrôleur de Struts. Cela donne finalement :
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/webapp_2_4.xsd">
<display-name>
BaseIsotopes
</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- Struts 2 filter -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<!-- Struts 2 filter mapping -->
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Les deux sections filter et filter-mapping indiquent au serveur que tous les types de requêtes reçues du client (symbolisées par /*) seront dirigées et prises en charge par l'aiguilleur de Struts 2 (org.apache.struts2.dispatcher.FilterDispatcher).
Nous n'entrerons pas dans les détails des possibilités de configuration de ce fichier.
7. Le contrôleur : le fichier struts.xml
1. Le contrôleur sous Struts 2
Nous avons vu que le point névralgique d'une application MVC est le contrôleur. Le contrôleur est l'aiguilleur qui reçoit et adresse toutes les requêtes et toutes les réponses. C'est le
passage obligé pour tous les flux d'information qui circulent dans l'application.
Sous Struts 2, l'unique élément visible du contrôleur est un fichier XML : struts.xml
Toute la configuration du contrôleur se fait dans ce fichier. En réalité, le contrôleur est un jeu
de classes Java, pilotées par ce fichier. Donc, dans la suite du TP, par simplification, nous
appelerons contrôleur le fichier struts.xml lui-même.
2. Localisation du fichier
Dans le projet exécutable, sa localisation doit être :
[nom_projet]/WebContent/WEB-INF/classes/struts.xml
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
26/44
Dans le projet en phase de développement sous Eclipse, une bonne solution est de le placer
dans :
[nom_projet]/src/struts.xml
Ainsi, à chaque compilation, il sera recopié automatiquement au bon endroit :
[nom_projet]/WebContent/WEB-INF/classes/struts.xml
3. Création du fichier
A la différence de web.xml qui est un fichier requis dans toute application web, struts.xml est
propre à une application qui utilise Struts. Pour cette raison, il n'est pas généré automatiquement par Eclipse. Il nous revient donc de le créer.
1) Ouvrez l'assistant de création de fichier
Illustration 27: Ouverture de l'assistant de création de fichier
2) Type d'entité à créer : File...
3) Localisation et nom de fichier : [projet]/src/struts.xml
Illustration 28: Type d'entité à créer : fichier
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
27/44
Illustration 29: Localisation du nouveau fichier
8. Structure et contenu de base
Nous allons utiliser la structure suivante comme base de travail.
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration
2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="true" />
<constant name="struts.url.includeParams" value="none" />
<package name="default" extends="struts-default">
</package>
</struts>
La fonction contrôleur est concentrée dans la section <package>. Elle est actuellement vide.
Collez ce fragment de document XML à l'intérieur de votre fichier struts.xml fraîchement
créé.
Les tâches de configuration du projet Struts 2 sont à présent terminées. Nous allons pouvoir
nous concentrer sur le développement des trois modules de l'application : modèles, vues et
contrôleur.
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
28/44
9. Importation du Modèle préexistant
S'agissant d'un TP d'initiation, nous n'allons programmer que les interfaces graphiques. Pour
ce faire, nous allons exploiter un modèle préexistant qui a été préparé pour l'occasion.
Le modèle vous est fourni sous forme de fichiers de classes Java20.
Ce modèle est partiel : il permet seulement d'afficher le contenu des tables PECHE, INDIVIDU et PRELEVEMENTS.
1. Procédure d'importation des fichiers
Créez deux paquetages (packages) :
Illustration 30: Création de paquetages
–
org.ird.crh.baseisotopes.pojos
–
org.ird.crh.baseisotopes.strutsactions
Illustration 31: Nommage des paquetages
2. Sur chaque paquetage (vide) :
–
[clic droit]/Import.../File System
20
Les fichiers source (format texte) portent l'extension *.java. Les fichiers compilés (binaires,
bytecode) portent l'extension *.class.
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
29/44
–
recherchez sur votre disque dur (ou sur le répertoire partagé de la formation) les fichiers
suivants :
–
–
Pour le paquetage org.ird.crh.baseisotopes.pojos :
–
Individu.java
–
Peche.java
–
TypePrelevement.java
–
Prelevement.java
–
Taxon.java
Pour le paquetage org.ird.crh.baseisotopes.strutsactions :
–
AfficherIndividus.java
–
AfficherPeches.java
–
AfficherRecherche.java
–
Validez pour effectuer l'importation
–
Le projet devient :
Illustration 32: Arborescence du projet
10.Documentation des classes fournies
En tant que développeurs de l'interface graphique, nous devons considérer que les classes
fournies par les développeurs Java sont des boîtes noires, dont nous ne savons que ce qui
est décrit dans la documentation.
Voici cette documentation. C'est elle qui va nous guider pour réaliser l'interface :
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
30/44
Classe
Paramètres en entrée
Paramètres en sortie
Actions Struts 2
AfficherPeches
[aucun]
- ArrayList<Peche> peches : une
liste iterable contenant toutes
les pêches de la base de données
sous forme d'objets de type Peche
(AfficherPeches.java)
- codes de retour : SUCCESS
AfficherIndividus
(AfficherIndividus.java)
- int idPeche : l'identifiant de la pêche pour laquelle les individus seront
affichés
- ArrayList<Individu> individus :
une liste iterable contenant tous
les individus de la pêche concernée sous forme d'objets de type
Individu
- codes de retour : SUCCESS
- String typePrelevement : - ArrayList<Taxon> taxons : une
le type de prélèvement à liste iterable qui contient les
(AfficherRecherche.java) rechercher
taxons disponibles dans la base de
données. Peut être utilisée pour
- int taxon : le taxon à construire une liste déroulante de
rechercher
tous les taxons.
AfficherRecherche
- ArrayList<TypePrelevement> typesPrelevement : une liste iterable qui contient les types de
prélèvements disponibles.
Peut
être utilisée pour construire une
liste déroulante de tous les types
de prélèvements.
- ArrayList<Prelevement> prelevements : une liste contenant le
résultat de la requête sous forme
de prélèvements.
Pojos (objets conteneurs d'information)
Peche
(Peche.java)
Individu
(Individu.java)
Prelevement
(Prelevement.java)
- int id : l'id de la pêche
- String idCampagne : l'id
de la campagne dont la
pêche fait partie
- String idPecheCampagne
- Date datePeche
- String saison
- String association
- String localisation
- String positionPeche
- double latitudePeche
- double longitudePeche
- int id : l'id de la pêche
- String idCampagne : l'id de la
campagne dont la pêche fait partie
- String idPecheCampagne
- Date datePeche
- String saison
- String association
- String localisation
- String positionPeche
- double latitudePeche
- double longitudePeche
-
int id
int idPeche
int idEspece
int indIdIndividu
int idIndividuPeche
Double tailleLfIndividu
Double poidsIndividu
String sexeIndividu
int numEstomac
Time heureCapture
-
int id
int idPeche
int idEspece
int indIdIndividu
int idIndividuPeche
Double tailleLfIndividu
Double poidsIndividu
String sexeIndividu
int numEstomac
Time heureCapture
- int idPrelevement
- int idIndividu
- String identifiantPilulier
-
int idPrelevement
int idIndividu
String identifiantPilulier
String typePrelevement
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
31/44
Classe
Taxon
(Taxon.java)
TypePrelevement
(TypePrelevement.java)
Paramètres en entrée
Paramètres en sortie
-
String typePrelevement
Time heurePrelevement
String rq
String typeDessication
boolean broye
boolean delipide
String typeSolvant
String laboNbEnvoi
double c
double n
double dc
double dn
-
Time heurePrelevement
String rq
String typeDessication
boolean broye
boolean delipide
String typeSolvant
String laboNbEnvoi
double c
double n
double dc
double dn
-
int id
String codeEspece
String nomEspeceLatin
String categorie
-
int id
String codeEspece
String nomEspeceLatin
String categorie
- String id
- String label
- String id
- String label
11.Développement des interfaces graphiques
Nous allons développer quatre pages JSP :
–
une page d'accueil basique
–
une page qui affichera toutes les pêches de la base de données
–
une page qui affichera les individus rattachés à une pêche
–
un page qui affichera une interface de recherche de prélèvements et les résultats de
recherche
Puis nous les mettrons en relation avec le modèle (sans lequel elles ne peuvent pas fonctionner) en configurant le contrôleur.
1. Première page : index.jsp
Dans le répertoire WebContent de notre projet, créez un sous-répertoire nommé webpages.
Il contiendra tout les fichiers relatifs à l'interface graphique : HTML, JSP, CSS, JavaScript...
Dans ce nouveau répertoire créez une nouvelle page JSP en utilisant l'assistant ad-hoc.
Nommez-le index.jsp ([clic droit]/New/JSP).
Son contenu doit être (en jaune ce qui a été modifié/rajouté par rapport au modèle créé par
Eclipse) :
<?xml version="1.0" encoding="UTF-8" ?>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Base Isotopes - Accueil</title>
<style type="text/css" media="all">@import url("<s:url value="/webpages/outils/style.css"/>");</style>
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
32/44
<s:head/>
</head>
<body>
<div id="container">
<div id="bandeau"></div>
<div id="contenu">
<h1>Base Isotopes</h1>
<h2>Cliquez ici pour afficher toutes les pêches :
<s:url id="url" action="AfficherPeches" />
<s:a href="%{url}"><s:property value="url" /></s:a>
</h2>
<h2>Cliquez ici pour effectuer une recherche :
<s:url id="url" action="AfficherRecherche" />
<s:a href="%{url}"><s:property value="url" /></s:a>
</h2>
</div>
<div id="pieddepage"><a href="http://www.ird.fr">Site de
l'IRD</a></div>
</div>
</body>
</html>
A) Analyse du contenu
–
l'en-tête taglib21 : elle signale que dans cette page, des balises Struts 2 vont pouvoir
être utilisées (et donc interprétées par le moteur Struts 2). Toutes ces balises seront
préfixées par "s:". On aurait pu choisir un autre préfixe.
–
<s:head/> : déclaration complémentaire à la précédente. Ces deux balises sont
nécessaires à l'activation des fonctions Struts.
–
<s:url.../> est la première balise Struts fonctionnelle que nous rencontrons. Son rôle
est de construire une URL qui pointera vers une "Action"22, nommée
"AfficherPeches". Nous verrons plus loin à quoi cela correspond.
–
<s:a.../> est une balise dont le but est similaire à celui de la traditionnelle balise
HTML <a.../>. Associée à l'URL que nous venons de créer avec la balise <s:url.../>,
elle va générer un lien hypertexte conduisant à notre future Action "AfficherPeches".
B) Mise à jour du contrôleur
Dans le fichier web.xml, nous avons indiqué que index.jsp est le fichier d'accueil de l'application. Donc si une requête arrive sur le serveur sans demander une action particulière23, c'est
index.jsp qqui sera affichée.
Toutefois, pour les besoins de la navigation du site, il peut être intéressant de déclarer dans
le contrôleur une action qui mènera aussi sur la page d'accueil.
21
Le mécanisme des taglibs permet d'enrichir les fonctionnalités de base des pages JSP.
Dans notre cas, nous enrichissons les fonctionnalités de notre JSP en y important la bibliothèque de balises fournie par Struts 2.
22
Une Action, en langage Struts 2, est une classe ( un programme) Java qui a la particularité
de s'exécuter juste avant l'affichage d'une interface graphique, et qui permet d'effectuer tout
type de traitement et d'initialiser les variables nécessaires à la construction de la page. En
d'autres termes, une Action est une fraction du modèle. On peut aussi dire que le modèle est
constitué de multiples classes Action.
23
requête similaire à http://localhost:8081/BaseIsotopes/
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
33/44
Nous appelons cette action "AfficherAccueil".
Le contrôleur devient :
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration
2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant
<constant
<!-- Pour
la page suivante
<constant
name="struts.enable.DynamicMethodInvocation" value="false" />
name="struts.devMode" value="true" />
éviter que les paramêtres de la requêtes soient répétés dans
-->
name="struts.url.includeParams" value="none" />
<package name="default" extends="struts-default">
<action name="AfficherAccueil">
<result>/webpages/index.jsp</result>
</action>
</package>
</struts>
C) Première exécution
Pour exécuter ce début de projet, il suffit de :
–
faire [clic droit sur le projet]/Run As/Run On Server
Illustration 33: Lancement du projet
–
sélectionner la configuration de lancement que nous avons créée en début de projet,
et cocher l'option "Always use this server when running this project"
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
34/44
Illustration 34: Attribution d'une configuration de lancement au
projet
–
Si on vous y invite, cocher la case "Update Context Root..."
–
Validez
–
Un navigateur web doit s'ouvrir dans Eclipse et afficher notre première page
–
Il est tout-à-fait possible de faire un copier/coller de l'url qui s'affiche dans ce navigateur
et de la copier dans votre navigateur habituel. Le résultat doit être le même.
C) Principe de fonctionnement
Un navigateur web ne comprend que des balises HTML. Il ne comprendrait donc pas nos balises Struts.
En réalité, le navigateur du client ne recevra jamais les balises Struts. Avant que la réponse
ne lui soit renvoyée, le fichier JSP sera analysé (parsé) et toutes les balises Struts seront
converties en code HTML.
Ainsi :
–
La balise <s:url...> va disparaître du flux-réponse. Par contre elle aura conduit à la
génération d'une variable (dans la mémoire du serveur) – une chaîne de texte –
contenant une URL relative du type : /BaseIsotopes/webpages/AfficherPeches.action
–
La balise <s:a.../> aura été convertie en une balise HTML <a...> (lien hypertexte)
pointant vers l'URL construite précédemment.
–
Extrait de la réponse générée par cette JSP :
<body>
<div id="container">
<div id="bandeau"></div>
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
35/44
<div id="contenu">
<h1>Base Isotopes</h1>
<h2>
Cliquez ici pour afficher toutes les pêches :
<a href="/BaseIsotopes/webpages/AfficherPeches.action">
/BaseIsotopes/webpages/AfficherPeches.action
</a>
</h2>
<h2>Cliquez ici pour effectuer une recherche :
<a href="/BaseIsotopes/webpages/AfficherRecherche.action">
/BaseIsotopes/webpages/AfficherRecherche.action
</a>
</h2>
</div>
<div id="pieddepage"><a href="http://www.ird.fr">Site de l'IRD</a></div>
</div>
</body>
</html
Note : Au premier chargement, un identifiant jsessionid est ajouté. Sa génération est automatique et permet au serveur de reconnaître le client lorsque celui-ci émet une requête.
2. Deuxième page : afficher_peches.jsp
Créez une deuxième JSP nommée afficher_peches.jsp
Sont contenu sera :
<?xml version="1.0" encoding="UTF-8" ?>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Base Isotopes - Affichage des Peches</title>
<s:head/>
<style type="text/css" media="all">@import url("<s:url value="/webpages/outils/style.css"/>");</style>
</head>
<body>
<div id="container">
<div id="bandeau"></div>
<div id="contenu">
<h1>Liste des pêches existantes</h1>
<br/>
<h2>Retour Ã
l'accueil :
<s:url id="url" action="AfficherAccueil" />
<s:a href="%{url}"><s:property value="url" /></s:a>
</h2>
<table border="1">
<tr>
<td>id</td>
<td>id campagne</td>
<td>id peche-campagne</td>
<td>date</td>
<td>saison</td>
<td>association</td>
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
36/44
<td>localisation</td>
<td>position-peche</td>
<td>latitude-peche</td>
<td>longitude-peche</td>
</tr>
<s:iterator value="peches" status="state">
<tr>
<td>
<s:url id="url" action="AfficherIndividus">
<s:param name="idPeche">
<s:property value="id"/>
</s:param>
</s:url>
<s:a href="%{url}">
<s:property value="id"/>
</s:a>
</td>
<td><s:property value="idCampagne"/></td>
<td><s:property value="idPecheCampagne"/></td>
<td><s:property value="datePeche"/></td>
<td><s:property value="saison"/></td>
<td><s:property value="association"/></td>
<td><s:property value="localisation"/></td>
<td><s:property value="positionPeche"/></td>
<td><s:property value="latitudePeche"/></td>
<td><s:property value="longitudePeche"/></td>
</tr>
</s:iterator>
</table>
<h2>Retour a l'accueil :
<s:url id="url" action="AfficherAccueil" />
<s:a href="%{url}"><s:property value="url" /></s:a>
</h2>
</div>
<div id="pieddepage"><a href="http://www.ird.fr">Site de l'IRD</a></div>
</div>
</body>
</html>
A) Analyse de la section <body/>
–
Nous créons le patron d'un tableau HTML
–
Nous déclarons manuellement les en-têtes de ses colonnes
–
La documentation de l'Action AfficherPeches (cf. plus haut) nous indique que la liste
des pêches de la base de données est disponible sous forme d'un objet iterable24.
–
Nous utilisons donc la balise Struts <s:iterator/> qui prend en paramètre un objet iterable et se comporte comme une boucle for. Dans notre cas, la boucle va se réaliser
autant de fois qu'il y a de pêches dans la liste.
–
La documentation nous indique aussi que chaque objet de la liste est de type Peche :
ArrayList<Peche> peches. Cela signifie qu'une fois entré dans une itération de l'iterator, nous sommes en possession d'un objet de type Peche (classe Peche).
–
Nous consultons la documentation de la classe Peche pour savoir comment l'exploiter. Cette classe expose les trois propriétés suivantes :
•
int id
•
String idCampagne
•
String idPecheCampagne
24
En Java, un objet iterable signifie qu'il implémente l'interface iterable. En d'autres termes,
quelque soit sa forme, un objet iterable peut être saisit par un iterator et piloté de façon générique par des méthodes du type .next(), .previous, .hasNext()... pour faire défiler son
contenu. A la manière d'une boucle for.
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
37/44
–
•
Date datePeche
•
String saison
•
String association
•
String localisation
•
String positionPeche
•
double latitudePeche
•
double longitudePeche
De plus, la balise Struts qui permet de lire une propriété est :
<s:property value="nomPropriété"/>
–
Voici donc comme afficher dans une itération de la boucle les données de la pêche
considérée :
Propriété à afficher
balise à insérer dans le tableau HTML
id
<s:property value="id"/>
idCampagne
<s:property value="idCampagne"/>
idPecheCampagne
<s:property value="idPecheCampagne"/>
datePeche
<s:property value="datePeche"/>
saison
<s:property value="saison"/>
association
<s:property value="association"/>
localisation
<s:property value="localisation"/>
positionPeche
<s:property value="positionPeche"/>
latitudePeche
<s:property value="latitudePeche"/>
longitudePeche
<s:property value="longitudePeche"/>
–
il ne reste plus qu'à générer une colonne avec chaque propriété pour remplir le tableau. Exemple pour l'identifiant : <td><s:property value="idCampagne"/></td>
C) Configuration du contrôleur
Pour le moment, nous avons :
–
une page d'accueil avec un lien vers l'Action "AfficherPeches"
–
une classe Action "AfficherPeches"
–
une page JSP "afficher_peches.jsp"
Mais leur ordonnancement n'est pas encore assuré. Pour ce faire, éditez le contrôleur
(struts.xml) et complétez-le ainsi :
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration
2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="true" />
<constant name="struts.url.includeParams" value="none" />
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
38/44
<package name="default" extends="struts-default">
<action name="AfficherPeches" class="org.ird.crh.baseisotopes.strutsactions.AfficherPeches">
<result name="success">/webpages/afficher_peches.jsp</result>
</action>
<action name="AfficherAccueil">
<result>/webpages/index.jsp</result>
</action>
</package>
</struts>
D) Adaptation des paramètres de connexion à la base de données au poste local
Le nom de la base de données, l'identifiant de l'utilisateur et son mot de passe doivent être
adaptés aux paramètres de votre poste de travail :
–
nom de base : isotopes
–
utilisateur : postgres
–
mot de passe : postgres
Ces paramètres se trouvent dans la classe Action "AfficherPeches".
La même adaptation devra être faite dans les deux autres classes Action que vous aurez
l'occasion d'utiliser dans la suite du TP.
E) Exécution
Assurez-vous d'avoir sauvegardé tous les fichiers et exécutez le projet :
–
[clic droit sur le projet]/Run As.../Run on Server
F) Fonctionnement
–
En cliquant sur le lien de la page d'accueil, l'utilisateur envoie au serveur la requête :
/BaseIsotopes/webpages/AfficherPeches.action
–
Comme nous avons défini un filtre qui redirige toute requête (/*) vers Struts 2, ce dernier recherche si une action portant ce nom existe dans son contrôleur
–
L'action est trouvée. Sa classe Java correspondante est org.ird.crh.baseisotopes.strutsactions.AfficherPeches. Celle-ci s'exécute, initialise ses propriétés et rend
la main au contôleur avec un code retour donné. Dans le cas de AfficherPeche, une
classe très basique, seul le code SUCCESS peut-être retourné.
–
Le contrôleur recherche la vue nommée SUCCESS, l'exécute et envoie le résultat (le
flux HTML) au navigateur de l'utilisateur.
G) Habillage avec une feuille de style CSS
Normalement, vos pages JSP disposent déjà d'un lien vers une feuille de style CSS :
<head>
...
<style type="text/css" media="all">@import url("<s:url value="/webpages/outils/style.css"/>");</style>
...
</head>
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
39/44
Néanmoins, elle n'est pas encore prise en compte, simplement car le fichier est absent. Nous allons
l'importer dans le projet :
–
créez un sous-dossier webpages/outils,
–
importez le fichier style.css25 dans ce dossier,
–
créer un sous-dossier webpages/images,
–
importez les deux images bandeau.jpg et bg1.gif.
Rechargez les pages web. La présentation devrait être un peu plus flateuse.
Si la présentation reste identique, il y a probablement une erreur dans les chemins vers les fichiers.
Vous pouvez modifier ce chemin directement dans la page JSP si besoin.
3. Troisième page : afficher_individus.jsp
A vous de jouer !
4. Quatrième page : afficher_recherche.jsp
Vous aurez besoin des tags suivants :
<s:select label="Taxon" name="taxon" headerKey="1" list="taxons" listValue="nomEspeceLatin" listKey="id"></s:select>
–
–
permet de construire une liste déroulante à partir d'un objet itarable
–
le paramètre list="taxons" identifie l'objet iterable qui contient les données de la liste déroulante
–
le paramètre listValue="nomEspeceLatin" identifie la propriété de l'objet itéré qui
doit être affichée dans la liste
–
listKey="id" identifie la propriété de l'objet itéré qui doit être postée dans la requête
<s:form action="AfficherRecherche" method="POST">...</s:form>
–
–
balise équivalente à la balise HTML <form>. Les éléments de formulaires, comme les listes et
les boîtes de texte, doivent être encadrées par la balise de déclaration de formulaire
<s:submit />
–
–
balise qui déclare un bouton de soummission du formulaire
25
Vous pouvez le trouver dans le dossier de partage de la sale de formation
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
40/44
4. Conclusion
Java permet de développer des application web de façon simple, avec des pages JSP. Mais
c'est grâce à tous les outils, librairies et frameworks open source disponibles que cet environnement révèle toute sa puissance. Parmi ces outils, les plus indispensables sont les
frameworks web qui permettent de construire des applications fiables et aisément maintenables.
Lors de cette séance nous avons succinctement mis en œuvre le framework Struts 2 qui, à
lui seul, procure déjà une puissance considérable. Outre la mise en application du modèle
MVC, il offre d'autres fonctions très puissantes comme :
–
l'internationalisation avancée de l'interface
–
un mécanisme de validation des entrées de formulaires, côté serveur comme côté
client
–
la génération automatique de composants graphiques (avec la bibliothèque dojo)
–
d'autres fonctions
Pour aller plus loin dans la conception d'applications web de qualité, deux autres types d'outils doivent être considérés :
–
les mécanismes de pools de connexion, qui permettent d'améliorer significativement
les temps de réponse de la base de donnée
–
les mécanismes de mapping objet-relationnel (ORM), qui permettent de s'affranchir
de la dernière pierre non-objet dans un programme Java : le SQL.
Ces deux outils sont facilement intégrables dans une application Struts 2 et contribuent à la
fois aux performances et à la fiabilité de la partie Modèle d'une application MVC.
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
41/44
5. Annexes
1. Fichier contrôleur struts.xml du TP, complet
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration
2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant
<constant
<!-- Pour
la page suivante
<constant
name="struts.enable.DynamicMethodInvocation" value="false" />
name="struts.devMode" value="true" />
éviter que les paramètres de la requêtes soient répétés dans
-->
name="struts.url.includeParams" value="none" />
<package name="default" extends="struts-default">
<action name="AfficherPeches" class="org.ird.crh.baseisotopes.strutsactions.AfficherPeches">
<result name="success">/webpages/afficher_peches.jsp</result>
</action>
<action name="AfficherIndividus" class="org.ird.crh.baseisotopes.strutsactions.AfficherIndividus">
<result name="success">/webpages/afficher_individus.jsp</result>
</action>
<action name="AfficherRecherche" class="org.ird.crh.baseisotopes.strutsactions.AfficherRecherche">
<result name="success">/webpages/afficher_recherche.jsp</result>
</action>
<action name="AfficherAccueil">
<result>/webpages/index.jsp</result>
</action>
</package>
</struts>
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
42/44
2. Architecture détaillée du framework Struts 2
Illustration 35: Architecture détaillée de Struts 2
3. Organisation des répertoires de Tomcat
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
43/44
4. Ressources
Apache Commons : http://commons.apache.org/
Apache Struts 2 : http://struts.apache.org/2.0.11.1/index.html
Documentation des tags Struts 2 : http://struts.apache.org/2.x/docs/using-tags.html
Apache Tomcat : http://tomcat.apache.org/
PostgresSQL : http://www.postgresql.org/
MVC : http://fr.wikipedia.org/wiki/Mod%C3%A8le-Vue-Contr%C3%B4leur
Rédaction : Pascal Cauquil
25 juin 2008 – IRD-IS/DSI - support_cours_v1.2.odt
44/44