You are on page 1of 136

1

Architectures client/serveur
Master Technologies de l'Internet 1
re
anne
Eric Cariou
Universit de Pau et des Pays de l'Adour
UFR Sciences Pau Dpartement Informatique
Eric.Cariou@univ-pau.fr
2
Tryptique d'une application
ervices !tier
"ersistance
"rsentation
#
Tryptique d'une application

"rsentation

Interface utilisateur pour interagir avec l'application

Interface classi$ue t%pe &'I (e) * traite!ent de te)te+

Interface ,e-. plus lgre

"ersistance

Enregistre!ent sur support ph%si$ue des donnes de


l'application

/ichiers (-inaires. 0M1. ...+

2ase de donnes

i!ple

3vec redondance pour fia-ilit

Multiples * fdration de -ases de donnes

...
4
Tryptique d'une application

ervices !tier

Intgre la logi$ue !tier

E)* un docu!ent est co!pos de sections. elles !5!es


co!poses de sous-sections ...

ervices offerts au) utilisateurs

E)* crer un docu!ent. le !odifier. a6outer des sections.


l'enregistrer ...

"artieapplicative

Trois parties

ont intgres et cooprent pour le fonctionne!ent de


l'application

En anglais. on les appele aussi des 8tiers9 (tages+

3pplication 8# : tiers9 $uand les # parties sont claire!ent


distinctes
;
Tryptique d'une application

<ans un conte)te distri-u

1es tiers sont = peuvent 5tre e)cuts sur des !achines


diffrente

Certains tiers peuvent 5tre sous dcoups

<e no!-reuses variantes de place!ent des tiers et de


leur distri-ution

Modle centralis

Tout est sur la !5!e !achine


"rsentation
"ersistance
ervices
Mtiers
>
Architecture 2 tiers

3rchitecture 2 : tiers

Client = serveur de -ase. avec 2 l!ents

Client * prsentation. interface utilisateur

erveur * partie persistance. gestion ph%si$ue des donnes

1es services !tier = la partie applicative peuvent 5tre

oit entire!ent cot client. intgrs avec la prsentation

1a partie serveur ne gre $ue les donnes

E) * traite!ent de te)te avec serveur de fichiers distants

E) * application accdant ? une 2<< distante

oit entire!ent cot serveur

1a partie client ne gre $ue l'interface utilisateur

1'interface utilisateur peut !5!e 5tre e)cute sur le serveur

/onctionne!ent !ode ter!inal = !ainfra!e

1'utilisateur a si!ple!ent devant lui cran = clavier = souris pour interagir


? distance avec l'application s'e)cutant entire!ent sur le serveur

oit dcoups entre la partie serveur et la partie client


@
Architecture 2 tiers

Client * prsentation A applicatif

erveur * applicatif A gestion donnes


"rsentation
"ersistance
ervices
Mtiers
Client
erveur
"rsentation
"ersistance
ervices
Mtiers
Client
erveur
"rsentation
"ersistance
ervices
Mtiers
Client
erveur
B
Architecture 2 tiers

Ter!inal * client intgre un !ini!u! de la partie


prsentation

3pplicatif * dcoup entre client et serveur


Client erveur
"rsentation
"ersistance
ervices
Mtiers
Ter!inal
"rsentation
"ersistance
3pplicatif
serveur
3pplicatif
client
Client
erveur
C
Architecture 3 tiers

3rchitecture # : tiers

1es # principau) tiers s'e)cutent chacun sur une


!achine diffrente

"rsentation

Machine client

3pplicatif = !tier

erveur d'applications

"ersistance

erveur de (-ase de+ donnes


"ersistance
erveur
donnes
ervices
Mtiers
erveur
applicatif
"rsentation
Client
1D
Architecture 3 tiers sur le web

3rchitecture # : tiers

Trs dveloppe de nos 6ours

3vec gnrale!ent un fonctionne!ent au dessus du ,e-

Couche prsentation

Eavigateur Fe- sur !achine cliente

Client lger

3ffichage de contenu GTM1

Couche applicative = !tier

erveur d'applications

erveur GTT" e)cutant des co!posants = l!ents logiciels $ui


gnrent d%na!i$ue!ent du contenu GTM1

Hia des re$u5tes ? des 2<< distantes

Couche persistance

erveur(s+ de 2<< de donnes


11
Architecture n tiers

3rchitecture n : tiers

Ia6oute des tages = couches en plus

1a couche applicative n'est pas !onoliti$ue

"eut s'appu%er et interagir avec d'autres services

Co!position horiJontale

ervice !tier utilise d'autres services !tiers

Co!position verticale

1es services !tiers peuvent aussi s'appu%er sur des services


techni$ues

curit.

Transaction

...

Cha$ue service correspond ? une couche

<'oK le ter!e de E-tiers


12
Architecture n tiers

Intr5ts d'avoir plusieurs services = couches (# ou plus+

Iutilisation de services e)istants

<couplage des aspects !tiers et techni$ue et des services entre


eu) * !eilleure !odularit

/acilite volution * nouvelle version de service

/acilite passage ? l'chelle * volution de certains services

Ln recherche en gnral un couplage fai-le entre les services

"er!et de faire voluer les services un par un sans !odification du


reste de l'application

Inconvnients

En gnral. les divers services s'appuient sur des technologies trs


varies * ncessite de grer l'htrognit et l'interopra-ilit

'tilisation de fra!eForM = outils suppl!entaires

1es services tant plus dcoups et distri-us. pose plus de pro-l!es


lis ? la distri-ution
1#
Logique de prsentation

1es tNches lies ? la prsentation re$uirent

1'interaction avec l'utilisateur

Ialise par la &'I d'un client lourd * -outons. listes. !enus. ...

Ialise par le navigateur pour un client Fe-

Hia interaction plus 8-asi$ue9 * for!ulaires. liens vers des 'I1s ...

1a logi$ue de prsentation

1e traite!ent des donnes retournes par les services !tiers et leur


prsentation ? destination de l'utilisateur

Ialise par un client lourd $ui gnrale!ent fait directe!ent l'appel


des services !tiers sur le serveur

"our un client Fe-

Eavigateur se contente d'afficher du code GTM1 $ui ne peut pas 5tre


stati$ue ici vu $ue le contenu dpend des donnes retournes

<oit donc e)cuter du code $ui rcupre les donnes retournes par les
services !tiers et gnre d%na!i$ue!ent du code GTM1

1ogi$ue de prsentation peut 5tre e)cute cot client ou cot serveur !ais
se fait gnrale!ent dans un tiers ? part cot serveur
14
Persistance

Couche de persistance

tocMage et !anipulation des donnes de l'application

"lusieurs supports ph%si$ue

/ichiers -inaires. te)tes 8de -ase9

/ichiers 0M1

'ne -ase de donnes ou un ense!-le de -ases de donnes

"our ce dernier cas

Ecessit d'envo%er ? distance des re$u5tes (t%pes O1+ et d'en


rcuprer les rsultats

"our raliser cela

oit c'est natif dans le langage utilis (e) * "G"+

oit on passe par des fra!eForMs ou des 3"I ddis


1;
Persistance

Ouel$ues standards = outils d'accs ? distance ? des 2<<

I<3 (Ie!ote <ata 3ccess+ de l'IL

L<2C (Lpen <ata 2ase Connectivit%+ de Microsoft

P<2C (Pava <ata 2ase Connectivit%+ de un

/ra!eForM pour le langage Pava

/onctionne!ent gnral

&estion de re$u5tes O1 !ais avec indpendance du &2<I utilis


(!%O1. "ostgreO1. Lracle ...+

En gnral. seule la phase de conne)ion au &2<I est spcifi$ue

E)iste gale!ent des fra!eForMs de plus haut niveau

E)e!ples * Gi-ernate (un. P2EE+. EGi-ernate (li-re. pour .Eet+

"rincipe gnral

Ln dfinit de !anire a-straite (via 0M1 par e)e!ple+ la structure des


donnes ? !anipuler

1'outil gnre un ense!-le d'oprations de !anipulation de donnes (en


6ava par e)e!ple+ utilisa-le dans un progra!!e

1'outil fait en interne le lien avec le support ph%si$ue (&2<I ...+ considr
1>
ra!ewor"s globau#

'ne application #=E : tiers intgre un grand no!-re de


technologies

"rsentation * GTM1. &'I ...

3pplicatif * o-6ets. co!posants. scripts e)cuta-les. services ...

2<< * fichiers 0M1. &2<I. ...

"rotocoles de co!!unication * I"C = IMI. GTT"

"our faciliter l'intgration de ces technologies et le


dveloppe!ent d'applications

Editeurs offrent des fra!eForMs glo-au)

P2EE = Pava EE cheJ un

.Eet cheJ Microsoft

erveur d'application

erveur per!ettant d'e)cuter les parties applicatives dans le


conte)te de ces fra!eFoMs
1@
$un %2&&

P2EE = Pava EE * Pava Entreprise Edition

Eor!e = standard dfini par un pour le langage Pava

Technologies intgres

Co!posants logiciels * EP2

3pplications orientes ,e- * P". servlet

Co!!unication ? distance * Pava IMI. IIL". PM (Pava Message


ervice * co!!unication par !essage+. ,e- ervices

&estion donnes distantes * P<2C. P"3 (Pava "ersistance 3"I+

&estion d'annuaires (t%pe 1<3"+ * PE<I

Transactions * PT3

Et -ien d'autres ...

E)iste plusieurs serveurs d'applications P2EE

Hersions li-res

&lass/ish. P2oss. 3pache &eroni!o. Ponas ...

Hersions d'diteurs

un Pava %ste! 3pplication erver (-as sur &lass/ish+. I2M


,e-phere. 2E3 ,e-1ogic. Lracle Container for Pava EE. ...
1B
'icroso(t )*et

olution Microsoft si!ilaire ? P2EE

"articularit * !ulti-langage

"er!et interopra-ilit d'l!ents crits en C. Pava. CQ. PQ. Eiffel.


H2. ... (plus de 2D langages+

Traduction en code inter!diaire (MI1+ $ui sera e)cut par la


couche C1I (Co!!on 1anguage Iunti!e+

Cot Pava. c'est le code Pava $ui tait converti en -%te code e)cut par
la !achine virtuelle Pava (PHM+

C'est une nor!e gale!ent

1a principale !ise en oeuvre est -ien sRr de Microsoft et pour ,indoFs.


!ais il e)iste $uel$ues versions li-res (i!pl!entations souvent partielles+

Technologies intgres

Co!posants logiciels * CLMA

3pplications orientes ,e- * 3" .Eet.

Co!!unication ? distance * .Eet re!oting. MMO. ,e- services

3ccs donnes * 3<L .Eet. L<2C

...
1C
Architecture 3/+ tiers, conte#te %2&&

<eu) architectures gnrales conte)te P2EE

1ogi$ue applicative

Ialise par co!posants EP2

Co!!unication via Gi-ernate ou P<2C pour atta$uer 2<< distante

"rsentation

3vec client lger ou client lourd

Client lger * navigateur Fe-

Intr5t * si!plifie la prsentation (suffit d'un navigateur+

Inconvnient * li!ite de l'interaction via GTM1

Client lourd

3pplication 8standard 9cot client. gre la logi$ue de prsentation

Intr5t * plus grande possi-ilit en ter!e de prsentation et d'interaction

Inconvnient * ncessite un dveloppe!ent ddi via des 3"I de Fidgets

Interaction avec la partie applicative sur le serveur

Hia P" = ervlet pour un client lger

'occupe de la logi$ue de prsentation

<irect si client lourd (via un !iddleFare t%pe IMI+


2D
Architecture 3/+ tiers, conte#te %2&&

Client lourd (#-tiers+


Client lger (4-tiers+


erveur
donnes
&2<
Co!posants
EP2
Client lourd
Conteneur EP2
erveur P2EE
erveur
donnes
&2<
Co!posants
EP2
Eavigateur
,e-
Conteneur EP2
erveur P2EE
Conteneur Fe-
ervlet = P"
logique de prsentation
logique mtier
21
Technologies -eb . gnration
dyna!ique /T'L cot serveur
%$P / $ervlet
22
Technologies -eb

"rsentation

3ffichage docu!ent GTM1 A feuilles de st%les

'e)cute dans un navigateur Fe- * client lger

Interaction avec l'utilisateur via des for!ulaires (listes.


entres te)te. -outons ...+ et liens

3pplicatif

2ut * produire un contenu GTM1

elon les choi) de l'utilisateur

elon les donnes ? afficher

Ecessite une gnration d%na!i$ue des pages GTM1

Ecessite d')ecuter du code $ui va gnrer ces pages


2#
Technologies -eb

E)cution de code * deu) possi-ilits

E)cution cot client

1e client tlcharge ? partir du serveur du code $ui s'e)cute


dans le navigateur du client

E)e!ple * applet Pava

