Alain Tchana, [email protected]

Transcription

Alain Tchana, [email protected]
N7
2015
Programmation web
Alain Tchana, Maître de Conférence
Institut National Polytechnique de Toulouse
IRIT / Équipe SEPIA
[email protected]
Inspiré des slides de Daniel Hagimont
Alain Tchana, [email protected]
N7
2015
Plan
Apperçu HTML, CSS, CGI
Rappel MCV
JEE : servlet, JSP, EJB
Alain Tchana, [email protected]
N7
2015
Web et HTML
Web et HTTP
Alain Tchana, [email protected]
N7
2015
Le web
●
Système d’information hypermédia ( texte, son, images, etc.)
●
Né en 1989, par Tim Berners-Lee au CERN
●
Concept de base universelle d’information
●
Accès aux bases d’information
●
Accessibles à tous et partout
●
Liens entre les informations
Alain Tchana, [email protected]
N7
2015
Le protocole HTTP
HTTP : HyperText Transfer Protocol
– Modèle client-serveur pour le transfert des documents hypertextes
– Protocole utilisé par les serveurs Web depuis 1990
– Protocole minimaliste basé sur TCP/IP et utilisant des messages sous
forme de chaînes de caractères
– Utilise un ensemble de mots clés (méthode) pour discuter avec le serveur
distant
URL : Uniform ressource Locator
– Syntax
• method://machine[:port]/fichier[#ancre|?param]
• Où method = file/ftp/http/telnet/news/mailto
Client
Web
(Firefox)
get/post
catalogue.html
Serveur
Web
(Apache)
Alain Tchana, [email protected]
N7
2015
Les méthodes HTTP
GET
Pour récupérer une
ressource
HEAD
Pour obtenir des
informations sur une
ressource
POST
Pour récupérer une
ressource
OPTIONS,
CONNECT, TRACE
Pour interroger le
serveur sur son état
PUT
Pour ajouter ou
remplacer une
ressource
DELETE
Pour supprimer une
ressource
Alain Tchana, [email protected]
N7
2015
Exemple GET - client
prompt>> telnet localhost 80
Trying ::1...
Connected to localhost.
Escape character is '^]'.
GET /cgi-bin/test-cours?nom=toto&prenom=titi HTTP/1.0
Host: localhost
HTTP/1.1 200 OK
Date: Thu, 30 Sep 2010 11:10:01 GMT
Server: Apache/2.2.16 (Debian)
Vary: Accept-Encoding
Connection: close
Content-Type: text/html
you submitted the following key-value pairs <br>
- nom=toto <br>
- prenom=titi <br>
Connection closed by foreign host.
Alain Tchana, [email protected]
N7
2015
Exemple POST - client
prompt>> telnet localhost 80
Connected to localhost.
Escape character is '^]'.
POST /cgi-bin/test-cours? HTTP/1.0
Host: localhost
Content-length: 20
nom=toto&prenom=titi
HTTP/1.1 200 OK
Date: Thu, 30 Sep 2010 11:17:41 GMT
Server: Apache/2.2.16 (Debian)
Vary: Accept-Encoding
Connection: close
Content-Type: text/html
you submitted the following key-value pairs <br>
- nom=toto <br>
- prenom=titi <br>
Connection closed by foreign host.
Alain Tchana, [email protected]
N7
2015
Réponse HTTP
Status
HTTP_version code phrase
En-tête
Location :
URL exacte de la ressource demandée
Descriptif
Server :
Informations sur le serveur
Content-Encoding :
Type de codage du corps de la réponse
Content-Length :
Taille du corps de la réponse
Content-Type :
Type MIME du corps de la réponse
Date :
Date de la génération de la réponse
Expires :
Date d'expiration du document
Last-Modified :
...
Dernière modification du document
Fin-Entête
CRLF
Ligne blanche
Document
...
Contenu du document demandé
HTTP/1.1 200 OK
Date: Fri, 09 Jan 1998 09:49:11 GMT
Server: Apache/1.3b2
Last-Modified: Tue, 19 Aug 1997 11:57:17 GMT
Content-Length: 118
Content-Type: text/html
<html> ...
Alain Tchana, [email protected]
N7
2015
Code de retour
Classe 1 : information (pas utilisé)
Classe 2 : succès
– 200 (OK), 201 (created), 204 (no content), . . .
Classe 3 : redirection
– 301 (moved permanently), 304 (not modified), . . .
Classe 4 : erreur client
– 400 (bad request), 401 (Unauthorized), 404 (not found), . . .
Classe 5 : erreur serveur
– 500 (internal serveur error), 501 (not implemented), 503 (service
unavailable), . . .
Alain Tchana, [email protected]
N7
2015
Web et HTML
HTML
Alain Tchana, [email protected]
N7
2015
●
Langage HTML
HTML : Hyper Text Markup Language
– Langage de description d’information structurée portable
– Organisme de standardisation : WWW consortium
– HTML 4.01 : http://www.w3.org/TR/html401/
●
<balise attributs> contenu </balise>
– balise (tag), ex : <html>
– attributs : représente des options, ex : <table width=”60%”>
– contenu : texte, images ou d’autres balises
– </balise> : fin de la balise
Alain Tchana, [email protected]
N7
2015
Syntaxe HTML (exemple)
<HR>
<IMG SRC=”monimage.gif” WIDTH=100 HEIGHT=120>
<H1>Ceci est un titre</H1>
<h2>Ceci est un sous­titre</h2>
<A HREF=”http://host/dir/file.html”>lien</A>
<!−− Commentaire −−>
XHTML est une transposition en syntaxe XML de HTML
– http://www.w3.org/TR/2002/REC-xhtml1-20020801/
– syntaxe plus rigoureuse, notamment :
• toute balise ouvrante doit être fermée (<img alt=”...”/>)
• noms des balises et des attributs en minuscules
• éléments HTML correctement imbriqués
– Recommandé !
Alain Tchana, [email protected]
N7
2015
●
●
●
Principales balises
<a> lien hypertexte attribut : href pour une URL ou name pour une
ancre
<em> met en emphase une portion de texte
<img> inclut une image dans le document, attributs : alt (texte
alternatif) et src (chemin vers l’image)
●
<div> conteneur générique de type bloc
●
<p> paragraphe de texte
●
<table> écriture d’un tableau voir aussi <tr>, <td>, <th>
●
<h1>, <h2>, . . . <h6> niveaux de titres
●
●
<ol>, <ul> listes ordonnées ou à puces simples, chaque élément (item)
sera écrit <li>
<form> formulaire interactif
Alain Tchana, [email protected]
N7
2015
Structure d'un document
Bluefish
Alain Tchana, [email protected]
N7
2015
Mise en page
CSS
Alain Tchana, [email protected]
N7
2015
●
Mise en page
CSS : Cascading Style Sheet
– Feuilles de style
– Correctement pris en charge depuis 2000
– http://www.w3.org/TR/CSS2
●
Documentations
– Valider son code HTML
• http://validator.w3.org/
– Valider son code CSS
• http://jigsaw.w3.org/css-validator/
– Tutoriels HTML – CSS
• http://www.alsacreations.com/tutoriels/
Alain Tchana, [email protected]
N7
2015
Syntaxe CSS
/* les titres de types h1 seront en bleu et centrés */
h1 {
color: blue ;
text-align: center;
}
/* on peut appliquer des propriétés à des classes d'objet :
ici seuls les paragraphes de classe 'note' auront cette propriété */
p.note {
font-family: Arial, sans-serif;
font-style: italic;
<p class="note">Hello</p>
}
/* les balises html peuvent aussi être dotées d'un attribut
id qui doit alors être unique dans la page */
p#menu {
font-weight: bold;
}
<p id="menu">Call</p>
/* ou encore */
#menu {
font-weight: bold;
}
Alain Tchana, [email protected]
N7
2015
Syntaxe CSS
Dans l'entête du document
<head >
...
<style type="text/css">
h1 {color: blue;}
</style>
...
</head>
Dans les balises
<h1 style=" color: blue;">
Titre de la page
</h1>
Référence à une feuille externe
<head>
...
<link rel="stylesheet"
type="text/css"
href="styles.css "/>
...
</head>
Alain Tchana, [email protected]
N7
2015
Syntaxe CSS
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http:// www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<style type="text/css">
h1 {color: blue;}
p.note {font-style: italic;}
p#menu {font-weight: bold;}
</style>
</head>
<body>
<h1>Un titre</h1>
<div>Un bloc.
<p id="menu">Un paragraphe.</p>
<p class="note">Un deuxième paragraphe (accent utf8).</p>
<p>Un troisi&egrave;me paragraphe (accent html).</p>
</div >
</body>
</html >
Alain Tchana, [email protected]
N7
2015
Premier
Bilan
Alain Tchana, [email protected]
N7
2015
Premier bilan
Initialement
– Web statique
• Requête limitée à la demande de ressources
statiques
– Principalement des serveurs
• de page HTML
• accédées par HTTP
Evolution vers des sites dynamiques
Alain Tchana, [email protected]
N7
2015
●
Premier bilan
Besoin d'exécuter une application sur le
serveur HTTP
●
Besoin de fournir des données
●
Solutions initiales
– Formulaires HTML pour la saisie
– Scripts CGI pour l’exécution
Alain Tchana, [email protected]
N7
2015
Formulaires HTML
<form action=”url” method=” methode ”>
...
</ form>
url : identifie le programme utilisé pour traiter le formulaire
method : méthode à utiliser pour transmettre l’information au
serveur
– GET : données ajoutées à l’URL
– POST : données envoyées dans le corps du message
Alain Tchana, [email protected]
N7
2015
Éléments de formulaire
Éléments INPUT
<input type=”type” name=”nom” size=”size” maxlength=”max” value=”val” />
Différents types possibles
TEXT
Champ de saisie de texte
PASSWORD
Champ de saisie de texte caché
SUBMIT
Bouton de soumission du formulaire
RADIO
Bouton à cocher de type radio (1 unique par name)
CHECKBOX
Bouton à cocher (plusieurs par name)
HIDDEN
Champ invisible
On envoie dans la requête un ensemble de pairs nom=val
Alain Tchana, [email protected]
N7
2015
Éléments de formulaire
Éléments SELECT
<select name="select">
<option value="value1">Valeur 1</option>
<option value="value2" selected>Valeur 2</option>
<option value="value3">Valeur 3</option>
</select>
Élément TEXTAREA
<textarea name="textarea" rows="10" cols="50">
Saisir un texte ici.
</textarea>
Alain Tchana, [email protected]
N7
2015
Exemple
<html>
<head><title>MaBanque</title></head>
<body>
<form method="post" action="/cgi-bin/monCGI.cgi">
<p>numero de compte<input type="text" name= "num">
</p>
<p>montant<input type="text" name= "val"></p>
<p>
<input type="submit" name="operation" value="solde">
<input type="submit" name="operation" value="debit">
<input type="submit" name="operation" value="credit">
</p>
</form>
</body>
</html>
Alain Tchana, [email protected]
N7
2015
Exemple - résultat
Alain Tchana, [email protected]
N7
2015
Exemple GET - client
prompt>> telnet localhost 80
Trying ::1...
Connected to localhost.
Escape character is '^]'.
GET /cgi-bin/monCGI.cgi?operation=credit HTTP/1.0
Host: localhost
HTTP/1.1 200 OK
Date: Thu, 30 Sep 2010 11:10:01 GMT
Server: Apache/2.2.16 (Debian)
Vary: Accept-Encoding
Connection: close
Content-Type: text/html
you submitted the following key-value pairs <br>
- operation=credit <br>
Connection closed by foreign host.
Alain Tchana, [email protected]
N7
2015
Exemple POST - client
prompt>> telnet localhost 80
Connected to localhost.
Escape character is '^]'.
POST /cgi-bin/monCGI.cgi? HTTP/1.0
Host: localhost
Content-length: 20
operation=credit
HTTP/1.1 200 OK
Date: Thu, 30 Sep 2010 11:17:41 GMT
Server: Apache/2.2.16 (Debian)
Vary: Accept-Encoding
Connection: close
Content-Type: text/html
you submitted the following key-value pairs <br>
- operation=credit <br>
Connection closed by foreign host.
Alain Tchana, [email protected]
N7
2015
Scripts CGI
●
Programme générant un contenu en réponse à une requête
●
Programmé dans n'importe quel langage
– Perl, C, C++, Java, shell, ...
●
Placé dans un répertoire particulier du serveur Web (cgi-bin)
●
Envoie le contenu sur STDOUT
●
Doit envoyer entête (type mime) + contenu
– Pour HTML: content-type : text/html
Client
Web
exec
→ $QUERY_STRING
→ stdin
get/post
Serveur
Web
catalogue.html
CGI
stdout
Alain Tchana, [email protected]
N7
2015
●
Requête à un CGI
Envoi de paramètres
– champ1=valeur1&champ2=valeur2...
●
Les requêtes GET et POST
– GET : paramètres inclus dans l'URL
• http://nom_du_serveur/cgi-bin/script.cgi?champ1=valeur1&...
• Limitation à 255 catactères, visible, ...
– POST : paramètres inclus dans le corps de la requête HTTP
– Utilisation de formulaires (pour interactions)
●
Réception des paramètres
– GET : variable d'environnement QUERY_STRING
– POST : STDIN, et variable d'environnement CONTENT_LENGTH
Alain Tchana, [email protected]
N7
2015
Exemple – serveur CGI
#!/bin/bash
function extract_parameter()
{
echo you submitted the following key-value pairs "<br>"
str=$1
while [ "$str" != "" ];
do
echo - `echo $str | cut -f1 -d'&'` "<br>"
str=`echo $str | cut -s -f2- -d'&'`
done
}
GET
POST
echo "Content-Type: text/html"
echo ""
extract_parameter $QUERY_STRING
echo ""
echo "Content-Type: text/html"
echo ""
read QUERY_STRING
extract_parameter $QUERY_STRING
echo ""
Alain Tchana, [email protected]
N7
2015
Web
Dynamique
Alain Tchana, [email protected]
N7
2015
App. web dynamiques
Caractéristiques d'une application web dynamique
➔
Les informations produites par le même lien varient d'un utilisateur à l'autre.
1) Les informations présentées sur la même page varient suivant les actions de l'utilisateur.