E)cution d'un progra!!e Pava (d'une for!e particulire+ au sein du


navigateur

"ro-l!es

Tlcharge!ent peut 5tre lourd * cha$ue client doit tlcharger le


code

"ro-l!e de scurit car on e)cute locale!ent du code venant d'un


l!ent distant

E)cution cot serveur

<u code est e)cut cot serveur pour gnrer de !anire


d%na!i$ue la page GTM1 $ui sera envo%e au client

Ln va s'intresser ? ce t%pe d'e)cution dans ce cours


24
0nration pages dyna!iques

<eu) principes gnrau) de fonctionne!ent. cot serveur

1angages de scripts

<ou-le t%pe de contenu dans une page GTM1

"artie stati$ue * -alises GTM1 standards avec contenu te)tuel

"artie d%na!i$ue * du code crit dans un langage de script

Ce code gnre du code GTM1 standard

1a page entre!elle les parties stati$ues et d%na!i$ues

Ouand un navigateur de!ande le contenu d'une page

1a partie d%na!i$ue est e)cute et re!place par le GTM1 gnr

1e navigateur du client reSoit donc uni$ue!ent du code GTM1

E)cution d'un progra!!e

'n progra!!e co!plet s'e)cute et gnre du contenu GTM1

1a page est entire!ent d%na!i$ue

"lus prcis!ent * les partie stati$ues e)istent !ais elles sont intgres
dans le code. pas crites directe!ent en GTM1 standard

1e navigateur de!ande l'e)cution d'un progra!!e et rcupre le


code GTM1 gnr

1a de!ande d'e)cution est transparente * utilise 'I1 standard


2;
0nration pages dyna!iques

E)e!ples de technologies

1angages de script

"G"

1angage interprt offrant l'avantage d'intgrer native!ent les


pri!itives de re$u5tes O1 sur des 2<<

3" et 3" .Eet

olutions Microsoft

P" (Pava erver "age+

olution un pour Pava

E)cution de progra!!es

C&I * Co!!on &ateFa% Interface

Gistori$ue!ent. une des pre!ires solutions

ervlet

olution un pour Pava * e)cution de code Pava respectant


certaines caractristi$ues
2>
0nration pages dyna!iques

"latefor!e d'e)cution

<ans tous les cas. il faut pouvoir e)cuter du code et


co!!uni$uer via GTT" avec le navigateur cot client

<eu) co!posants pour gnration de pages d%na!i$ues

erveur GTT" standard

El!ent (conteneur+ d'e)cution des progra!!es ou des scripts

E)e!ples de serveurs = platefor!es

3pache To!cat

P". ervlet

1ogiciel li-re

Microsoft II

3". 3" .Eet

"ropritaire
2@
$ervlet

'ne servlet est un progra!!e Pava particulier

Classe $ui hrite de HttpServlet

E$uivalent d'une applet Pava. !ais cot serveur

Classe standard du point de vue de son contenu en ter!e


d'attri-uts. !thodes ...

Mais e)cution et interactions diffrentes d'un o-6et Pava


standard

"as d'appel de constructeur. pas de main()

3 la cration de la servlet par le serveur d'e)cution

3ppel par le serveur d'e)cution de la fonction init(ServletConfig)

Ln peut % faire les actions $u'on ferait dans un constructeur

Ouand la servlet est dtruite

3ppel par le serveur d'e)cution de destroy()

3 redfinir si on veut effectuer certaines actions ? la


suppression de la servlet
2B
$ervlet

Eavigateur Fe- cot client

Envoie des re$u5tes GTT" au serveur

&ET. "LT. "'T. <E1ETE. GE3<. L"TILE. TI3CE

<ans une servlet

3 cha$ue re$u5te correspond une !thode doXXX(...) hrite de


la classe HttpServlet et $ui sera appele selon la re$u5te client

Ln rdfinit ces !thodes pour % placer le code ? e)cuter par la servlet

En prati$ue. pas -esoin de redfinir toutes les !thodes (&ET et "LT


!ini!u!+

<e !anire plus gnrale (!ais !oins reco!!ande+. la !thode service(...)


reSoit toutes les re$u5tes et peut 5tre redfinie directe!ent (par dfaut elle
redispatche au) doXXX(...) +

E)e!ple pour &ET

doGet(HttpServletRequest request, HttpServletResponse response)


thros Servlet!"ception, #$!"ception

request * contient la description de la re$u5te du client

response * ? utiliser pour envo%er la rponse au client

Toutes les !thodes doXXX(...) ont la !5!e signature


2C
Para!1tres des do2223)))4

HttpServletRequest request

Initialis par l'appel du client (le navigateur+

<onnes = infor!ations sur la re$u5te envo%e par le


client

Ln peut % rcuprer nota!!ent

Haleurs entres pour un for!ulaire

'ne session pour grer un tat ddi ? cha$ue client

CooMies du client envo%s avec la re$u5te

Infor!ations sur l''I1 utilise pour l'appel de la servlet

1ogin de l'utilisateur s'il s'est identifi

Et de !anire plus gnrale. tous les 8headers9 de l'appel

Identifiants du navigateur. t%pe de re$u5te (&ET. "'T ...+. t%pe


d'encodage support par le navigateur. ...
#D
Para!1tres des do2223)))4

HttpServletResponse response

3 initialiser et utiliser par la servlet pour gnrer le rsultat ?


envo%er au navigateur client

<finir le t%pe MIME des donnes envo%es

&nrale!et du code GTM1

response.setContent%ype(&te"t'html(charset)*%+,-&)(

Mais peut utiliser n'i!porte $uel t%pe MIME * image'gif, audio'mp.,


application'pdf. ...

Icuprer le flu) de sortie pour envo%er les donnes

/rint0riter get0riter()

/lu) te)te. t%pi$ue!ent pour du GTM1

Servlet$utputStream get$utputStream

/lu) -inaire pour des i!ages. vidos ...

36outer=envo%er des donnes cot client

Cr un nouveau cooMie (ou !odifier un e)istant+

36outer un header au) donnes envo%es


#1
5aractristiques d'une servlet

'nicit d'une servlet

'ne servlet n'est cre $u'en une seule instance

i plusieurs clients accdent ? l''I1 d'une !5!e servlet

3ppelle les !thodes sur cette instance uni$ue

'ne servlet possde des attri-uts donc un tat

Cet tat est per!anent et conserv (tant $ue la servlet e)iste+

Il est accd = !odifi par tous les clients * tat glo-al

Etat associ ? un client

Te!poraire * !ode session

"our cha$ue client. une session est cre

Ln peut lui associer des donnes via des couples 8cl (chaine+ = o-6et 9

1a session a une dure de vie configura-le

E)e!ple t%pi$ue d'utilisation d'une session

"anier d'un utilisateur sur un site de vente en ligne * conserve les produits
choisis par l'utilisateur pendant son parcours sur le site

"er!anent * cooMies du navigateur


#2
&#e!ple . servlet hello world

E)e!ple -asi$ue de servlet

&nre une page $ui affiche 8hello Ford9

&re et affiche un co!pteur $ui est incr!ent ? cha$ue accs ?


la servlet

Eote sur le code prsent

1e code $ui suit a t cr sous Eet-eans $ui gnre un


s$uelette de code

Ce s$uelette contient une !thode principale processRequest() $ui


contiendra le code principal de la servlet

1es !thodes hrites doGet() et do/ost() appellent directe!ent


cette !thode processRequest() avec les !5!es para!tres

'ne fois dplo%e sur le serveur. on accde ? une servlet


via une 'I1 GTT"

1a notre est contenue dans le fichier Hello0orld.1ava

'I1 sera de la for!e * http2''."""""".fr'XXX'Hello0orld

Eote * peut choisir une 'I1 d'accs ? la servlet diffrente


du no! de la servlet Pava
##
&#e!ple . servlet hello world

Code de la servlet Hello0orld.1ava



public class HelloWorld extends HttpServlet {
== co!pteur gr par la servlet
protected int compteur = 0;

protected void processRequest(
HttpServletRequest request, HttpServletResponse response)
thros Servlet!xception, "#!xception {
== out * flu) de sortie !ode te)te $ui contiendra le GTM1
response$set%ontent&'pe((text)html;charset=*&+,-();
.rintWriter out = response$/etWriter();
tr' {
== on crit ligne par ligne le code GTM1 ? afficher cheJ le client
out$println((0html1();
out$println((0head1();
out$println((0title1Servlet HelloWorld0)title1();
out$println((0)head1();
out$println((0bod'1();
out$println((0h21Servlet HelloWorld0)h21();
== on insre ici la valeur du co!pteur (en l'incr!entant au passage+
out$println((0p13ombre d4appels 5 (6(66compteur)6(0)p1();
out$println((0)bod'1();
out$println((0)html1();

7 8inall' {
out$close();
7 7
#4
&#e!ple . servlet hello world

E)e!ple d'e)cution
3prs 4 charge!ents
de la servlet
co!pteur passe ? ;
#;
&#e!ple . servlet hello world

Code prcdent

1e co!pteur est glo-al * co!!un ? tous les clients

Hariante pour grer un co!pteur local ? cha$ue client

"asser par les donnes $u'on peut associer ? une session

Modification de processRequest()

tr' {
== rcupre la session associe au client
HttpSession session = request$/etSession(true);
== rcupre le co!pteur associ ? la session
"nte/er compteur = ("nte/er)session$/et9ttribute((compteur();
== si valeur null * attri-ut 8co!pteur9 n'e)iste pas. Sa signifie
== $ue c'est la pre!ire e)cution par le client. il faut crer le co!pteur
i8 (compteur==null) {
compteur = ne "nte/er(2);
session$set9ttribute((compteur(, compteur);
== configure pour $u'une session dure 1D secondes !a)
session$set:ax"nactive"nterval(20);
7
($$$)
out$println((0p13ombre d4appels 5 (6compteur6(0)p1();
($$$)
== incr!ente le co!pteur
session$set9ttribute((compteur(, ne "nte/er(compteur$int;alue()62));
#>
&#e!ple . passage de para!1tres

3utre e)e!ple

Manipulation de rectangles avec # oprations

Cration d'un rectangle

<calage du rectangle courant (non prsent en dtail pour gagner


de la place+

Calcul de la surface du rectangle courant

I!pl!entation

'ne page GTM1 contient un for!ulaire pour entrer les para!tres et


appeler la servlet avec ces para!tres

Eote * dans l'e)e!ple. c'est une page P" !ais c'est du GTM1
standard. aucun code Pava n'est inclus dans la page

ervlet

'ne servlet gre le rectangle et e)cute les # oprations en fonction


des para!tres venant du for!ulaire

Ln rcupre ces para!tres via *


request.get/arameter(nom/aram)
#@
&#e!ple . servlet rectangle

Code de la page GTM1



0html1
0head1
0meta http,equiv=(%ontent,&'pe( content=(text)html; charset=*&+,-(1
0title1<S. .a/e0)title1
0)head1
0bod'1
0h21:anipulation de rectan/le avec une servlet0)h21
08orm action=(RectServlet( method=(post(1
0p1 0table border=(0(1
0tr1 0td1=2 ou = d>cala/e0)td1 0td10input name=(x2(1 0)td1 0)tr1
0tr1 0td1?2 ou ? d>cala/e0)td1 0td10input name=('2(1 0)td1 0)tr1
0tr1 0td ali/n=(ri/ht(1=@0)td1 0td10input name=(x@(1 0)td1 0)tr1
0tr1 0td ali/n=(ri/ht(1?@0)td1 0td10input name=('@(1 0)td1 0)tr1
0)table10)p1
0p10input t'pe=(radio( name=(action( value=(creer( checAed=(checAed( )1
%r>er Rectan/le0br )1
0input t'pe=(radio( name=(action( value=(decaler( )1B>caler Rectan/le0br )1
0input t'pe=(radio( name=(action( value=(sur8ace( )1%alcul Sur8ace0)p1

0p10input t'pe=(submit( value=(!x>cuter(1
0input t'pe=(reset( value=(Remise C D>ro10)p1
0)8orm1
0)bod'1
0)html1
#B
&#e!ple . servlet rectangle

1iens entre page GTM1 et la servlet

1e for!ulaire de la page GTM1 contient

'ne action associe $ui est l'appel de la servlet RectServlet

4 cha!ps d'entre de no!s "3, y3, "4, y4

'ne liste de -outons radio dont selon le choi). on aura le


para!tre action gal ? 8creer9. 8 decaler9 ou 8surface9

<ans le code de la servlet RectServlet.1ava

Ln rcupre ces ; para!tres dans request

Eota!!ent le para!tre action $ui prcisera $uelle opration


on veut appeler

1a servlet conservera le dernier rectangle cr (avec un


pre!ier rectangle dfini par dfaut+ et les fonctions de
dcalage et de surface seront appeles sur ce rectangle

"our si!plifier. on !et les fonctions !tiers (!anipulation de


rectangles+ directe!ent dans le code de la classe
de la ervlet
#C
&#e!ple . servlet rectangle

Code de la servlet ServRectangle.1ava



public class RectServlet extends HttpServlet {
== rectange !anipul par la servlet
protected Rectan/le rectan/le;

public int calculSur8ace(Rectan/le rect) {
return ( (rect$x@ , rect$x2) E (rect$'@ , rect$'2));
7
public Rectan/le decalerRectan/le(Rectan/le rect, int x, '){
return ne Rectan/le(rect$x2 6 x, rect$'2 6 ',
rect$x@ 6 x, rect$'@ 6 ');
7

public void init(Servlet%on8i/ con8i/)
thros Servlet!xception {
== initialisation par dfaut du rectangle
rectan/le = ne Rectan/le(20, @0, F0, G0);
7
4D
&#e!ple . servlet rectangle

Code de la servlet ServRectangle.1ava (suite+



protected void processRequest(
HttpServletRequest request, HttpServletResponse response)
thros Servlet!xception, "#!xception {
response$set%ontent&'pe((text)html;charset=*&+,-();
.rintWriter out = response$/etWriter();
tr' {
== ent5te du docu!ent
out$println((0html1();
out$println((0head1();
out$println((0title1&est de Servlet 5 RectServlet0)title1();
out$println((0)head1();
out$println((0bod'1();
out$println((0h21Servlet RectServlet0)h21();
== affichage du rectangle courant
out$println((0p1!tat courant de mon rectan/le5(6rectan/le6(0)p1();

== rcupre l'identifiant de l'action ? raliser
Strin/ action = request$/et.arameter((action();
== calcul de surface du rectangle courant
i8 (action$equals((sur8ace())
int sur8ace = calculSur8ace(rectan/le);
out$println((0p1Sur8ace 5 (6sur8ace6(0)p1();
7
41
&#e!ple . servlet rectangle

Code de la servlet ServRectangle.1ava (fin+



== cration d'un rectangle
i8 (action$equals((creer()) {
int x2 = "nte/er$parse"nt(request$/et.arameter((x2());
int '2 = "nte/er$parse"nt(request$/et.arameter(('2());
int x@ = "nte/er$parse"nt(request$/et.arameter((x@());
int '@ = "nte/er$parse"nt(request$/et.arameter(('@());
rectan/le = ne Rectan/le(x2, '2, x@, '@);
out$println((0p1Rectan/le cr>> 5 (6 rectan/le 6 (0)p1();
7
catch (!xception e) {
== en cas de pro-l!e. affiche un !essage
out$println((0p10b1!rreur HH0)b10br )1();
out$println(e$toStrin/()6(0)p1();
7

== fin du docu!ent * lien pour retour en arrire
out$println((0p10a hre8=I((6request$/et%ontext.ath()6(I(1
Retour0)a10)p1();
out$println((0)bod'1();
out$println((0)html1();
out$close();
7
42
&#e!ple . servlet rectangle

3ffichage de la page GTM1

Ln re!plit les 4 cha!ps et slectionne 8crer9


4#
&#e!ple . servlet rectangle

3prs clic sur 8e)cuter 9

e retrouve 8sur 9 la servlet $ui cre alors un rectangle


44
&#e!ple . servlet rectangle

lection de retour pour revenir ? la page GTM1


puis choi) de 8calcul surface9
4;
&#e!ple . servlet rectangle

3prs clic sur e)cuter

E)cute la servlet avec l'opration de calcul surface

Ln voit $u'elle s'appli$ue sur le rectangle $u'on vient de


crer et $ui a donc t conserv
4>
%ava $erver Page . %$P

"ages !i)tes contenant ? la fois

<u code GTM1 stati$ue

<u code Pava $ui est e)cut d%na!i$ue!ent et gnre


du code GTM1

1es parties stati$ues et Pava sont entre!5les pour


for!er une page P"

1e navigateur client rcupre une page GTM1 standard


contenant

1es parties stati$ues

1es parties en Pava re!places par le code GTM1 $u'elles ont


gnres

En prati$ue

1e serveur d'e)cution de la P" la traduit d'a-ord en une


servlet co!plte $uivalente et c'est cette servlet $ui est
e)cute
4@
%$P . insertion de code %ava

3ttri-uts i!plicites (non dclars+ utilisa-les dans le


code Pava

i!ilaires ? ce $u'on aurait dans une servlet

out * flu) de sortie te)te dans le$uel on crit le code GTM1


gnr par les parties de code Pava

request * para!tres de l'appel de la P" = ervlet

response * pour renvo%er la rponse au client

session * la session spcifi$ue au client courant

config * configuration de la P"

pcifi$ue au fonctionne!ent des P"

page * l'instance de la P" = ervlet ($uivalent du this+

e"ception * l'e)ception $ui a t leve en cas de pro-l!e

application * donnes co!!unes ? toutes les P" du serveur

pageConte"t * conte)te de la page (gestion d'attri-uts ...+


4B
%$P . insertion de code %ava

2alises spciales pour insrer du code Pava

Trois -alises 56 ... 67. 568 ... 67 et 56) ... 67

"eut insrer plusieurs de ces -alises dans une !5!e page P"

"oint i!portant

P" co!pile en ervlet donc unicit de la P" gale!ent

568 ... 67

<claration d'attri-uts et de !thodes

Ils seront glo-au) ? tous les appels de la P" pour tous les clients

56 ... 67

criplet * suite d'instructions Pava $ui sera e)cute ? cha$ue


appel de la page P"

i on % dclare des attri-uts. ils sont locau) ? cha$ue appel

56) e"pr 67

Evalue le e"pr et affiche le rsultat dans le code GTM1

E$uivalent de 56 out.print(e"pr) 67
4C
%$P . insertion de code %ava

2alise spciale 569 page .... 67

Infor!ations gnrales sur la P"

3 utiliser si les valeurs par dfaut de la page sont ? !odifier

I!port de classes Pava

569 page import ) 1ava.util.:ector 67

T%pe MIME de la page

"ar dfaut du te)t=ht!l

569 page content%ype ) ;;image'png;; 67

&estion des erreurs

E)cuter une P" en cas d'erreur rencontre

569 page error/age);;erreur.1sp;; 67

"rciser $u'une P" est ou pas une page d'erreur

569 page is!rror/age);;true;; 67


;D
&#e!ple . %$P hello world

E)e!ple -asi$ue de page P"

Code stati$ue GTM1 * affiche 8Gello ,orld T9

Code d%na!i$ue et code Pava

&estion d'un co!pteur local et d'un co!pteur glo-al d'appel

3ffichage de ces 2 co!pteurs (via !lange code stati$ue et


d%na!i$ue+

I!pl!entation

Trois insertions de code Pava pour grer les co!pteurs


1. UV ...VW * dclaration du co!pteur local
2. UVT ... VW * dclaration du co!pteur glo-al et d'une !thode
d'incr!entation de ce co!pteur
#. UV ... VW * incr!entation des 2 co!pteurs

"uis affiche via des 56) ... 67 les valeurs des co!pteurs
;1
&#e!ple . %$P hello world

Code de la page P"

5html7
5head7
5meta http,equiv)&Content,%ype& content)&te"t'html( charset)*%+,-&7
5title7<S/ Hello0orld5'title7
5'head7
5=ody7
5h37Hello 0orld85'h37
56
int n=>ocal ) ?(
67

568
int n=Glo=al ) ?(
void inc@=Glo=al() A n=Glo=alBB( C
67
56
n=>ocalBB(
inc@=Glo=al()(
67
5p7Compteur local 2 56) n=>ocal 67 5=r '7
Compteur glo=al 2 56) n=Glo=al 675'p7
5'=ody7
5'html7
!ode e"cut localement
!ode dclar glo#alement
$valuation de la valeur
des attri#uts
1gende couleur *
!ode %&'( statique
;2
&#e!ple . %$P hello world

E)e!ple d'e)cution
3prs 4 charge!ents de la servlet
co!pteur glo-al passe ? ;
!ais le local est s%st!ati$ue!ent ? 1
;#
&#e!ple . %$P hello world

Co!!entaires sur le code prsent

<ans dernire -alise UV ... VW

3urait pu re!placer 8incGlo=al@=()( 9 par directe!ent


8glo=al@=BB(E

1es attri-uts et !thodes dclares en glo-al sont tous


accessi-les directe!ent

Ee peut par contre pas dclarer une !thode pour


incr!enter le co!pteur local

void inc@=>ocal A n=>ocalBB( C

Ee peut pas dclarer de !thode dans une -alise UVT ... VW

Ee contient $u'une suite d'instructions ? e)cuter

Ee peut pas dclarer cette !thode dans la -alise UV ... VW

1'attri-ut n=>ocal est local et n'est pas connu dans le code glo-al
;4
&#e!ple . %$P rectangle

M5!e e)e!ple de gestion des rectangles

Ln a -esoin d'une seule page P" au total

Elle fera l'affichage du for!ulaire avec GTM1 standard et


contiendra le code Pava des oprations (en vert+

Elle s'auto-appellera pour l'e)cution de l'opration choisie

Code la page rectangle.1sp



0head1
0meta http,equiv=(%ontent,&'pe(
content=(text)html; charset=*&+,-(1
0title1Rectan/le0)title1
0)head1
0bod'1
0JKpa/e import=(rect$E( J1

0h21:anipulation de rectan/es avec du <S.0)h21
la classe Rectangle est dfinie
dans un pacMage rect
;;
&#e!ple . %$P rectangle

Code la page rectangle.1sp (suite+



0JH
Rectan/le rectan/le = ne Rectan/le(20, @0, F0, G0);
public int calculSur8ace(Rectan/le rect) {
return ( (rect$x@ , rect$x2) E (rect$'@ , rect$'2));
7
public Rectan/le decalerRectan/le(Rectan/le rect, int x, int '){
return ne Rectan/le(rect$x2 6 x, rect$'2 6 ',
rect$x@ 6 x, rect$'@ 6 ');
7
J1
08orm action=(rectan/le$Lsp( method=(post(1
0p1 0table border=(0(1
0tr1 0td1=2 ou = d>cala/e0)td1 0td10input name=(x2(1 0)td1 0)tr1
0tr1 0td1?2 ou ? d>cala/e0)td1 0td10input name=('2(1 0)td1 0)tr1
0tr1 0td ali/n=(ri/ht(1=@0)td1 0td10input name=(x@(1 0)td1 0)tr1
0tr1 0td ali/n=(ri/ht(1?@0)td1 0td10input name=('@(1 0)td1 0)tr1
0)table10)p1
0p10input t'pe=(radio( name=(action( value=(creer( checAed=(checAed( )1
%r>er Rectan/le0br )1
0input t'pe=(radio( name=(action( value=(decaler( )1B>caler Rectan/le0br )1
0input t'pe=(radio( name=(action( value=(sur8ace( )1%alcul Sur8ace0)p1
;>
&#e!ple . %$P rectangle

Code la page rectangle.1sp (suite+



0p10input t'pe=(submit( value=(!x>cuter(1
0input t'pe=(reset( value=(Remise C D>ro10)p1
0)8orm1
0p1Rectan/le courant 5 0J= rectan/le$toStrin/() J1 0)p1
0J
tr' {
Strin/ action = request$/et.arameter((action();
== cas du pre!ier affichage de la page * pas de para!tre
== il n'% a pas d'actions ? e)cuter
i8 (action == null) return;
)) cr>ation d4un rectan/le
i8 (action$equals((creer()) {
int x2 = "nte/er$parse"nt(request$/et.arameter((x2());
int '2 = "nte/er$parse"nt(request$/et.arameter(('2());
int x@ = "nte/er$parse"nt(request$/et.arameter((x@());
int '@ = "nte/er$parse"nt(request$/et.arameter(('@());

rectan/le = ne Rectan/le(x2, '2, x@, '@);
out$println((0p1Rectan/le cr>> 5 (6rectan/le 6 (0)p1();
7

;@
&#e!ple . %$P rectangle

Code la page rectangle.1sp (suite+



)) calcul de sur8ace du rectan/le courant
i8 (action$equals((sur8ace()) {
int sur8ace = calculSur8ace(rectan/le);
out$println((0p1Sur8ace 5 (6sur8ace6(0)p1();
7
7 )) tr'
catch (!xception e) {
out$println((0p10b1!rreur HH0)b10br )1();
out$println(e$toStrin/()6(0)p1();
7
J1
0)bod'1
0)html1

Ln utilise ici les attri-uts i!plicites

request * pour rcuprer les para!tres passs avec get/arameter()

out * flu) de sortie pour gnrer du code GTM1

<eu) faSons de gnrer du code GTM1 en d%na!i$ue

'tilisation du out co!!e avec une servlet

'tilisation d'une -alise UVX ... VW dans du code GTM1




;B
&#e!ple . %$P rectangle

3ffichage par dfaut de la page rectangle.1sp

Ln va re!plir les 4 cha!ps avec valeurs 4;. 12. ;C. 4@


et lancer l'e)cution de 8crer rectangle9
;C
&#e!ple . %$P rectangle

Isultat de la cration du rectangle

Ln e)cute !aintenant ? partir de cette page


8calcul surface9
>D
&#e!ple . %$P rectangle

Isultat du calcul de surface


>1
&#cution concurrente

Modle par dfaut d'e)cution

ervlet = page P" est uni$ue

erveur GTT" peut avoir plusieurs re$u5tes d'accs ? la


servlet=P" par plusieurs clients ? la fois

E)cution !ulti-threade par le serveur GTT"

"lusieurs threads peuvent donc e)cuter en !5!e te!ps du code de la


!5!e servlet=P"

'assurer $u'un seul thread ? la fois e)cute une servlet=P"

ervlet

I!pl!entation de l'interface (vide+ Single%hreadFodel

pu=lic class FaServlet e"tends HttpServlet implements Single%hreadFodel

P"

"asse par les para!tres gnrau) de la page * is%hreadSafe

569 page is%hreadSafe)&true& 67

"our une gestion plus fine et plus prcise

Mar$uer des !thodes ou des parties de code de la servlet=P"


avec synchroniGed
>2
5o!!unication inter6l!ents

Cha$ue servlet = P" possde un tat glo-al ou un tat


local pour cha$ue client

"eut aussi vouloir avoir un tat glo-al ? toutes les pages P" ou
les servlets gres par le serveur GTT"

3ttri-ut i!plicite application dans P"

"er!et de dfinir des attri-uts co!!e pour une session. !ais co!!uns
? toutes les pages P" gres par le serveur GTT"

E)e!ple * code Pava pour grer un co!pteur co!!un ? toutes les


pages P"

56
#nteger compteur ) (#nteger)application.getHttri=ute(&compteur&)(
if (compteur))null) A
'' on crIe le compteur qui n;e"istait pas
compteur ) ne #nteger(?)(
application.setHttri=ute(&compteur&, compteur)(
out.println(&5p7CrIation du compteur ...5'p7&)(
C
application.setHttri=ute(&compteur&, BBcompteur)(
out.println(&5p7Compteur glo=al 2 &BcompteurB&5'p7&)(
67
>#
5o!!unication inter6l!ents

Etat co!!un glo-al au serveur GTT"

3utre techni$ue * dfinir une classe accessi-le (dans


!5!e pacMage+ par toutes les servlets = P"

Y dfinir des attri-uts ou !thodes stati$ues

E)e!ple pour le co!pteur

pu=lic class Compteur A


protected static int compteur ) ?(
pu=lic synchroniGed static int ne"t:alue() A
return BBcompteur(
C
C

Ln accde par e)e!ple au co!pteur glo-al dans une servlet ou


une page P"

out.println(&5p7@om=re d;appels 2 &BCompteur.ne"t:alue()B&5'p7&)(


>4
7elation entre servlets/%$P

<ans une servlet ou une page P". possi-ilit

<'appeler une autre servlet ou page P" pour dlguer le


traite!ent de la re$u5te ou inclure un rsultat suppl!entaire dans
celui de la servlet=page P" courante

ervlet

Icupre le 8re$uest dispatcher 9

RequestJispatcher rd ) request.getRequestJispatcher( &maServlet& )(

/ait suivre le traite!ent de la re$u5te ou inclus un traite!ent ralis


par la servlet 8 !aervlet9

rd.forard(request, response)(
rd.include(request, response)(

"age P"

Inclusion du rsultat d'une autre page

51sp2include page);;ma/age.1sp;;75'1sp2include7

/aire suivre le traite!ent de la re$u5te ? une autre page P"

51sp2forard page);;ma/age.1sp;;75'1sp2forard7

<ans les 2 cas. peut passer des para!tres ? la page appele via inclusion

51sp2param name);;compteur;; value);;34;; '7


>;
7elation entre l!ents

En cas d'erreur dans une page P". peut aussi


e)cuter une page P" particulire

<ans la page. insrer une redirection en cas d'erreur

569 page error/age);;erreur.1sp;; 67

En cas d'e)ception leve par une instruction Pava. la page


erreur.1sp est alors e)cute

<ans erreur.1sp

"rciser $ue l'on est une page d'erreur

569 page is!rror/age);;true;; 67

"eut alors rcuprer l'e)ception leve et par e)e!ple l'afficher

5p7!"ception levIe 2 56) e"ception 67 5'p7

1'attri-ut i!plicite e"ception est une e)ception Pava classi$ue. on


peut appeler dessus des !thodes co!!e getFessage(),
getCause(), printStacK%race(), ...
>>
7etour sur l'e#e!ple des rectangles

<ans une P". une part i!portante du code est


ddie ? si!ple!ent afficher le contenu d'o-6ets

M5!e avec des UVX ... VW Sa peut 5tre relative!ent


lourd ? raliser

E)e!ple

Ieprenons notre !anipulation de rectangles

1a servlet RectServlet gre le rectangle courant et e)cute les


actions associs

'ne page GTM1 affiche un for!ulaire pour rentrer les diffrents


cha!ps

i l'utilisateur veut !odifier une des 4 valeurs de coordonne (%1


par e)e!ple+ du rectangle courant. il doit rentrer les 4 valeurs

Ln pourrait re!plir par dfaut les 4 cha!ps avec le contenu du


rectangle courant
>@
7etour sur l'e#e!ple des rectangles

Modifie RectServlet.1ava pour a6outer le rectangle en


tant $u'attri-ut de la session

protected void processRequest(...) A


HttpSession session ) request.getSession(true)(
'' premier appel de la servlet, on crLe l;attri=ut rectangle
if (session.getHttri=ute(&rectangle&) )) null)
session.setHttri=ute(&rectangle&, rectangle)(
if (action.equals(&creer&)) A
'' rIcupLre les paramLtres "3, "4, y3, y4 dans la requMte
(...)
rectangle ) ne Rectangle("3, y3, "4, y4)(
out.println(&5p7Rectangle crII 2 &Brectangle B &5'p7&)(
'' met N 1our l;attri=ut de la session avec le nouveau rectangle
session.setHttri=ute(&rectangle&, rectangle)(
C
(...)
>B
7etour sur l'e#e!ple des rectangles

Transfor!e la page GTM1 associe en page P" pour


pouvoir rcuprer le rectangle associ ? la session

569page import ) &rect.Rectangle& 67


56 Rectangle rect )(Rectangle) session.getHttri=ute(;;rectangle;;)( 67
5h37Fanipulation de rectangle avec une servlet5'h37
5form action)&RectServlet& method)&post&7
5p7 5ta=le =order)&?&7
5tr7
5td7X35'td7
5td75input name)&"3& value)&56)rect.getX3() 67&75'td7
5'tr7
(...)

Ln rcupre l'attri-ut 8rectangle9 associ ? la session

Ln s'en sert pour !ettre une valeur par dfaut dans les cha!ps
d'entre des 4 valeurs de coordonnes
>C
7etour sur l'e#e!ple des rectangles

1e code prsent se!-le pertinent ... !ais ne !arche pas

3u pre!ier charge!ent de la P". aucun appel n'a encore t fait


sur la ervlet * pas d'attri-ut 8rectangle9 associ ? la session

1'attri-ut rect vaut donc null et 56) rect.getX3() 67 lve une e)ception

Il faut grer e)plicite!ent le cas oK l'attri-ut n'est pas encore dfini

569page import ) &rect.Rectangle& 67


56 Rectangle rect ) (Rectangle) session.getHttri=ute(;;rectangle;;)(
String "3 ) ;;;;, "4) ;;;;, y3 ) ;;;;, y4 ) ;;;;(
if (rect 8) null) A
"3 ) ne #nteger(rect.getX3()).toString()(
(...)
C 67
5h37Fanipulation de rectangle avec une servlet5'h37
5form action)&RectServlet& method)&post&7
5p7 5ta=le =order)&?&7
5tr7
5td7X35'td7
5td75input name)&"3& value)&56) "3 67&75'td7
(...)

@D
7etour sur l'e#e!ple prcdent

3utre solution pour rcuprer le rectangle courant

E)pression 'E1 ('nified E)pression 1anguage+

i!plifie l'accs au) attri-uts (dans le sens des attri-uts associs ?


une session+

1a page P" devient tout si!ple!ent


5h37Fanipulation de rectangle avec une servlet5'h37
5form action)&RectServlet& method)&post&7
5p7 5ta=le =order)&?&7
5tr7
5td7X35'td7
5td75input name)&"3& value);; OAsessionScope.rectangle."3C;;75'td7
(...+

1e cha!p d'entre 01 est initialis par le contenu de la proprit "3 de


l'attri-ut rectangle associ ? la session

i l'attri-ut rectangle n'e)iste pas. ne gnre pas d'erreur. retourne


si!ple!ent une chaine vide

"lus -esoin de vrifier e)plicite!ent $ue l'attri-ut e)iste


@1
8&L 9 %$TL

'nified E)pression 1anguage ('E1+

1angage d'e)pression per!ettant si!ple!ent dans une page P"

<e rcuprer des attri-uts associs ? des conte)tes

3ttri-uts de la session. de l'application. du header ou de la re$u5te GTT" ...

<'crire des e)pressions de calcul ou de test

3ddition. !ultiplication. !odulo ...

Co!paraisons de valeurs. oprateurs logi$ues (L'. ET ...+

Pava erver "ages tandard Tag 1i-rar% (PT1+

Ense!-les de -alises offrant des fonctionnalits pour !anipuler


des fichiers 0M1. accs ? des 2<<s. l'internationalisation ...

Ense!-le 8core9 per!et nota!!ent de !anipuler si!ple!ent


des ense!-les de donnes. faire des tests et d'associer des
-alises GTM1 (ou autres+ ? ces traite!ents ...

En co!-inant 'E1 et PT1

/acilite grande!ent dans une page P" l'affichage de donnes


retourns par la logi$ue !tier
@2
8&L . attributs, proprits

3ttri-ut

Instance d'une classe Pava respectant $uel$ues contraintes


structurelles * Pava 2eans

<finit des proprits

'n attri-ut (de la classe+ avec un getter et un setter associ

<finit un constructeur sans para!tre

Ln peut ensuite accder au) proprits des attri-uts via une


notation pointe ? partir d'un certain conte)te

E)e!ple * sessionScope.rectangle."3

Conte)te * sessionScope

3ttri-ut * rectangle

"roprit * "3

Ievient ? e)cuter de !anire rfle)ive

((Rectangle)sessionScope.getHttri=ute(;;rectangle;;)).getX3()

Ln voit -ien l'o-ligation d'avoir un getter=setter associ ? cha$ue proprit


pour pouvoir % accder

i l'attri-ut ou une de ses proprits n'est pas dfinie (valeur null+


gnre une chaZne vide
@#
8&L . conte#tes et ob:ets i!plicites

L-6ets i!plicites. dont certains si!ilaires au) o-6ets


i!plicites P"

pageConte"t. param. param:alues. header. header:alues.


cooKie. init/aram

Conte)tes (8scope9+. ? partir des$uels on peut associer


des attri-uts

pageScope * la page P"

requestScope * la re$u5te GTT"

sessionScope * la session associe avec le navigateur client

applicationScope * conte)te glo-al ? toutes les pages P" du


serveur
@4
8&L . tableau# et !ap

3ccde au) donnes d'un ta-leau (arra%. list ...+ ou d'une


!ap via une notation inde)e

attPinde"Q

3vec inde) $ui est soit la cl pour une !ap. soit l'inde) pour un ta-leau

"eut aussi 5tre le contenu d'une varia-le

"our un ta-leau. peut utiliser un inde) sous for!e d'entier ou de chaine

E)e!ple * une servlet e)cute le code suivant

Iectangle rect1 X neF Iectangle(1D.1D.2D.2D+[


Iectangle rect2 X neF Iectangle(#D. #D. ;D. ;D+[

GashMapUtring. IectangleW !apIect X neF GashMapUtring. IectangleW(+[
Iectangle\] arra%Iect X neF Iectangle\2][
int inde) X 1[
!apIect.put(^pre!ier^.rect1+[
!apIect.put(^second^. rect2+[
arra%Iect\D] X rect1[
arra%Iect\1] X rect2[
session.set3ttri-ute(^!apIect^. !apIect+[
session.set3ttri-ute(^arra%Iect^. arra%Iect+[
session.set3ttri-ute(^inde)^. inde)+[
@;
8&L . tableau# et !ap

1a servlet forFarde la re$u5te ? la page P"

5p7
Fap ,7 &premier& 2 OAsessionScope.mapRectP&premier&Q."3C5=r '7
Fap ,7 ;second; 2 OAsessionScope.mapRectP;second;Q."3C5=r '7
Fap ,7 &troisieme& 2 OAsessionScope.mapRectP&troisieme&Q."3C5=r '7
Hrray ,7 ? 2 OAsessionScope.arrayRectP?Q."3C5=r '7
Hrray ,7 ;3; 2 OAsessionScope.arrayRectP;3;Q."3C5=r '7
Hrray ,7 4 2 OAsessionScope.arrayRectP4Q."3C5=r '7
Hrray ,7 inde" 2 OAsessionScope.arrayRectPsessionScope.inde"Q."3C5=r '7
5'p7

3ffichage rsultant

Fap ,7 &premier& 2 3?
Fap ,7 ;second; 2 .?
Fap ,7 &troisieme& 2
Hrray ,7 ? 2 3?
Hrray ,7 ;3; 2 .?
Hrray ,7 4 2
Hrray ,7 inde" 2 .?

i des l!ents dans la !ap n'e)istent pas ou si on dpasse


l'inde) !a) du ta-leau. renvoie une chaine vide
@>
8&L . oprateurs

Lprateurs logi$ues

RR (ou and+. SS (ou or+. 8 (ou not+

Lprateurs de co!paraison

)) (ou eq+. 8) (ou ne+. W (ou gt+ ...

Lprateurs de calcul

B. ,. T. ' (ou div+. 6 (ou mod+

T%pes de no!-re disponi-les * entier et rel

<ivers

empty * renvoie vrai si valeur 8vide9

Egale ? null. chaine vide. un ta-leau vide ou une !ap vide

_ * choi) conditionnel

test U choi":rai 2 choi"+au"


@@
%$TL . core

"our utiliser du PT1 core dans une page P". insrer la


-alise suivante dans la page

569tagli= uri)&http2''1ava.sun.com'1sp'1stl'core& prefi")&c& 67

3u dploie!ent. ne pas ou-lier le lien vers la li-rairie (.6ar+ e)terne


i!pl!entant cet ense!-le de -alises

3ffichage d'une valeur

5c2out value);;valeur;; '7

Test d'une valeur

5c2if test);;condition;;7 ... 5'c2if7

Choi) conditionnels

5c2choose7
5c2hen test);;condition1;;7 ... 5'c2hen7
5c2hen test);;condition2;;7 ... 5'c2hen7
...
5c2otherise7 ... 5'c2otherise7
5'c2choose7
@B
%$TL . core

"arcours d'une liste = ta-leau

5c2for!ach items);;laListe;; var);;eltCourant;;7


...
5'c2for!ach7

items * la liste ou le ta-leau ? parcourir

var * varia-le $ui contiendra l'l!ent courant

"arcours d'une !ap

Co!!e pour une liste !ais sur l'l!ent courant

3ccde ? sa cl via * eltCourant.Key

3ccs ? sa valeur via * eltCourant.value

3utres tags e)istants

5c2for%oKens7,5c2set7, 5c2remove7, 5c2catch7,


5c2import7, 5c2url7, 5c2redirect7, 5c2param7
@C
%$TL . core

E)e!ple

5c2if test)&OAempty sessionScope.arrayRectP4Q."3C&7


/as d;IlIment d;inde" 4 dans le ta=leau5=r '75=r '7
5'c2if7
Surface des rectangles 25=r '7
5c2for!ach items)&OAsessionScope.arrayRectC& var)&rect&7
,7 5c2out value)&OA(rect."4 , rect."3) T (rect.y4 , rect.y3)C&'75=r '7
5'c2for!ach7

3ffichage rsultant

/as d;IlIment d;inde" 4 dans le ta=leau


Surface des rectangles 2
,7 3??
,7 V??
BD
$ervlet vs %$P

ervlet

C'est du 6ava standard $ui est e)cut

1es lignes 8out.println(+9 servent ? gnrer le code GTM1 $ui


sera affich

"ro-l!e * une -onne partie de ce code GTM1 est stati$ue

Ent5te. affichage du titre ...

'n peu lourd ? gnrer de la sorte

"age P"

"er!et de 8!langer9 du code GTM1 standard avec du Pava


standard

Meilleure dcoupage des diffrentes parties $u'avec des servlets

Moins lourd ? progra!!er $u'une servlet

i!plification des affichages des donnes. surtout si co!-in avec


'E1 et PT1

Mais !oins structur du point de vue du code Pava


B1
$ervlet et %$P

ervlet = P"

Technologie cot serveur per!ettant donc la gnration


d%na!i$ue de page GTM1

Intr5t est de profiter de la puissance d'un langage L-6et

En prati$ue

1e code e!-ar$u dans les ervlet = P" n'intgre pas


de prfrence le code et la logi$ue !tier

Ln s'appuie sur d'autres l!ents (co!posants EP2 par


e)e!ple+

"our un serveur applicatif ,e-. dcouper son r`le en

1ogi$ue de prsentation

Manire de prsenter et de gnrer les pages au) clients

1ogi$ue !tier

3ppele par la logi$ue applicative pour gnrer les pages


B2
ra!ewor"s de persistance .
introduction ; /ibernate
B#
Probl!atique

E)e!ple si!ple d'application

&rer une liste de personnes

"rogra!!ation partie !tier = client en Pava

Classe $ui contient les infor!ations sur une personne

pu=lic class /ersonne A


String nom(
#nt age(

'' mIthodes d;accLs au" attri=uts age et nom
C

1ors du stocMage d'une personne. on lui associera un identifiant uni$ue

<eu) techni$ues de stocMages de l'ense!-le de personnes

<irecte!ent en Pava via une GashMap

Hashmap5#nteger, /ersonne7 personnes(

Hia un &2< avec accs en O1 au) donnes

tocMage sous for!e de ta-les O1


personne (int id, varchar(4?) nom, int age)
B4
Probl!atique

Code pour rcuprer une personne via son id

"ur Pava
pu=lic /ersonne get/ersonne(int id) thros #nvalid#d!"ception A
'' si la personne n;e"iste pas, lLve e"ception
if ( 8 (personnes.containsWey(ne #nteger(id))))
thro ne #nvalid#d!"ception(&invalid inde" value 2 &Bid)(
'' sinon, retourne son identifiant
return (personnes.get(ne #nteger(id)))(
C

Manipule directe!ent la GashMap personnes

Code 8naturel9. progra!!ation Pava standard


B;
Probl!atique

Pava avec stocMage 2<< et accs via P<2C

pu=lic int get#d(/ersonne p) thros #nvalid#d!"ception A


try A
Statement requete ) connection.createStatement()(

'' requMte SX> pour rechercher la personne
ResultSet result ) requete.e"ecuteXuery(&S!>!C% @$F, HG!
+R$F /!RS$@@! 0H!R! #J)Y&&BidB&Y&&)(
'' regarde si la requMte a renvoyI quelque chose 2 si Za n;est pas
'' le cas, la personne n;e"istait pas
if (8result.ne"t())
thro ne #nvalid#d!"ception(&invalid inde" value 2 &Bid)(
'' sinon, N partir du rIsultat retournI, instancie une personne
'' avec les valeurs du rIsultat
else return ne /ersonne(result.get#nt(&age&), result.getString(&nom&))(
C
catch(SX>!"ception e) A
System.err.println(e)( C
C
B>
Probl!atique

Pava avec stocMage 2<< et accs via P<2C

Ecessite des re$u5tes O1

'tilisation d'un fra!eForM ddi * P<2C

ort du for!at 8standard9 de reprsentation Pava des


donnes

'ne re$u5te de t%pe E1ECT retourne un Iesultet

C'est ? dire un ense!-le de ligne de plusieurs colonnes

Ln accde au) l!ents du Iesultet en naviguant selon les


lignes et les colonnes

"eu prati$ue !ais difficile de faire autre!ent vu ce $ue retourne


de !anire native les re$u5tes O1

auf ? passer par des &2< o-6et-relationnel


B@
Probl!atique

Pava avec stocMage 2<< et accs via P<2C

3u dela de l'accs ? faire ? distance

Oui co!ple)ifie forc!ent les choses !ais ne peut pas % couper

Ieprsentation des donnes trs diffrentes

Cot 2<<

tructure en ta-le avec langage de re$u5te ddi

Icupre tou6ours une 8sous-ta-le9 via le rsultat de l'e)cution


d'une re$u5te de t%pe E1ECT

Cot Pava

Instances de classe ("ersonne ici+ * o-6ets

1es o-6ets sont associs entre eu) et for!ent un graphe d'o-6et


dans l'application
_
BB
Probl!atique

<oit 5tre capa-le de faire la correspondance d'une


reprsentation ? une autre

"as si!ple * d'une reprsentation o-6et ? une


reprsentation relationnelle

olution

1e faire ? la !ain

Co!!e pour notre e)e!ple

'tiliser une -ase de donnes relationnelle oriente o-6et

Cot 2<<. la structure de stocMage intgrera des concepts o-6ets

"assage plus facile du progra!!e au stocMage dans la -ase

Mais tou6ours -esoin de faire des re$u5tes e)plicites

'tiliser un fra!eForM de persistance


BC
ra!ewor" de persistance

"rincipes

'a-straire des pro-l!ati$ues de stocMage des donnes

"ouvoir !anipuler directe!ent des entits !tiers


indpenda!!ent de leur stocMage ph%si$ue

<finition de !appings entre

1a structure des classes utilises dans l'application

1e stocMage ph%si$ue utilis par le support de persistance

&nrale!ent. un &2< relationnel

1ors de l'e)cution de l'application

Cration. suppression. !anipulation. collections d'o-6ets ... grs


de !anire classi$ue. progra!!ation 8standard9

1e fra!eForM fait le lien entre le graphe d'o-6et en !!oire dans


l'application et le stocMage ph%si$ue

T%pi$ue!ent * envoi de re$u5te O1 au &2< pour


rcuprer des donnes. les !odifier. les a6outer = suppri!er
CD
ra!ewor" de persistance

Intr5t des fra!eForMs de persistance

"lus -esoin de se proccuper du stocMage ph%si$ue et des


pro-l!es de correspondance

Co!!e on le voit dans notre e)e!ple de l'atelier

Ecriture des re$u5tes O1 via P<2C est asseJ lourd

1'i!pl!entation des accs au) donnes peut reprsenter un te!ps


i!portant lors du dveloppe!ent d'une application

Ln gagne ainsi en te!ps de dveloppe!ent et en indpendance


des supports ph%si$ues

uffit de changer les rgles de !appings sans !odifier le code de


l'application

Gi-ernate

/ra!eForM de persistance li-re pour le !onde Pava

EGi-ernate pour .Eet

tandard de fait. trs utilis dans l'industrie

'tilis gale!ent par P"3 (fra!eForM standard de


persistance sous Pava : Pava "ersistence 3"I+
C1
/ibernate

"rincipes gnrau) d'Gi-ernate

<finition des structures de donnes = entits !anipules

Ielation entre la structure cot 2<< et la structure des entits

Hia des fichiers 0M1

Lu des classes Pava annotes

Cot Pava. l'entit est une classe Pava dite persistante

'n "LPL * "lain Lld Pava L-6et

Classe Pava totale!ent standard avec dfinition d'attri-uts.


d'accesseurs. de constructeurs pour gestion donnes de l'entit

Ee s'appuie donc pas sur des fra!eForMs ou li-rairies particuliers.


contraire!ent par e)e!ple au) entits d'EP2

"ersistante * son contenu est li avec les donnes ph%si$ues sur


la 2<< et est sauvegard dans cette 2<<

<finition. en 0M1. d'un ense!-le de fichiers de configuration

Mapping d'une entit vers un support ph%si$ue

Configuration gnrale de l'accs au support ph%si$ue


C2
/ibernate

"rincipes gnrau) d'Gi-ernate (fin+

"our grer la persistance. on cre une session Gi-ernate

Hia cette session. peut

Icuprer sous for!e d'instances de "LPL des donnes


stocMes par le support ph%si$ue

'tilisation nota!!ent d'GO1 (Gi-ernate Ouer% 1anguage+

Modifier le contenu de ces "LPL. leurs associations. en a6outer.


en suppri!er. ...

1e fra!eForM fera le lien entre les !odifications locales et le


stocMage ph%si$ue

/onctionne en !ode transactionnel pour les !odifications


1. Cration d'une transaction
2. Modification des o-6ets
#. Halidation de la !odification (co!!it+ ou annulation
en cas de pro-l!e (roll-acM+
C#
&#e!ple /ibernate

E)e!ple de gestion de sports et de disciplines

'n sport contient plusieurs disciplines

Ta-les du &2< (Lracle ici+

sport (code)sport . intitule+


discipline (code)discipline. intitule. codeasport+

Ici cot Pava. on choisira d'avoirdes o-6ets de t%pe Sport


et Jiscipline

3vec les !5!es structures de donnes $ue ce $ui est stocM


dans la -ase

Mais Sa n'est pas une o-ligation d'avoir e)acte!ent la !5!e


chose (voir plus loin+
C4
&#e!ple /ibernate

Contenu des ta-les pour l'e)e!ple

Ta-le sport
code M
sport M intitule
,,,,,,6,,,,,,,,,,,
2 M athletisme
@ M sAi
F M natation

Ta-le discipline
code M M code
discipline M intitule M sport
,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,6,,,,,,
2 M 200 metres M 2
@ M @00 metres M 2
F M saut en hauteur M 2
G M saut en lon/ueur M 2
N M 200m G na/es M F
O M 200m papillon M F
P M marathon M 2
C;
/ibernate . e#) con(iguration gnrale

Configuration gnrale d'Gi-ernate

Uhi-ernate-configurationW
Usession-factor%W
Upropert% na!eX^hi-ernate.dialect^Worg.hi-ernate.dialect.Lracle<ialectU=propert%W
Upropert% na!eX^hi-ernate.connection.driveraclass^Woracle.6d-c.Lracle<riverU=propert%W
Upropert% na!eX^hi-ernate.connection.url^W6d-c*oracle*thin*@scinfeDCC*1;21*etud1DU=propert%W
Upropert% na!eX^hi-ernate.connection.userna!e^WecariouU=propert%W
Upropert% na!eX^hi-ernate.connection.passFord^WtotoU=propert%W
Upropert% na!eX^hi-ernate.shoFas$l^WtrueU=propert%W
U!apping classX^data.port^ fileX^^ 6arX^^ pacMageX^^ resourceX^data=port.h-!.)!l^=W
U!apping classX^data.<iscipline^ fileX^^ 6arX^^ pacMageX^^ resourceX^data=<iscipline.h-!.)!l^=W
U=session-factor%W
U=hi-ernate-configurationW

Ln % trouve. nota!!ent

1es para!tres de conne)ion ? la -ase Lracle (avec le t%pe de


driver ? utiliser+

Ln peut voir $ue l'accs en prati$ue se fera via P<2C

1'association d'un "LPL avec son fichier de !apping

E)* data.Sport (classe Pava+ dont le !apping est prcis dans


Sport.h=m."ml
C>
/ibernate . e#) de (ichier de !apping

/ichier port.h-!.)!l

Uhi-ernate-!appingW
Uclass na!eX^data.port^ ta-leX^"LIT^ sche!aX^EC3IIL'^W
Uid na!eX^codeport^ t%peX^short^W
Ucolu!n na!eX^CL<Ea"LIT^ precisionX^4^ scaleX^D^ =W
Ugenerator classX^assigned^ =W
U=idW
Upropert% na!eX^intitule^ t%peX^string^W
Ucolu!n na!eX^IETIT'1E^ lengthX^2D^ =W
U=propert%W
Uset na!eX^disciplines^ inverseX^true^W
UMe%W
Ucolu!n na!eX^CL<Ea"LIT^ precisionX^4^ scaleX^D^ =W
U=Me%W
Uone-to-!an% classX^data.<iscipline^ =W
U=setW
U=classW
U=hi-ernate-!appingW

<ans classe data.Sport. attri-utcodeSport correspond ? la colonne


CL<Ea"LIT de la ta-le "LIT

<finition d'un ense!-le no!! disciplines dans la classe data.Sport

Pointure avec la ta-le discipline * toutes les disciplines de ce sport


C@
/ibernate . e#) de P<%<

"LPL d'un sport. gnr ? partir du fichier de !apping

pu-lic class port i!ple!ents 6ava.io.erialiJa-le b


private short codeport[
private tring intitule[
private et disciplines X neF Gashet(D+[
pu-lic port(+ b
c
pu-lic port(short codeport+ b
this.codeport X codeport[
c
pu-lic port(short codeport. tring intitule.
et disciplines+ b
this.codeport X codeport[
this.intitule X intitule[
this.disciplines X disciplines[
c

<finition des attri-uts. avec


getter et setter associs

<finition des constructeurs (avec un constructeur sans para!tre+

Iedfinir !thodes equals() et hashcode() pour gestion dans collections


pu-lic short getCodeport(+ b
return this.codeport[
c
pu-lic void setCodeport(short codeport+ b
this.codeport X codeport[
c
pu-lic tring getIntitule(+ b
return this.intitule[
c
pu-lic void setIntitule(tring intitule+ b
this.intitule X intitule[
c
pu-lic et get<isciplines(+ b
return this.disciplines[
c
pu-lic void set<isciplines(et disciplines+ b
this.disciplines X disciplines[
c
CB
/ibernate . e#) acc1s au# donnes

3ffichage de la liste des sports. avec pour chacun la liste


de ses disciplines

'' crIation session Hi=ernate (et donc conne"ion au serveur $racle)


Session session ) (ne
Configuration().configure().=uildSession+actory()).openSession()(

'' requMte en HX> 2 rIcupLre la liste de tous les sports,
'' sous forme d;une liste <ava
Xuery query ) session.createXuery(&from data.Sport&)(
>ist sports ) query.list()(
'' varia=les utilisIes pour le parcours de la liste des sports
Set disciplines(
#terator itSport, itJisc(
Sport sport(
Jiscipline disc(
CC
/ibernate . e#) acc1s au# donnes

3ffichage de la liste des sports. avec pour chacun la


liste des disciplines (suite+

'' parcourt les sports


itSport ) sports.iterator()(
hile (itSport.has@e"t()) A
sport ) (Sport) itSport.ne"t()(
System.out.println(sport.getCodeSport() B & ,7 & B sport.get#ntitule())(
'' rIcupLre l;ensem=le des disciplines du sport
disciplines ) sport.getJisciplines()(
itJisc ) disciplines.iterator()(
'' parcourt les disciplines
hile (itJisc.has@e"t()) A
disc ) (Jiscipline) itJisc.ne"t()(
System.out.println(& &Bdisc.getCodeJiscipline() B
& ,7 &Bdisc.get#ntitule())(
C
C
1DD
/ibernate . e#) acc1s au# donnes

3ffichage rsultant de l'e)cution

3 ,7 athletisme
3 ,7 3?? metres
4 ,7 4?? metres
[ ,7 marathon
V ,7 saut en longueur
. ,7 saut en hauteur
4 ,7 sKi
. ,7 natation
\ ,7 3??m papillon
] ,7 3??m V nages

"oint intressant

3 partir d'un o-6et de classe Sport. on accde directe!ent ? sa


liste de disciplines via getJisciplines() * ense!-le d'o-6ets

1es o-6ets sont chargs ? partir de la -ase directe!ent sans -esoin


de traite!ent particulier. c'est transparent

i on tait pass par du O1 via P<2C. on aurait du faire une


re$u5te e)plicite du t%pe

E1ECT d /ILM <ICI"1IEE ,GEIE CL<Ea"LITX00


1D1
/ibernate . e#) acc1s au# donnes

3 l'e)cution. peut de!ander ? tracer les re$u5tes O1


effectues. ce $ui donne ici

Hibernate: select sport0_.CODE_SPOR as CODE1_0_! sport0_."#"$LE


as "#"$LE0_ %ro& EC'R"O$.SPOR sport0_
3 ,7 athletisme
Hibernate: select discipline0_.CODE_SPOR as CODE2_1_!
discipline0_.CODE_D"SC"PL"#E as CODE1_1_!
discipline0_.CODE_D"SC"PL"#E as CODE1_1_0_!
discipline0_.CODE_SPOR as CODE2_1_0_! discipline0_."#"$LE as
"#"$LE1_0_ %ro& EC'R"O$.D"SC"PL"#E discipline0_ ()ere
discipline0_.CODE_SPOR*+
3 ,7 3?? metres
4 ,7 4?? metres
[ ,7 marathon
V ,7 saut en longueur
. ,7 saut en hauteur
(...)

"re!ier E1ECT * pour rcuprer la liste des sports

<eu)i!e E1ECT * pour rcuprer la liste des


disciplines du sport courant
1D2
/ibernate . e#) acc1s au# donnes

3utre e)e!ple * a6out d'une discipline au sport natation

try A
'' ouvre la session et une transaction
session ) (ne Configuration().configure().=uildSession+actory()).openSession()(
trans ) session.=egin%ransaction()(
'' rIcupLre l;instance de sport correpondant Nnatation (requMte en HX>)
query ) session.createXuery(&select sport from Sport sport here sport.intitule);natation;&)(

'' a1out du relais V " 3?? dans le sport natation en rendant l;o=1et persistant
disc ) ne Jiscipline((short)-, sport, &relais V " 3??&)(
session.persist(disc)(
'' commit pour valider physiquement l;a1out
trans.commit()(
C catch (!"ception e) A
System.err.println(&!rreur Hi=ernate 2 & B e)(
'' pro=lLme 2 on annule la transaction
trans.roll=acK()(
C
session.close()(
1D#
/ibernate . e#) acc1s au# donnes

Eotes sur code d'a6out

Ln cre l'o-6et discipline disc avec l'o-6et sport en para!tre

Ln passe une rfrence d'o-6et. on ne donne pas une cl identifiant


un sport co!!e on le ferait avec O1

Ln est -ien dans de la !anipulation 8standard9 d'o-6ets

1e persist() sur cet o-6et per!et directe!ent. sans traite!ent


suppl!entaire. de le rendre persistant (voir plus loin pour dtails+

C'est-?-dire l'enregistrer dans la 2<<

i on trace les re$u5tes O1. on o-tient

Hi=ernate2 select sport?^.C$J!^S/$R% as C$J!3^?^, sport?^.#@%#%*>! as


#@%#%*>!?^ from !CHR#$*.S/$R% sport?^ here
sport?^.#@%#%*>!);natation;
Hi=ernate2 insert into !CHR#$*.J#SC#/>#@! (C$J!^S/$R%, #@%#%*>!,
C$J!^J#SC#/>#@!) values (U, U, U)

1a pre!ire re$u5te est un E1ECT $ui rcupre les donnes du


sport 8natation9

1a deu)i!e re$u5te est un IEEIT $ui a6oute la discipline


$u'on vient de crer
1D4
&#e!ple plus dtaill

Modlisation !tier de l'application de sports avec


a6out d'une classe = entit sportif
1D;
&#e!ple plus dtaill

Classes Sport et Jisciplines

Ieprend les !5!es contenus $u'on vient de voir

'ne discipline est associe ? un sport

36oute une entit Sportif

'n sportif prati$ue plusieurs disciplines et une discipline est


prati$ue par plusieurs sportifs

3ssociation -idirectionnelle T 5,7 T pratique entre les 2 classes

3ttri-ut n=Jisciplines est driv

1e no!-re de disciplines se dter!ine ? partir de l'association prati$ue

E). en LC1 *
conte"t Sportif def2 n=Jisciplines 2 int ) pratique ,7 siGe()

'n sportif a un no! et une adresse

3ssociation unidirectionnelle drive 'sports entre Sportif et Sport

1es sports prati$us par le sportif

e dter!ine de l'association pratique en rcuprant les sports


de ces disciplines * pratique.sport ,7 asSet()
1D>
&#e!ple plus dtaill

Ta-les associes dans le &2<

Conserve les ta-les sport et discipline d6? vues

sport (code_sport, intitule)

discipline (code_discipline, intitule, code^sport)

code^sport * cl trangre venant de sport

<onnes sur un sportif

'ne adresse est spcifi$ue ? un sportif * peut inclure les


donnes de l'adresse avec les donnes du sportif

sportif(code_sporti%, nom, rue, code^postal,ville)

3ssociation entre disciplines et sportifs * ncessite une


ta-le d'association

pratique(code_sporti%! code_discipline)

Cl pri!aire * co!-inaison de code^sportif et code^discipline

Cls trangres * code^sportif de sportif et code^discipline


de discipline
1D@
&#e!ple plus dtaill

"oint fonda!ental lors de l'utilisation d'un fra!eForM de


persistance

"as de ncessit=peu reco!!and d'avoir un !apping 1 vers 1


entre une ta-le de la 2<< et une classe cot !tier

Ln !odlise d'un cot le !tier et de l'autre la 2<< en s'attachant ?


faire les !eilleures !odlisations selon le do!aine

Cot !tier * structure logi$ue et facilit de !anipulation des donnes

Cot 2<< * opti!iser la sauvegarde des donnes et perfor!ance d'accs

Ln dfinira ensuite les !appings ad$uats

<ans notre e)e!ple

1es donnes de la classe Hdresse et de la classe Sportif sont stocMes


via une seule ta-le et non pas deu) ta-les diffrentes

1a ta-le d'association pratique n'a pas ? 5tre reprsente par une


classe

Ln aura directe!ent des !thodes dans les classes Sportif et Jiscipline


pour rcuprer les l!ents correspondants

1e fichier de !apping per!ettra de directe!ent grer cette association

1'attri-ut n=Jisciplines est utile=pertinent seule!ent cot !tier


1DB
'apping pour la classe $porti(

Contenu de la classe Sportif * "LPL

pu=lic class Sportif implements 1ava.io.SerialiGa=le A


private int codeSportif(
private String nom(
private Set disciplines ) ne HashSet(?)(
private int n=Jisciplines(
private Hdresse adresse(

pu=lic Sportif() A
C
(...)

<finition des attri-uts

3vec disciplines $ui est une association ? cardinalit !ultiple


donc utilise un et

Cha$ue attri-ut doit possder un getter et un setter

L-ligation d'un contructeur sans para!tre

"eut en dfinir d'autres en plus


1DC
'apping pour la classe $porti(

/ichier de !apping pour la classe Sportif

5hi=ernate,mapping7
5class name)&data.Sportif& ta=le)&sportif& catalog)&sports&7

1a classe persistante data.Sportif se -ase sur le contenu de la ta-le


sportif

5id name)&codeSportif& type)&int&7


5column name)&code^sportif& '7
5generator class)&assigned& '7
5'id7

<finition d'un attri-ut codeSportif correspondant ? la colonne


code^sportif de la ta-le

1a -alise 5id7 prcise $u'on est en train de dfinir un attri-ut 6ouant


le r`le particulier d'identification de l'o-6et

2alise non o-ligatoire !ais forte!ent reco!!ande

"ar principe. elle sera en gnral lie ? la cl pri!aire de la ta-le

1a -alise 5generator7 prcise co!!ent l'identifiant est gnr

assigned * gr ? la !ain par celui $ui cre les classes

"eut utiliser d'autres valeurs pour une gnration auto!ati$ue


(voir plus loin+
11D
'apping pour la classe $porti(

5property name)&nom& type)&string&7


5column name)&nom& length)&4?& '7
5'property7

2alise 5property7 dfinit une proprit au sens des Pava 2eans.


concrte!ent. un attri-ut si!ple (autre $u'une collection. ta-leau ...+
de la classe

Ici l'attri-ut nom !appe la colonne nom de la ta-le

5property name)&n=Jisciplines& type)&integer&


formula ) &(select count(T) from /RH%#X*! p here
code^sportif ) p.code^sportif)& '7

Cha!p formula (ou -alise 5formula7+ per!et de dfinir une


for!ule (e)pression O1+ au lieu d'un !apping vers une colonne
d'une ta-le

Ici on co!pte le no!-re de disciplines associes au sportif courant via


une re$u5te sur la ta-le pratique

1'appel du setter associ (set@=Jisciplines+ ne servira ? rien ...


111
'apping pour la classe $porti(

5component name)&adresse& class)&data.Hdresse&7


5property name)&rue& type)&string&7
5column name)&rue& length)&]?& '7
5'property7
5property name)&code/ostal& type)&string&7
5column name)&code^postal& length)&]& '7
5'property7
5property name)&ville& type)&string&7
5column name)&ville& length)&3]& '7
5'property7
5'component7

2alise 5component7 dfinit un l!ent co!pos (relation 'M1 de


co!position+ dans la classe courante

Ici on dfinit un attri-ut adresse de classe Hdresse $ui contient les attri-uts
rue. code/ostal et ville !appant les colonnes $uivalentes dans la ta-le
sportif (la ta-le de la classe englo-lante+

1a classe Hdresse est dfinie co!!e un "LPL car sera persitante

pu=lic class Hdresse implements 1ava.io.SerialiGa=le A


private String rue(
private String code/ostal(
private String ville(
112
'apping pour la classe $porti(

5set name)&disciplines& inverse="false" ta=le)&pratique&7


5Key7
5column name)&code^sportif& not,null)&true& '7
5'Key7
5many,to,many entity,name)&data.Jiscipline&7
5column name)&code^discipline& not,null)&true& '7
5'many,to,many7
5'set7

2alise 5set7 dfinit un ense!-le de donnes

Correspond ici au !apping d'une association avec une cardinalit


!ultiple sur une autre ta-le (ici pratique+

2alise 5Key7 * cl trangre sur la ta-le avec la$uelle on fait la 6ointure

ur la ta-le pratique. la cl trangre est code^sportif

2alise 5many,to,many7 dfinit une association en T 5,7 T

Ln fait la 6ointure sur la colonne code^discipline de pratique

Ietournera des instances de la classe Jiscipline

1'attri-ut disciplines de la classe Sportif correspond donc ? l'ense!-le


des disciplines trouves dans pratique avec le !5!e
code^sportif $ue le sportif courant
11#
Association bidirectionnelle

<ans la classe Jiscipline. on trouvera l'association


inverse. de discipline vers sportif

<ans la classe Jiscipline. attri-ut

private Set sportifs(

<ans le !apping de la classe Jiscipline

5set name)&sportifs& inverse="true" ta=le)&pratique&7


5Key7
5column name)&code^discipline& not,null)&true& '7
5'Key7
5many,to,many entity,name)&data.Sportif&7
5column name)&code^sportif& not,null)&true& '7
5'many,to,many7
5'set7

Ense!-le de sportifs correspondant ? la 6ointure via la ta-le


pratique et la cl code^discipline
114
Association bidirectionnelle

Contrainte pour un !apping d'association -idirectionnelle

<'un des deu) cots. on doit avoir un inverse ) true dans la


dfinition du set (et un false. par dfaut. de l'autre+

Ici c'est dans le !apping pour la classe Jiscipline

<ans les classes. pour assurer la -idirectionnalit. on doit


faire un a6out dans les deu) ense!-les des deu) l!ents

Classe Sportif

pu=lic void addJiscipline(Jiscipline disc) A


this.disciplines.add(disc)(
disc.getSportifs().add(this)
C

Classe Jiscipline

pu=lic void addSportif(Sportif sportif) A


this.sportifs.add(sportif)(
sportif.getJisciplines().add(this)(
C
11;
Association et cardinalits

Ouatre t%pe d'associations. par 6ointure en


prcisant la cl trangre

Uone-to-oneW

'n vers un

Uone-to-!an%W

'n vers plusieurs * sport vers discipline

U!an%-to-oneW

"lusieurs vers un * discipline vers sport

U!an%-to-!an%W

"lusieurs vers plusieurs * entre discipline et sportif

Ecessite une ta-le d'association entre les 2 ta-les


11>
'apping pour la classe $porti(

Ieste ? dfinir l'ense!-le (driv+ des Sports

Consiste ? rcuprer les sports des disciplines du sportif


courant

En O1. 6ointure sur les 4 ta-les pratique. discipline.


sportif et sport. en fonction de la valeur code_&onSporti%

select distinct(sport.code^sport), sport.intitule


from discipline, pratique, sportif, sport
where sportif.code^sportif ) code_&onSporti% and
discipline.code^discipline ) pratique.code^discipline and
pratique.code^sportif ) sportif.code^sportif and
sport.code^sport ) discipline.code^sport

<ifficile ? e)pri!er par un !apping Gi-ernate. on va


passer par une re$u5te

Ia6oute dans la classe Sportif la !thode suivante

pu=lic Set5Sport7 getSports() A ... C

"as -esoin d'un attri-ut sports car il ne sera pas persistant


11@
7equ=te get$ports34

"re!ire (!auvaise+ i!pl!entation

'tilisation de Pava au !a)i!u!

pu=lic Set5Sport7 getSports() A


Set5Sport7 sports ) ne HashSet5Sport7()(
#terator it ) this.getJisciplines().iterator()(
hile (it.has@e"t())
sports.add(((Jiscipline)it.ne"t()).getSport())(
return sports(
C

"arcourt les disciplines du sportif et rcupre pour chacun le sport


associ

Ln place ces sports dans un et ($ui par principe ne contiendra pas


de dou-lon+

Trs !auvaise ide T

Ln o-lige en effet ? charger en !!oire (de la 2<< vers le


progra!!e Pava+ toutes les disciplines du sportif alors $u'on n'en a
pas -esoin

"ro-l!e potentiel de perfor!ance


11B
7equ=te get$ports34

2onne i!pl!entation

"asser par une re$u5te en GO1 (Gi-ernate Ouer% 1anguage+

E$uivalente ? celle $u'on aurait faite en O1 ... !ais en plus si!ple

pu=lic Set5Sport7 getSports() A



Set5Sport7 sports ) ne HashSet5Sport7()(
'' crIation de la requMte
Xuery query ) session.createXuery(
&select distinct(sport) from data.Sport sport, data.Jiscipline disc&B
&here disc.sport ) sport and :leSportif in elements(disc.sportifs)&)(

'' le sportif est l;o=1et courant
query.set/arameter(&leSportif&, this)(
'' construit le set N retourner N partir de la liste rIsultat de la requMte
#terator it ) query.list().iterator()(
hile (it.has@e"t())
sports.add(it.ne"t())(
return sports(
C

Eote * ne pas ou-lier de grer en plus les e)ceptions


11C
Langage de requ=te />L

Ie$u5te GO1 prcdente

e lit asseJ si!ple!ent * rcuprer la liste des sports des


disciplines $ui sont associes au sportif pass en para!tre

'tilisation d'un para!tre no!! pour prciser le sportif

query.set/arameter(;;nom/aram;;, valeur)(

3vec la valeur pouvant directe!ent 5tre un o-6et

Co!!e ici * c'est une instance de la classe Sportif

E)cution de la re$u5te

3ppel de list() sur l'o-6et re$u5te $ui retourne la liste des rsultats

Ln peut ensuite associer un itrateur ? cette liste

3ttention T

Il e)iste une !thode iterate() appela-le directe!ent sur l'o-6et re$u5te

#terator it ) query.iterate()(

Cette !thode ne charge pas en !!oire les o-6ets persistants


retourns par la re$u5te

'ils taient d6? chargs. Sa !arche. sinon on ne rcupre rien

<onc privilgier l'usage de * #terator it ) query.list().iterate()(


12D
Langage de requ=te />L

GO1 est un langage de re$u5te aussi puissant $ue O1 et


$ui est en plus orient o-6et

"er!et de !anipuler directe!ent des o-6ets (instances de "LPL+

<finir une 8varia-le9 sport correspondant ? une instance de la


classe data.Sport 2 ... data.Sport sport ...

"er!et de naviguer sur les associations entre o-6ets

Icuprer l'o-6et sport associ ? une discipline 2 ... disc.sport ...

M5!es fonctionnalits $ue O1. gestion du pol%!orphis!e...

3u final. les re$u5tes GO1 sont gnrale!ent (-ien+ plus


si!ples $ue les re$u5tes O1 $uivalentes

Trace de la re$u5te O1 e)cute

select distinct sport?^.code^sport as code3^[^, sport?^.intitule as


intitule[^ from sports.sport sport?^, sports.discipline discipline3^
where discipline3^.code^sport)sport?^.code^sport and (U in
(select sportifs4^.code^sportif from pratique sportifs4^ where
discipline3^.code^discipline)sportifs4^.code^discipline))

<eu) re$u5tes E1ECT i!-ri$ues sur 4 ta-les


121
Langage de requ=te />L

i l'on sait $u'une re$u5te ne renvoie $u'un seul rsultat

"eut utiliser uniqueResult() au lieu de list() pour rcuprer le


rsultat

query ) session.createXuery(&select sport from data.Sport sport here


sport.codeSport ) ;4; &)(
Sport sport ) (Sport)query.uniqueResult()(
if (sport )) null) System.out.println(&/as de sport 4&)(
else System.out.println(&>e sport 4 est 2 &Bsport.get#ntitule())(

i une re$u5te slectionne plus d'une valeur. on rcupre


un ense!-le de ta-leau). un ta-leau par rsultat

query ) session.createXuery(&select sportif.nom, sportif.adresse.ville


from data.Sportif sportif&)(
#terator it ) query.list().iterator()(
System.out.println(&@om des personnes avec leur ville&)(
hile(it.has@e"t()) A
$=1ectPQ res ) ($=1ectPQ)it.ne"t()(
System.out.println(&nom 2 & B resP?Q B &, ville 2 & B resP3Q)(
C
122
5ycle de vie d'un ob:et persistant

Toutes les fonctions de gestion du c%cle de vie d'un o-6et


se font par rapport ? une session Gi-ernate ouverte

Toute !odification d'tat se fait en !ode transactionnel

Iendre persistant un o-6et. !odifier le contenu d'un o-6et


persistant. suppri!er un o-6et persistant. ...

ch!a gnral ? appli$uer de prfrence

En cas d'erreur (e)ception leve+ lors de la transaction. e)cuter


s%st!ati$ue!ent un roll-acM pour annuler ce $ui a pu 5tre !odifi

session ) (ne Configuration().configure().=uildSession+actory()).openSession()(


(...)
try A
trans ) session.=egin%ransaction()(
'' faire les modifications voulues
(...)
'' pas d;erreur, on commit
trans.commit()(
C catch (!"ception e) A
'' pro=lLme 2 on annule tout
if (trans 8) null) trans.roll=acK()(
C
12#
5ycle de vie d'un ob:et persistant

"lusieurs !thodes pour charger un o-6et persistant ?


partir de la 2<<

E)cuter des re$u5tes GO1 co!!e on l'a vu

'tiliser des re$u5tes natives O1

SX>Xuery query ) session.createSX>Xuery(...)(

Icuprer une conne)ion P<2C puis faire des re$u5tes O1

Connection conn ) session.connection()(

'tiliser l'3"I Criteria

i on connait l'identifiant d'un o-6et * load() ou get()

Charger le sportif d'identifiant gal ? 2

Sportif sportif ) session.load(Sportif.class, 4)(

<iffrence entre load() et get()

i ne trouve pas l'o-6et (identifiant ine)istant+. load() lve une e)ception et


get() renvoie null

Contraire!ent ? get(), load() ne charge pas forc!ent tout de suite l'o-6et


en !!oire. l'e)ception potentielle sera donc leve
seule!ent $uand on accdera au) donnes de l'o-6et
124
5ycle de vie d'un ob:et persistant

Crer un o-6et et le rendre persistant

Instantier de !anire nor!ale un "LPL et positionner la valeur de


ses attri-uts

i l'on ne veut pas grer soi !5!e la cl pri!aire associ au


"LPL dans la 2<<

<ans fichier de !apping. -alise 5id7, -alise 5generator7. cha!p


class peut prendre diffrentes valeurs

assigned * ? la charge de celui $ui instancie l'o-6et de fi)er la cl pri!aire


(valeur par dfaut si aucun gnrateur n'est prcis+

native * laisse le &2< dter!iner la cl pri!aire (valeur entire


seule!ent+ selon ses fonctionnalits

uuid * identifiant sous for!e de chaine. en utilisant l'adresse I" de la


!achine

....

Ensuite. on rend l'o-6et persistant via l'appel de persist() ou save()


sur la transaction courante

Sport sport ) ne Sport()(


sport.set#ntitule(;;pMche;;)(
session.persist(sport)(
12;
5ycle de vie d'un ob:et persistant

Crer un o-6et et le rendre persistant (suite+

<iffrence entre persist() et save()

save() ralise i!!diate!ent la gnration de la cl !ais


l'enregistre!ent ph%si$ue se fera plus tard

persist() fait les deu) actions si!ultan!ent et i!!diate!ent

3ttention au) dpendances entre o-6ets crs

%ransaction trans ) trans.=egin%ransaction()(


Sport sport ) ne Sport(;;pMche;;)(
Jiscipline disc ) ne Jiscipline(;;mouche;;, sport)(
session.persist(disc)(
trans.commit()(

Ce code gnrera une e)ception car le sport associ ? la discipline n'a


pas t rendu persistant

Il faut donc le faire e)plicite!ent

Lu prciser dans les fichiers de !apping $ue la persistance se fait


auto!ati$ue!ent en cascade

<ans une dfinition d'association (U!an%-to-oneW. ...+ a6outer le


cha!p * cascade ) ;;persist;;
12>
5ycle de vie d'un ob:et persistant

<tacher = rattacher un o-6et

Tout o-6et persistant (charg depuis la 2<<. instanti puis rendu


persistant+ est attach ? la session

1'tat de l'o-6et est li avec le contenu de la 2<< tant $ue la session e)iste

<ans certains cas. on peut vouloir dtacher un o-6et

Mthodes evict() ou close()

Il n'est plus associ ? la session !ais e)iste encore en 2<<

es !odifications ne sont plus rpercutes sur la 2<<

"eut ensuite rattacher l'o-6et ? la session et rpercuter ses !odifs

Mthodes merge(). locK(). update(). save$r*pdate()

uppri!er un o-6et persistant

Mthode delete() * session.delete(sport)(

1e contenu de l'o-6et est suppri! de la 2<< (!ais l'o-6et Pava e)iste


tou6ours lui. il n'a 6uste plus aucun lien avec la 2<<+

3ttention au) dpendances entre o-6ets lors de la suppression

<ans fichier de !apping. utiliser au -esoin des cha!ps *


cascade);;delete;; et cascade);;all,delete,orphan;;
12@
5ycle de vie d'un ob:et persistant

Modifier un o-6et persistant

Modifier son contenu via l'appel des setters et autres accs au)
collections

sportif.getHdresse().setRue(;;rue !mile GuichennI;;)(


sportif.getHdresse().setCode/ostal(;;\V???;;)(
sportif.getHdresse().set:ille(;;/au;;)(
sportif.addJiscipline(disc)(

1a dtection de la !odification et la !ise ? 6our sur la 2<< sont


faites auto!ati$ue!ent par Gi-ernate

En prati$ue. la !thode flush(o=1) est appele pour faire la !ise ?


6our ph%si$ue

Iecharger le contenu d'un o-6et persistant

Mthode refresh(o=1)

Il n'% a pas de raison d'appeler e)plicite!ent cette !thode vu


$ue les !odifications sont trans!ises. sauf si on sait $u'un trigger
a t e)cut
12B
Autres (onctionnalits de !apping

Collections

Ln a dfini des !appings correspondant ? des 6ointures retournant


une collection 6ava de t%pe Set via une -alise 5set7

Ln peut dfinir d'autres t%pes de collections. correspondant au)


t%pes Pava $uivalents

-ag. list. !ap. arra%. collections inde)es ...

2alise 51oin7

"er!et de !apper des donnes venant de plusieurs ta-les dans


une seule classe cot Pava

Gritage

Mappings pour une hirarchie d'hritage

Trois stratgies possi-les

'ne ta-le uni$ue pour toutes les classes

'ne ta-le par classe logi$ue (!apping pour la classe !re A !appings
pour les classes filles+

'ne ta-le par classe 8concrte9 (pas de !apping pour la classe !re+
12C
5oncurrence 9 per(or!ances

"erfor!ance

1es perfor!ances sont principale!ent lies au charge!ent en


!!oire des donnes

Co!!e le graphe d'o-6ets lis est potentielle!ent grand. on essa%e


de charger les o-6ets uni$ue!ent ? la de!ande

Cha!p laGy);;true;; dans les !appings des collections

"ar dfaut. $uand Gi-ernate charge un o-6et. il ne charge pas ses


collections associes tant $u'on % accde pas

E)e!ple avec code prcdent. et sa trace. accdant au) sports et


leurs disciplines

'n pre!ier E1ECT rcupre tous les sports

"our cha$ue sport. un autre E1ECT est e)cut pour rcuprer la liste des
disciplines $uand on % accde (au !o!ent du sport.getJisciplines()+

&estion de la concurrence

M5!es fonctionnalits $ue dans les &2< pour grer de !anire


prcise les accs concurrents * verrous sur donnes. ...

1a gestion dtaille des transactions est i!portante


1#D
'apping par annotation

Eos !appings se -asent sur des couples de fichiers

1a classe Pava (le "LPL+ et son fichier 0M1 de !apping

"eut aussi directe!ent a6outer des annotations dans la classe Pava


pour prciser les !appings

9!ntity
9%a=le(name ) &sport&)
9@amedXueries(A9@amedXuery(name ) &Sport.findHll&, query ) &S!>!C% s +R$F Sport s&),
9@amedXuery(name ) &Sport.find_yCodeSport&, query ) &S!>!C% s +R$F Sport s 0H!R!
s.codeSport ) 2codeSport&), 9@amedXuery(name ) &Sport.find_y#ntitule&, query ) &S!>!C% s
+R$F Sport s 0H!R! s.intitule ) 2intitule&)C)
pu=lic class Sport implements SerialiGa=le A
private static final long serial:ersion*#J ) 3>(
9#d
9_asic(optional ) false)
9Column(name ) &code^sport&)
private #nteger codeSport(
9Column(name ) &intitule&)
private String intitule(
9$ne%oFany(mapped_y ) &codeSport&)
private Collection5Jiscipline7 disciplines(
(...)
1#1
5onclusion sur /ibernate

/ra!eForM de persistance trs puissant (on n'en a


vu $u'une introduction dtaille+

Indpendance des supports ph%si$ues

&estion des caractristi$ues o-6et (hritage ...+

"oliti$ues de charge!ents des o-6ets (? la de!ande ...+

1angage de re$u5te GO1

'n O1-liMe orient o-6et

"er!et vrai!ent de se consacrer sur la logi$ue !tier

1a gestion des donnes est principale!ent du Pava natif. pas ?


soucier de co!!ent sont gres et accdes les donnes

3u niveau du progra!!e en tout cas. car il faut $uand !5!e


concevoir la -ase de donne et les !appings

Cot Pava. on !anipule donc directe!ent les entits !tiers


telles $u'on les a conSues

M5!e si on doit avoir en t5te $u'elles ont une persistance en 2<<


1#2
?ocu!entation /ibernate

ite officiel d'Gi-ernate

http*==FFF.hi-ernate.org

3vec -eaucoup de docu!entation

Traductions franSaises du !anuel de rfrence du


site d'Gi-ernate

http*==FFF.dil.univ-!rs.fr=e!assat=docs=hi-ernate-#.1=reference=fr=ht!l=inde).ht!l

http*==docs.6-oss.org=hi-ernate=core=#.#=reference=fr=ht!l=inde).ht!l

1ivre

8Gi-ernate #.D : &estion opti!ale de la persistance dans


les applications Pava=P2EE9. 3nthon% "atricio. E%rolles
1##
&#e!ple (inal

Co!-inaison de Gi-ernate. servlets. pages P"


avec 'E1 et PT1 pour afficher les sportifs avec
leurs disciplines et sports prati$us

"age GTM1 via un lien envoie une re$u5te ? la servlet


SportServlet

ervlet SportServlet.1ava (d;*R> `'SportsE)

Icupre via une re$u5te GO1 l'ense!-le des sports

36oute cet ense!-le ? la re$u5te GTT" reSue par la servlet

"uis fait suivre (forFard+ la re$u5te GTT" ? la page


afficherSports.1sp

"age afficherSports.1sp

Icupre l'ense!-le des sports dans la re$u5te GTT"

Hia 'E1 et PT1. !et en page leur affichage

1a servlet ne gnre aucun code GTM1. c'est le


r`le de la page P" ? $ui on a forFard la re$u5te
1#4
&#e!ple (inal

1ien dans la page GTM1

5a href)&SportsUoperation)listeSportif& target)&operation&7
Hfficher la liste des sportifs5'a7

Code de SportServlet.1ava

pu=lic >ist5Sportif7 get>isteSportifs() thros !"ception A


Session session ) this.openHi=ernateSession()(
Xuery query ) session.createXuery(&from data.Sportif&)(
return query.list()(
C
protected void processRequest( ... request, ... response) A
String operation ) request.get/arameter(&operation&)(
if (operation.equals(&listeSportif&)) A
'' rIcupLre la liste des sports et l;associe N la requMte H%%/
request.setHttri=ute(&sportifs&, get>isteSportifs())(
'' forarde la requMte N la page <S/
getServletConfig().getServletConte"t().getRequestJispatcher(
&'afficheSportifs.1sp&).forard(request,response)(
C (...)
1#;
&#e!ple (inal

"age P" afficheSportifs.1sp

UV@tagli- uriX^http*==6ava.sun.co!=6sp=6stl=core^ prefi)X^c^ VW


Uh2W1iste des sportifs et de ce $u'ils fontU=h2W
Uc*forEach ite!sX^fbre$uestcope.sportifsc^ varX^sp^W
Uh#Wfbsp.no!cU=h#W
UpWU-W3dresse * U=-Wfbsp.adresse.ruec - fbsp.adresse.code"ostalc fbsp.adresse.villecU=pW
Uc*chooseW
Uc*Fhen testX^fbe!pt% sp.disciplinesc^W
UpWUiWEe prati$ue aucune discpline sportiveU=iWU=pW
U=c*FhenW

Uc*otherFiseW
UpWU-W1iste des disciplines prati$ues * U=-WU=pW
UulW
Uc*forEach ite!sX^fbsp.disciplinesc^ varX^disc^W
UliWfbdisc.intitulecU=liW
U=c*forEachW
U=ulW
UpWU-W1iste des sports * U=-W U=pW
UulW
Uc*forEach ite!sX^fbsp.sportsc^ varX^sport^W
UliWfbsport.intitulecU=liW
U=c*forEachW
U=ulW
U=c*otherFiseW
U=c*chooseW
U=c*forEachW
1#>
&#e!ple (inal