Le site reconnaît chaque utilisateur
Construit un contenu en fonction
du user

Alain Tchana, [email protected]
35
N7
2015
App. web dynamiques
Caractéristiques d'une application web dynamique
➔
Les informations produites par le même lien varient avec le temps (peu être très court).
1) Les informations présentées sur la même page varient avec le temps (court).
2) Les informations présentées sur la même page varient suivant les actions de l'utilisateur.


Le site se met à jour dynamiquement

sans l'admin system
L'utilisateur est directement à l'origine
Alain Tchana, [email protected]
36
N7
2015
App. web dynamiques
Caractéristiques d'une application web dynamique
➔
Les informations présentées sur la même page varient suivant les actions de l'utilisateur.
1) Les informations présentées sur la même page varient avec le temps (court).
2) Les informations présentées sur la même page varient suivant les actions de l'utilisateur.


La vue prend des initiatives toute seule

Modifie des bouts de la page

Peut contacter un serveur distant
L'utilisateur est indirectement à l'origine
Alain Tchana, [email protected]
37
App. web dynamiques
N7
2015
Comment était implantée une app. web dyn, à l'époque ?
➔
➔
Un script côté serveur (CGI par exemple)
➔
Reçoit la requête
➔
Identifie l'utilisateur et génère une page HTML
Toute action du client sur la page
➔
Nécessite le contact du serveur
➔
La régénération de la page (toute entière)
➔
Même si la modification était minime
Alain Tchana, [email protected]
38
App. web dynamiques
N7
2015
Comment était implantée une app. web dyn, à l'époque ?
➔
➔
Conséquences (pour le développeur)
➔
Le script est volumineux
➔
Illisible
➔
Difficile à maintenir et à faire évoluer
Pb. 1
Conséquences (pour le client web)
➔
Les temps de réponse sont longs (trafic sur le réseaux)
➔
Le serveur sature très vite (génération de la page entière, IO)
Alain Tchana, [email protected]
Pb. 2
39
N7
2015
Modèle
MVC
Alain Tchana, [email protected]
Modèle MVC
N7
2015
MVC : un guide de programmation au secours du développeur
➔
Organise le code de l'application en 3 catégories
➔
➔
Les structures de données des informations que manipulent l'app.
➔
Contient le code métier
➔
C'est le Modèle
Le code qui construit la façon dont le modèle est présenté
➔
➔
C'est la Vue
Les contrôles
➔
Contrôle des requêtes. MAJ modèle
➔
C'est le Contrôle
Alain Tchana, [email protected]
42
Modèle MVC
N7
2015
MVC : un guide de programmation au secours du développeur
➔
Organise le code de l'application en 3 catégories
➔
➔
Les structures de données des informations que manipulent l'app.
➔
Contient le code métier
➔
C'est le Modèle
Le code qui construit la façon dont le modèle est présenté
➔
➔
C'est la Vue
Les contrôles
➔
Contrôle des requêtes. MAJ modèle
➔
C'est le Contrôle
Alain Tchana, [email protected]
43
Modèle MVC
N7
2015
MVC : un guide de programmation au secours du développeur
➔
Organise le code de l'application en 3 catégories
➔
➔
Les structures de données des informations que manipulent l'app.
➔
Contient le code métier
➔
C'est le Modèle
Le code qui construit la façon dont le modèle est présenté
➔
➔
C'est la Vue
Les contrôles
➔
Contrôle des requêtes. MAJ modèle
➔
C'est le Contrôle
Alain Tchana, [email protected]
44
N7
2015
MVC
JEE
Alain Tchana, [email protected]
MVC avec JEE
N7
2015
MVC : un guide de programmation au secours du développeur
➔
Plusieurs technos permettent de faire du MVC
➔
PHP
➔
JEE
Le modèle
Le controle
Navigateur
(1)
HTML+
JS
(2)
(3)
Selvlet
(6)
(5)
Facade
(4)
Data
(7)
➔
Etc.
Codes :
HTML+
JSP+
JS
La vue
Alain Tchana, [email protected]
46
JEE
N7
2015
(1)
(8)
HTML+
Ajax+
JS 1er ctr+
JS modif. DOM
Navigateur
(9)
(7)
(2)
(3)
Selvlet
(6)
(5)
Facade
Codes :
HTML+
JSP+
Ajax+
JS 1er ctr+
JS modif. DOM
Alain Tchana, [email protected]
(4)
Data
JEE
N7
2015
(1)
(8)
HTML+
Ajax+
JS 1er ctr+
JS modif. DOM
(2)
Selvlet
(9)
(7)
Navigateur
(5)
(6)
Facade
Codes :
HTML+
JSP+
Ajax+
JS 1er ctr+
JS modif. DOM
Tomcat Servlet
server
h
h
t
t
t
t
...
p
p
d
d
servlet
servlet
servlet
servlet
servlet
JVM
AJP12
HTTP
Client
(3)
Apache
Web server
JDBC
Tomcat
Servlet server
MySQL
Database server
Alain Tchana, [email protected]
(4)
Data
N7
2015
JEE
Servlet
Alain Tchana, [email protected]
N7
2015
Servlets Java
S’exécute dans un “Servlet Container” sur une JVM
– Tomcat ou Jetty
– Soit utilisé comme un serveur intégré (web + servlets)
– Soit utilisé comme un plug-in de Apache (séparé)
Tomcat Servlet
server
h
h
t
t
t
t
p ... p
d
d
JVM
AJP12
HTTP
Client
servlet
servlet
servlet
servlet
servlet
Apache
Web server
JDBC
Tomcat
Servlet server
MySQL
Database server
Alain Tchana, [email protected]
N7
2015
Servlet HTTP - API
public void init()
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
Paramètres
– HttpServletRequest : permet de manipuler la requête reçue
– HttpServletResponse : permet de générer la réponse
Remarques
– Attention, ces méthodes peuvent être exécutées en concurrence
– Ces méthodes peuvent appeler des BD : JDBC
Alain Tchana, [email protected]
N7
2015
Exemple
1/3
<html> <head><title>Directory</title></head><body>
<h1>Enter a person</h1>
<form action= "Directory" method="post">
firstname<input type="text" name="firstname"><br/>
lastname<input type="text" name="lastname"><br/>
email<input type="text" name="email"><br/>
<input type="submit" name="op" value="add">
<input type="submit" name="op" value="list">
</form>
</body></html>
Alain Tchana, [email protected]
N7
2015
Exemple
2/3
public class Directory extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
try {
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:/comp/env/jdbc/DirectoryDB");
Connection con = ds.getConnection();
response.setContentType("text/html");
out.print("<html><body><h1>Directory</h1>");
String op = request.getParameter("op");
if (op.equals("list")) {
Statement stmt = con.createStatement();
ResultSet res = stmt.executeQuery("SELECT * FROM directory");
while(res.next()) {
out.print("<p>"+res.getString("firstname")+" "+res.getString("lastname")
+" "+res.getString("email"));
}
Alain Tchana, [email protected]
N7
2015
}
}
Exemple
3/3
} else {
PreparedStatement ps = con.prepareStatement("INSERT INTO directory
VALUES(?,?,?)");
ps.setString(1, request.getParameter("firstname"));
ps.setString(2, request.getParameter("lastname"));
ps.setString(3, request.getParameter("email"));
ps.executeUpdate();
out.print("Person was added");
}
out.print("</body></html>");
} catch (Exception ex) {
ex.printStackTrace(out);
}
Alain Tchana, [email protected]
N7
2015
Session
Notion de session
– Une requête dépend du résultat des requêtes
précédentes
– Ex : caddie
Création de session
HttpSession HttpServletRequest.getSession ()
HttpSession HttpServletRequest.getSession(boolean create)
Utilisation de la session
Object getAttribute(String name)
Enumeration getAttributeNames()
long getCreationTime()
int getMaxInactiveInterval()
void invalidate()
void removeAttribute(String name)
void setAttribute(String name, Object value)
void setMaxInactiveInterval(int interval)
Alain Tchana, [email protected]
N7
2015
Cookies
Création / initialisation
Cookie(java.lang.String name, java.lang.String value)
void setValue(java.lang.String newValue)
void setMaxAge(int expiry)
void setDomain(java.lang.String pattern)
java.lang.String getValue()
java.lang.String getDomain()
int getMaxAge()
A l'exécution
Cookie[] HttpServletRequest.getCookies()
HttpServletResponse.addCookie(javax.servlet.http.Cookie)
Alain Tchana, [email protected]
N7
2015
Configuration d'une servlet
web.xml
(déclaration des servlets – en 2.5)
<servlet>
<display-name>Directory</display-name>
<servlet-name>Directory</servlet-name>
<servlet-class>directory.Directory</servletclass>
</servlet>
<servlet-mapping>
<servlet-name>Directory</servlet-name>
<url-pattern>/Directory</url-pattern>
</servlet-mapping>
ou
// Annotation servlet
@WebServlet("/Directory")
Alain Tchana, [email protected]
N7
2015
Packaging et déploiement d'une
servlet
Un répertoire par application
– Pages web (html)
– Répertoire "WEB-INF"
• Répertoire "classes" : les classes des servlets
• Répertoire "lib" : les librairies (jar) par exemple driver jdbc
• "web.xml" : descripteur des servlets
– Répertoire "META-INF"
• "context.xml" : configuration du container par example datasource
Création d'un fichier WAR (jar)
Copie dans $CATALINA_BASE/webapps
Le fichier WAR est expansé
Alain Tchana, [email protected]
N7
2015
●
Servlet - Bilan
Facile à programmer
– Un peu pareil que la page PHP
– Programmation en Java
– Manque l'insertion de code dans les pages HTML
●
Mélange entre aspects présentation (génération
HTML), code métier et code d’accès aux
données persistantes (à priori pas très MVC …)
– But séparer ces aspects
Alain Tchana, [email protected]
N7
2015
JEE
JSP
Alain Tchana, [email protected]
N7
2015
Modèle MVC
Model View Controler
Séparation entre
– Le contrôleur : servlet qui aiguille les requêtes
– La vue : pages JSP pour l’affichage à l’écran
– Le Modèle : les classes (beans) qui traitent les données
Requête
HTTP
Réponse
HTTP
Controler
(quel traitement ?
quelle page ? )
Model
(traitement)
View
(page web)
Alain Tchana, [email protected]
N7
2015
JSP (Java Server Page)
Langage de script (proche de Java)
– Générer des pages dynamiques
– Intégré dans des pages web
– Compilé dynamiquement en servlet
Interaction avec des classes Java
parseur
Page.jsp JSP
compilateur
Servlet.java
Servlet.class
Alain Tchana, [email protected]
N7
2015
Un petit exemple
<%@ page language="Java" %>
<html>
<head>
<title>First.jsp</title>
</head>
<body>
<h1>Nombres de 1 à 10</h1>
<% for(int i=1; i<=10; i++) {
out.println(i + "<br>");
}
%>
</body>
</html>
Alain Tchana, [email protected]
N7
2015
Les directives
<%@ directive attribut1="valeur" attribut2="valeur"... %>
3 directives possibles :
– page : informations relatives à la page
• <%@ page import=”...”%>
• <%@ page errorPage=”...”%>
• <%@ page isThreadSafe=”...”%>
– include : fichiers à inclure littéralement (file)
• <%@ include file=”...”%>
– taglib : permet d'utiliser des librairies de tags personnalisés
• <%@ taglib uri=”...” prefix=”...”%>
Alain Tchana, [email protected]
N7
2015
Les déclarations
<%! declaration %> variables et méthodes
globales à la page
Exemple
<%!
String Chaine = ”bonjour”;
int Numero = 10 ;
public void jspInit() {
// instructions
}
%>
Alain Tchana, [email protected]
N7
2015
Les scripts Java
Du code Java : <% code Java %>
Des évaluations d'expression : <%= expression %>
Des variables prédéfinies
<%@ page language="Java" %>
<html><head><title>First.jsp</title>
</head><body>
<h1>Nombres de 1 à 10</h1>
<% for(int i=1; i<=10; i++) { %>
<%= i %> <br/>
<% } %>
</body>
</html>
Variables prédéfinies
– HttpServletRequest request
– HttpServletResponse response
– HttpSession session
– ServletContext application
– PrintWriter out
– ServletConfig config
– ...
Alain Tchana, [email protected]
N7
2015
Les actions
Des tags standards des JSP de la forme
<jsp:tag attribut1=”valeur” attribut2=”valeur”... />
<jsp:forward page=”page2.jsp” />
– Transfère le contôle à une autre page JSP (annule
l’appelante)
<jsp:include page=”page2.jsp” />
– Transfère le contrôle à une autre page JSP (inclusion)
Peuvent prendre des paramètres avec
– <jsp:param name=”...” value=”...” />
(une JSP ou une Servlet)
Alain Tchana, [email protected]
N7
2015
Les actions
<jsp:usebean id="nomAttribut" class="package.classe" scope="portéeAttribut>
<%-- code executé si l'attribut est créé --%>
</jsp:usebean>
Importe un attribut si il existe, le crée sinon
<jsp:usebean id="personne" class="testjsp.Personne" scope="session/>
équivaut à
<% testjsp.Personne personne = (testjsp.Personne) session.getAttribute("personne");
if (personne == null) {
personne = new testjsp.Personne();
session.setAttribute("personne", personne);
} %>
Alain Tchana, [email protected]
N7
2015
Lien HTML/Servlet/JSP
Une page HTML peut référencer une servlet ou
une page JSP
Une page JSP peut référencer une servlet
– jsp :include ou jsp :forward
Une servlet peut référencer une page JSP
– RequestDispatcher disp =
request.getRequestDispatcher(”page.jsp”) ;
– disp.forward(request, response) ;
Alain Tchana, [email protected]
N7
2015
Exemple : annuaire
Alain Tchana, [email protected]
N7
2015
Exemple : architecture
Une page JSP pour chaque écran
– user.jsp, person.jsp, listusers.jsp
Une servlet qui aiguille les requêtes vers les
pages
Deux objets Java (beans) pour gérer les
données
– Person.java, ListOfPerson.java
Alain Tchana, [email protected]
N7
2015
Exemple : user.jsp
<%@ page language="java" %>
<html>
<body>
<form action="Action" method="post">
User : <input type="text" name="user"/><br/><br/>
<input type="submit" value="enter"/>
<input type="hidden" name="form" value="user"/>
</form>
</body>
</html>
Alain Tchana, [email protected]
N7
2015
Exemple : person.jsp
<%@ page language="java" %>
<html>
<body>
<jsp:useBean id="user" class="directory.Person" scope="session" />
<b> Enter a person</b> <br/><br/>
User: <%= user.user %><br/>
<form action="Action" method="post">
Firstname : <input type="text" name="firstname"/><br/>
LastName : <input type="text" name="lastname"/><br/>
Email : <input type="text" name="email"/><br/><br/>
<input type="submit" value="add"/>
<input type="hidden" name="form" value="person"/>
</form>
</body>
</html>
Alain Tchana, [email protected]
N7
2015
Exemple : listusers.jsp
<%@ page language="java" import="directory.*, java.util.*"%>
<html><body>
<jsp:useBean id="listOfUsers" class="directory.ListOfPerson" scope="application"/>
<b> List of registered persons </b> <br/><br/>
<table border="2">
<tr><th>User</th><th>Firstname</th><th>Lastname</th><th>Email</th></tr>
<%
Enumeration enu = listOfUsers.list.elements();
while (enu.hasMoreElements()) {
Person p = (Person)enu.nextElement();
%>
<tr>
<td><%= p.user %></td>
<td><%= p.firstname %></td>
<td><%= p.lastname %></td>
<td><%= p.email %></td>
</tr>
<% } %>
</table>
</body></html>
Alain Tchana, [email protected]
N7
2015
Exemple : action.java (servlet)
public class Action extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String form = request.getParameter("form");
HttpSession session = request.getSession();
ServletContext context = getServletContext();
if (form == null) {
RequestDispatcher disp = request.getRequestDispatcher("user.jsp");
disp.forward(request, response);
return;
}
ListOfPerson listOfUsers = (ListOfPerson)context.getAttribute("listOfUsers");
if (listOfUsers == null) {
listOfUsers = new ListOfPerson();
request.setAttribute("listOfUsers", listOfUsers);
}
Alain Tchana, [email protected]
N7
2015
Exemple : action.java (servlet)
if (form.equals("user")) {
String u = request.getParameter("user");
if (listOfUsers.contains(u)) {
RequestDispatcher disp = request.getRequestDispatcher("listusers.jsp");
disp.forward(request, response);
return;
} else {
Person p = new Person();
p.user = request.getParameter("user");
session.setAttribute("user", p);
RequestDispatcher disp = request.getRequestDispatcher("person.jsp");
disp.forward(request, response);
return;
}
}
Alain Tchana, [email protected]
N7
2015
Exemple : action.java (servlet)
if (form.equals("person")) {
Person p = (Person)session.getAttribute("user");
p.firstname = request.getParameter("firstname");
p.lastname = request.getParameter("lastname");
p.email = request.getParameter("email");
listOfUsers.list.add(p);
}
}
}
RequestDispatcher disp = request.getRequestDispatcher("listusers.jsp");
disp.forward(request, response);
Alain Tchana, [email protected]
N7
2015
Exemple : les beans
public class Person {
public String user, firstname, lastname, email;
}
public class ListOfPerson {
public Vector list = new Vector();
}
public boolean contains(String user) {
Enumeration enu = list.elements();
while (enu.hasMoreElements()) {
Person p = (Person)enu.nextElement();
if (p.user.equals(user)) return true;
}
return false;
}
Alain Tchana, [email protected]
N7
2015
Servlet/JSP - Bilan
Présentation
– Sous forme de pages HTML
– Programmation en Java dans les pages
Code métier
– Sous forme de servlet
– Échange de données avec les pages sous forme de javaBeans
Modèle MVC donne une séparation claire entre
– Présentation (page JSP)
– Contrôle (servlet)
– Métier (programmes Java)
Le traitement des données récupérées de la BD peuvent être lourds
(d'où les EJB)
Alain Tchana, [email protected]
N7
2015
EJB
Enterprise Java Beans
Alain Tchana, [email protected]
N7
2015
Modèle MVC
Model View Controler
Séparation entre
– Le contrôleur : servlet qui aiguille les requêtes
– La vue : pages JSP pour l’affichage à l’écran
– Le Modèle : les classes (beans) qui traitent les données
Requête
HTTP
Réponse
HTTP
Controler
(quel traitement ?
quelle page ? )
Model
(traitement)
View
(page web)
Alain Tchana, [email protected]
N7
2015
Architecture souhaitée
Presentation (VC)
Requête
HTTP
Business (M)
Controler
servlet
result
Réponse
HTTP
Facade
View
JSP/HTML
Alain Tchana, [email protected]
Data
N7
2015
Architecture souhaitée
Clients
Serveur d'application
(Jboss)
Client
Java
RMI
Client
Web
HTTP
Client
Web service
SOAP
SGBD
(postgresql)
EJB
Container
Web
Container
Servlet
JSP
BD
EJB
Facade
Entity
Web
Services
Alain Tchana, [email protected]
N7
2015
Motivations
Solutions clusterisées
– Tolérance aux pannes
– Passage à l'échelle
Maintenance et évolution du code
– Adaptation, extension
– Portabilité (sur d'autres serveurs d'application)
Différents types de client (Web, lourd, mobiles ...)
Propriétés non-fonctionnelles (services techniques)
– Persistance
– Transactions
– Sécurité
Alain Tchana, [email protected]
N7
2015
Les EJB
Caneva (framework) logiciel pour gérer
– Des Entity beans
• Représentation des données stockées en base de donnée
• Évite d'avoir à implanter l'accès à la BD avec JDBC
– Des Session beans
• Pour implanter la facade
• Inclut le code de l'application qui utilise les données
(Entity)
– Des Message Driven beans
• Pour des traitements asynchrones
Alain Tchana, [email protected]
N7
2015
Prise en compte de services
techniques
Services techniques appelé propriétés non-fonctionnelles
– La distribution
– Les transactions
– La persistance
– Le cycle de vie
– La montée en charge
– Le concurrence
– Le sécurité
– La sérialisation
–…
Implantation par le container, configuration
Alain Tchana, [email protected]
N7
2015
Trois types d'EJB
Entity beans
– Représentent les données manipulées par l’application
– Chaque Entity est associé à une table au niveau de la base de données
Session beans
– Accessibles à distance (via RMI et IIOP)
– Implémentent le code métier
– Stateless session beans : sans état
• Une instance pour plusieurs connexions clientes (allouée à partir d'un pool)
• Ne conserve aucune donnée dans son état
– Statefull session bean : avec état
• Création d’une instance pour chaque connexion cliente
• Conserve des données entre les échanges avec le client
– Singleton: Instance Unique
• Création d’une instance unique quelque soit le nombre de connexion.
Message Driven Beans : Beans de messages
– Un listener exécute des traitements à réception d'un message JMS
Alain Tchana, [email protected]
N7
2015
EJB session
Interface Remote (annotation @Remote)
– Accessible à distance
Interface Local (annotation @Local)
– Accessible en local uniquement (dans le serveur d'application)
Classe du bean (annotations @Singleton, @Statefull, @Stateless)
– Peut implanter les 2 interfaces Local et Remote
JNDI
– Les interfaces définies sont exportées dans JNDI
– Nom de la classe utilisée, ou nom passé en attribut du tag
• @Singleton(name="monBean")
– Une recherche retourne une référence au bean (unique ou une copie)
Alain Tchana, [email protected]
N7
2015
Un exemple : application bancaire
Gestion de compte
– Données
• numero, nom, solde
– Méthodes
•
•
•
•
•
Ajouter un compte
Consulter un compte
Consulter tous les comptes
Créditer sur un compte
Débiter d'un compte
Depuis un client lourd distant
Depuis une application Web
(on pourrait le faire avec un WS)
Alain Tchana, [email protected]
N7
2015
Les données manipulées
public class Compte implements Serializable {
private int num;
private String nom;
private int solde;
public Compte() {}
public Compte(int num, String nom, int solde) {
this.num = num; this.nom = nom; this.solde = solde;
}
public String toString() {
return "Compte [num="+num+", nom="+nom+", solde="+solde+"]";
}
// setters and getters
Alain Tchana, [email protected]
N7
2015
Interface Remote / interface Local
@Remote
public interface IBanqueRemote {
public void addCompte(Compte c);
public List<Compte> consulterComptes();
public Compte consulterCompte(int num);
public void debit(int num, int montant);
public void credit(int num, int montant);
}
@Local
public interface IBanqueLocal {
public void addCompte(Compte c);
public List<Compte> consulterComptes();
public Compte consulterCompte(int num);
public void debit(int num, int montant);
public void credit(int num, int montant);
}
Alain Tchana, [email protected]
N7
2015
Implantation d'un EJB session
@Singleton
public class BanqueEjbImpl implements IBanqueLocal, IBanqueRemote {
private Map<Integer, Compte> comptes = new Hashtable<Integer, Compte>();
public void addCompte(Compte c) {
comptes.put(c.getNum(), c);
}
public List<Compte> consulterComptes() {
return new ArrayList<Compte>(comptes.values());
}
public Compte consulterCompte(int num) {
Compte c = comptes.get(num);
if (c == null) throw new RuntimeException("Compte introuvable");
return c;
}
Alain Tchana, [email protected]
N7
2015
Implantation d'un EJB Stateless
public void debit(int num, int montant) {
Compte c = consulterCompte(num);
if (c.getSolde()<montant) throw new RuntimeException("Solde insuffisant");
c.setSolde(c.getSolde()-montant);
}
public void credit(int num, int montant) {
Compte c = consulterCompte(num);
c.setSolde(c.getSolde()+montant);
}
@PostConstruct
public void initialisation() {
addCompte(new Compte(1, "dan", 2000));
addCompte(new Compte(2, "alain", 4000));
addCompte(new Compte(3, "luc", 6000));
}
}
Alain Tchana, [email protected]
N7
2015
Un client web (servlet)
Soit la servlet est dans une JVM séparée
– Configuration comme un client lourd
Soit la servlet est dans le serveur d'application (avec les EJB)
– Injection de dépendance
@EJB
private IBanqueLocal facade;
– Au déploiement, variable initialisée avec une instance
• de stateless, statefull ou singleton
Alain Tchana, [email protected]
N7
2015
Un client web (servlet)
@WebServlet("/Controller")
public class Controller extends HttpServlet {
private static final long serialVersionUID = 1L;
@EJB
private IBanqueLocal facade;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
String action=request.getParameter("action");
if (action.equals("consulter")) {
int num=Integer.parseInt(request.getParameter("num"));
request.setAttribute("num", num);
request.setAttribute("compte", facade.consulterCompte(num));
} else
if (action.equals("consultertous")) {
request.setAttribute("comptes", facade.consulterComptes());
} else
Alain Tchana, [email protected]
N7
2015
Un client web (servlet)
if ((action.equals("debit")) || (action.equals("credit"))) {
int num=Integer.parseInt(request.getParameter("num"));
int montant=Integer.parseInt(request.getParameter("montant"));
request.setAttribute("num", num);
request.setAttribute("montant", montant);
if (action.equals("debit")) facade.debit(num, montant);
else facade.credit(num, montant);
}
} catch (Exception ex) {
request.setAttribute("exception", ex.getMessage());
}
request.getRequestDispatcher("Banque.jsp").forward(request, response);
}
}
Alain Tchana, [email protected]
N7
2015
Une petite JSP
<%@ page language="java" import="bk.*, java.util.*" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="Controller" method="get">
<table>
<tr>
<td> Code :</td>
<td><input type="text" name="num" value="${num}"></td>
<td><input type="submit" name="action" value="consulter"></td>
<td><input type="submit" name="action" value="consultertous"></td>
</tr>
</table>
</form>
Alain Tchana, [email protected]
N7
2015
Une petite JSP
<% if (request.getAttribute("compte") != null) { %>
<table>
<tr><td> Num :</td><td>${compte.num}</td></tr>
<tr><td> Nom :</td><td>${compte.nom}</td></tr>
<tr><td> Solde :</td><td>${compte.solde}</td></tr>
</table>
<form action="Controller" method="get">
<table>
<tr>
<td><input type="hidden" name="num" value="${num}"></td>
<td><input type="text" name="montant" value="${montant}"></td>
<td><input type="submit" name="action" value="debit"></td>
<td><input type="submit" name="action" value="credit"></td>
</tr>
</table>
</form>
<% } %>
Alain Tchana, [email protected]
N7
2015
Une petite JSP
<% List<Compte> l = (List<Compte>)request.getAttribute("comptes");
if (l != null) {
%>
<table border="1" width="80%">
<tr> <th>Num</th><th>Nom</th><th>Solde</th></tr>
<% for (Compte c : l) { %>
<tr><td><%=c.getNum() %></td><td><%=c.getNom() %></td><td><%=c.getSolde() %></td></tr>
<% } %>
</table>
<% } %>
${exception}
</body>
</html>
Alain Tchana, [email protected]
N7
2015
Exécution
Alain Tchana, [email protected]
N7
2015
Entity beans (JPA)
Représentent des objets dans la base de donnée
– Une classe correspond à une table
– Une instance correspond à une ligne dans cette table
– Un champ correspond à une colonne de la table
Programmés comme des POJO (Plain Old Java Object)
– Pas d'héritage ou d'implantations spéciales
Sont serialisables et peuvent être échangés avec les applications
clientes
Ce sont des Java Beans
– Implements java.io.Serializable
– Possèdent un constructeur sans arguments
– Possèdent des setters / getters
Alain Tchana, [email protected]
N7
2015
Entity beans
La classe doit être annotée avec @Entity
Un champ annoté avec @Id est la clé primaire qui sert d'identifiant
unique dans la table
– Cette clé primaire peut être un type primitif ou de type objet
Les autres champs peuvent être associés aux colonnes de la table
Les champs sont utilisables au travers des accesseurs
(getters/setters)
On peut décrire l'association
– Entre le nom de la classe et le nom de la table
– Entre le nom d'un champ et le nom d'une colonne
– Mêmes noms par défaut
La base de donnée peut être pré-existante ou générée
Alain Tchana, [email protected]
N7
2015
Annotation de mapping entre le
bean et la table
@Table
– Préciser le nom de la table associée à une classe. Par défaut, c'est le
nom de la classe.
@Column
– Préciser le nom de la colonne associée à un champ. Par défaut, c'est
le nom du champ.
@Id
– Déclarer un champ (donc une colonne) comme clé primaire de la table.
@GeneratedValue
– Demander la génération automatique de la clé primaire par la BD (tag
utilisé avec @Id).
@Transient
– Demander à ne pas tenir compte d'un champ (par défaut tous les
champs sont associés à des colonnes)
Alain Tchana, [email protected]
N7
2015
Entity Compte
@Entity
public class Compte {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int num;
private String nom;
private int solde;
public Compte() {}
public Compte(String nom, int solde) {
this.nom = nom; this.solde = solde;
}
// num est généré
// constructors, setters and getters
Alain Tchana, [email protected]
N7
2015
Gestion avec l'EntityManager
EntityManager permet de gérer la persistance
@PersistenceContext
private EntityManager em;
Rendre un objet persistant dans la BD
Compte c = new Compte() ;
em.persist(c);
Retrouver un objet à partir de sa clé primaire
Compte c = em.find(Compte.class, num);
Retrouver un ou plusieurs objets avec une requête JPQL
TypedQuery<Compte> req = em.createQuery("select c from Compte c",Compte.class);
– Il y a aussi des NativeQuery (SQL)
Alain Tchana, [email protected]
N7
2015
Facade BanqueEjbImpl avec
EntityManager
@Singleton
public class BanqueEjbImpl implements IBanqueLocal, IBanqueRemote {
@PersistenceContext
private EntityManager em;
public void addCompte(Compte c) {
em.persist(c);
}
public List<Compte> consulterComptes() {
TypedQuery<Compte> req = em.createQuery("select c from Compte c",
Compte.class);
return req.getResultList();
}
Alain Tchana, [email protected]
N7
2015
Facade BanqueEjbImpl avec
EntityManager
public Compte consulterCompte(int num) {
Compte c = em.find(Compte.class, num);
if (c == null) throw new RuntimeException("Compte introuvable");
return c;
}
public void debit(int num, int montant) {
Compte c = consulterCompte(num);
if (c.getSolde()<montant) throw new RuntimeException("Solde insuffisant");
c.setSolde(c.getSolde()-montant);
}
public void credit(int num, int montant) {
Compte c = consulterCompte(num);
c.setSolde(c.getSolde()+montant);
}
...
}
Alain Tchana, [email protected]
N7
2015
Etat des objets
Objet transient
– @Transient
– Pas d'image dans la BD
Objet attaché
– Objet géré dans le container EJB est associé à une image dans la BD
– Toute modification de l'objet est répercutée dans la BD
Objet détaché
– Objet associé à une image dans la BD, mais plus géré par le
container
– Lorsqu'un objet attaché est sérialisé, sorti du container, modifié, puis
repassé au Container
c = em.merge(c);
Alain Tchana, [email protected]
N7
2015
Exécution avec JPA
Alain Tchana, [email protected]
N7
2015
Gérer les associations entre les
Entity
@OneToMany
@ManyToOne
@OneToOne
@ManyToMany
Alain Tchana, [email protected]
N7
2015
@OneToMany (unidirectionnel)
pk=primary key
fk=foreign key
Un Entity (Client) possède un champ Collection de références vers des instances (d'un autre Entity
(Compte))
Exemple : un client a plusieurs comptes
@Entity
public class Client {
@Id
@GeneratedValue(strategy=
GenerationType.IDENTITY)
int id;
String nom;
@Entity
public class Compte {
@Id
@GeneratedValue(strategy=
GenerationType.IDENTITY)
int id;
int solde;
@OneToMany
List<Compte> comptes;
Peut être implanté par une fk ou une table
de jointure (avec unicité pk Compte)
public void ajoutCompte(int cli_id, Compte c) {
em.persist(c);
Client cli = em.find(Client.class, cli_id);
cli.getComptes().add(c);
}
Alain Tchana, [email protected]
N7
2015
@ManyToOne (unidirectionnel)
Un Entity (Compte) possède un champ référence vers une instance (d'un autre Entity (Client))
Exemple : un compte appartient à un client (qui peut en avoir plusieurs car plusieurs comptes
peuvent avoir le même propriétaire)
@Entity
public class Client {
@Id
@GeneratedValue(strategy=
GenerationType.IDENTITY)
int id;
String nom;
@Entity
public class Compte {
@Id
@GeneratedValue(strategy=
GenerationType.IDENTITY)
int id;
int solde;
@ManyToOne
Client owner;
public void ajoutCompte(int cli_id, Compte c) {
em.persist(c);
Client cli = em.find(Client.class, cli_id);
c.setOwner(cli);
}
Alain Tchana, [email protected]
N7
2015
@OneToMany / @ManyToOne
(bidirectionnel)
Permet la navigation dans les 2 sens
Exemple : un client a plusieurs comptes et un compte appartient à un client
@Entity
public class Client {
@Entity
public class Compte {
@Id
@GeneratedValue(strategy=
GenerationType.IDENTITY)
int id;
String nom;
@Id
@GeneratedValue(strategy=
GenerationType.IDENTITY)
int id;
int solde;
@OneToMany(mappedBy="owner")
List<Compte> comptes;
@ManyToOne
Client owner;
Alain Tchana, [email protected]
N7
2015
@OneToMany / @ManyToOne
(bidirectionnel)
Le mappedBy indique le champ correspondant à la relation dans l'autre Entity
On dit que le coté opposé au mappedBy (Compte) est le porteur de la relation
On peut le faire dans l'autre sens, mais ce serait inefficace
La mise à jour
– Doit être faite du coté du porteur de la relation (Compte)
– Elle est propagée de l'autre coté par le container (dans la liste de Client)
public void ajoutCompte(int cli_id, Compte c) {
em.persist(c);
Client cli = em.find(Client.class, cli_id);
c.setOwner(cli);
}
Alain Tchana, [email protected]
N7
2015
@OneToOne
Unidirectionnel
– B1 doit pointer sur un B2 qui n'est pointé que par B1
– Deux implantations possible : fk dans B1 ou B2
– La BD ne vérifie pas forcément l'unicité de la fk
– JBoss ne semble pas le faire pour unidirectionnel
Bidirectionnel
– Le schéma ci-dessous est utilisé (garantit unicité fk coté B2)
// Client
@OneToOne(mappedBy="owner")
Compte compte;
// Compte
@OneToOne
Client owner;
public void changerCompte(int cli_id, Compte c) {
em.persist(c) ;
Client cli = em.find(Client.class, cli_id);
Compte old = cli.getCompte();
old.setOwner(null);
c.setOwner(cli);
}
sinon Exception
Alain Tchana, [email protected]
N7
2015
@ManyToMany
Unidirectionnel
– Comme un @OneToMany unidirectionnel (mais pas unicité du
référençant)
– @ManyToMany des 2 cotés sans mappedBy correspond a 2 relations
indépendantes
Bidirectionnel
– @ManyToMany des deux cotés
– Un porteur de l'association avec mappedBy
– Forcément une table de jointure (peut être implanté sans table de
jointure avec une fk pour unidirectionnel)
– Une mise à jour est effectuée du coté du porteur et propagée à l'autre
coté
Alain Tchana, [email protected]
N7
2015
@ManyToMany
// Client
@ManyToMany
List<Compte> comptes;
// Compte
@ManyToMany(mappedBy="comptes")
List<Client> owners;
public void partagerCompte(int cli_id, int co_id) {
Client cli = em.find(Client.class, cli_id);
Client co = em.find(Compte.class, co_id);
cli.getCompte().add(co);
}
Le compte apparaît dans la liste comptes du client
Le client apparaît dans la liste owners du compte
Alain Tchana, [email protected]
N7
2015
Cascades / Fetch
Entity Manager permet d'appeler les opérations persist(), merge(), remove()
(notamment)
– On peut contrôler la propagation de ces opérations sur les Entity référencés
// Client
@OneToMany(cascade=CascadeType.REMOVE)
List<Compte> comptes;
Que se passe t-il lorsqu'un Entity est sérialisé (sorti du container), pour ses
références aux autres Entity
– On peut contrôler le chargement des Entity
// Client
@OneToMany(mappedBy="owner", fetch=FetchType.EAGER)
List<Compte> comptes;
– Un client sérialisé aura une liste cohérente de comptes
– Par défaut FetchType.LAZY (chargement paresseux lors de l'utilisation)
Alain Tchana, [email protected]
N7
2015
Attention
Il faut toujours utiliser les setter/getter pour
affecter des champs (notamment pour le maintien
des relations bidirectionnelles)
Alain Tchana, [email protected]
N7
2015
L'essentiel
Alain Tchana, [email protected]
N7
2015
L'essentiel
Tomcat
Jboss
Postgres
Entity bean
Servlet
1
Session bean
(facade)
n
Entity bean
@EJB
table
@Stateless
@PersistenceContext
new MyEntity
em.persist()
em.find()
em.createQuery()
@Entity
@Id
@OneToOne
@OneToMany
@ManyToOne
@ManyToMany
Alain Tchana, [email protected]
table
N7
2015
L'essentiel
Jboss
Postgres
Facade
@Stateless
public class Mngr {
@PersistenceContext
EntityManager em;
public void ajoutCompte (
String na, int nu, int ba) {
Account a = new Account(nu,ba);
em.persist(a);
Person p = em.find(Person.class,na);
p.getList().add(a);
}
}
@Entity
public class Person {
@Id
String name;
String address;
@OneToMany
List<Account> list;
}
1
n
@Entity
public class Account {
@Id
int num;
int balance;
}
Alain Tchana, [email protected]
Person
name
address
Account
num balance name
N7
2015
Conclusion
Alain Tchana, [email protected]