Vous êtes sur la page 1sur 114

Java Edition Entreprise

Java EE
Présentation du cours

 36h sur 12 semaines


 Objectifs
Développement d’applications Web robustes
utilisation d’un framework (standard)
Apprentissage d’une partie de Java EE
Servlet, JSP et EJB
 Prérequis
Maîtrise du langage Java (Java SE)
Maîtrise du développement Web client
 XHTML (au moins balises de structure et formulaires)
 CSS et XML sont un plus
Java EE?

 Java Enterprise Edition est un framework


– riche (Java SE + nombreuses API)
– ouvert (specs. du Java Community Process)
– dédié au développement, au déploiement et à l’exécution
d’applications Internet modernes (nécessaires aux
entreprises)

 Favorise la séparation des préoccupations


– Code métier vs. Propriétés non-fonctionnelles
persistance (JPA), administration (JMX), sécurité,
transaction
(JTS/JTA), …
Le développement Web
 Le World Wide Web
– Un SI public et universel déployé sur Internet
– Un langage : HTML (ou XHTML)
– Un modèle de communication : client-serveur
– Un protocole : HTTP

 Pages statiques
– Pages HTML préparées à l’avance
– Le serveur renvoie les pages sans effectuer de traitement
Particulier

 Pages dynamiques
– Pages HTML générées par le serveur
– Le serveur construit la réponse en fonction de la requête de
l’utilisateur
Java et le développement Web
Différentes technologies « Java » permettent de
faire du
développement Web à différents niveaux.
Développement
Côté client Côté serveur
Classe autonome applet Servlet
Java mixé avec JavaScript JSP
HTML
Pages statiques Pages dynamiques
HTML (rappel)

 Langage de balisage, non propriétaire


 Conçu pour afficher des documents sur le Web
 Liens hypertextes possibles entre les documents
 XHTML assure maintentant la compatibilité avec XML

<?xml version="1.0" encoding="ISO-8859-1"?>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html >
<head> <title>Titre de mon document</title> </head>
<body>
...
</body>
</html>
Quelques balises
Pages statiques
 Fonctionnement normal d’un serveur Web seul
– Le serveur cherche la page dans le système de fichiers
– La page est renvoyée au client telle quelle
Limites d’un serveur Web seul
 Pas de contenu dynamique

 Pas de sauvegarde de données sur le serveur


• Traitemenent de formulaires :
• besoin d’une application d’aide au serveur Web
pour évaluer les paramètres reçus
pour générer une réponse appropriée
Pages dynamiques
 Le serveur Web a besoin d’aide pour faire du dynamique
– Autrefois, les CGI (Common Gateway Interface)
– Aujourd’hui, un conteneur Java EE avec servlets (ex :
Tomcat)
Introduction aux servlets
Conteneur
 La notion de conteneur se retrouve dans de nombreuses
technologies
– Servlet, Applet, MIDlet, Xlet, (*-let), EJB, …
 Un conteneur est un composant logiciel système qui contrôle
d’autres composants, dits métier
– Tomcat est un exemple de conteneur
– Les servlets n’ont pas de méthode main(), ils sont contrôlés par le
conteneur
Tomcat
– Les requêtes ne sont pas adressées aux servlets mais au conteneur
dans lequel ils sont
déployés
Pourquoi un conteneur ?
 Pour oublier le cours de « réseau » !
 Un conteneur fournit pour les Servlets
– Un support pour la communication
• Pas besoin de ServerSocket, Socket, Stream, …
– La gestion du cycle de vie
– Un support pour le Multithreading
• Création automatique des Threads
– Un support pour la sécurité
– Un support pour les JSP
Notion de module Web
 Un servlet ne peut pas être déployé directement dans un
conteneur, il doit faire partie d’un module Web
 Un module Web est un ensemble de librairies, de fichiers de
configurations, de code Java (bytecode des servlets…), …
 Le module Web est l’unité de déploiement dans le conteneur
Servlet en 4 étapes (1/4)
Créer l’arborescence suivante
Projet Dynamic web project

WebConten
src
t

WEB-
INF Imposé par
la spécificatio
des servlets
Clock.java

Web.xml
Servlet en 4 étapes (2/4)
package ensat.cours.tp;
Ecrire servlet Clock et le mettre dans
import java.io.*; src
import javax.servlet.http.*;
import javax.servlet.*;
Redéfinition
public class Clock extends HttpServlet { de la
méthode
public void doGet(HttpServletRequest request, HttpServletResponse reponse)
throws IOException, ServletException{ doGet
String title = "Clock";
String doctype = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Strict//EN \"
\" http://www.w3.org/TR/html4/strict.dtd \" >" ;

reponse.setContentType("text/html");
PrintWriter out = reponse.getWriter();

Code out.println(doctype +
html "<html><head><title>"+title+"</title></head>"+
incorporé "<body><h1>Time On Server</h1>"+"<br>"+
dans du new java.util.Date() +"</body></html>");
out.close();
java }
}
Servlet en 4 étapes (3/4)
Créer un descripteur de déploiement et
<?xml version="1.0" encoding="UTF-8"?> le mettre dans WEB-INF
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<display-name>WebModule1</display-name>

<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list> Servlet-name permet de lier
<servlet >et <servlet-
<servlet> mapping>
<servlet-name>The Clock</servlet-name>
<servlet-class>ensat.cours.tp.Clock</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>The Clock</servlet-name> nom utilisé par
<url-pattern>/Serv1</url-pattern>
l’utilisateur dans sa
</servlet-mapping>
requête
</web-app>
Servlet en 4 étapes (4/4)
 Démarrer le serveur (Tomcat)
 Compiler la servlet
 Lancer un navigateur et taper http://localhost:8080/Projet/Serv1
Servlets
 Un servlet est un objet qui peut être manipulé par
le conteneur via l’interface suivante :

 Lorsque le conteneur reçoit une requête, il la


transmet au servlet qui correspond à l’URL pour
que la requête soit traitée effectivement
Cycle de vie d’un servlet

1. Chargement de la classe
2. Instanciation du servlet
• constructeur par défaut
3. Appel de init()
4. Appel(s) de service()
• 1 thread par requête
5. Appel de destroy()
La méthode service()
 Lors de la réception d’une requête, le conteneur crée
– un objet ServletRequest (la requête), et
– un objet ServletResponse (la réponse)

 Le conteneur appelle ensuite la méthode service() avec ces deux objets en paramètres pour
permettre au servlet de répondre à la requête du client

Requêtes HTTP (rappel)


 Deux méthodes principales : GET et POST
Servlets HTTP
Requêtes et Réponses HTTP
Entêtes d’une requête GET
public class ShowRequestHeaders extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws
IOException {

//...
out.println(doctype +
"<html>\n<head><title>" + title + "</title></head>\n" +
"<body>\n<h1>" + title + "</h1>\n" +
"<b>Request Method: </b>" + request.getMethod() + "<br />\n" +
"<b>Request URI: </b>" + request.getRequestURI() + "<br />\n" +
"<b>Request Protocol: </b>" + request.getProtocol() + "<br />)

out.println("<table>\n" +"<tr><th>Header Name</th><th>Header Value</th></tr>");

Enumeration<String> headerNames = request.getHeaderNames();

while(headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
out.println("<tr><td>" + headerName + "</td>");
out.println("<td>" + request.getHeader(headerName) +"</td></tr>");
}

out.println("</table>\n</body></html>");
out.close();
}
}
changer
Entêtes d’une requête POST

public class ShowRequestHeaders extends HttpServlet {


public void doPost(HttpServletRequest request, HttpServletResponse
response) throws IOException {
doGet(request,response);
}
}
Formulaire GET

<form action="Serv2">
<table border="0">
<tr>
<td>Nom: </td><td><input type="text" name="nom"></td>
</tr>
<tr>
<td>Prénom:</td><td><input type="text" name="prenom"></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="
Envoyer" </td>
</tr>
</table>
</form>
Traitement formulaire GET
Get http://localhost:8080/WebModule1/Serv2?
nom=houda&prenom=Belmokadem HTTP/1.1
host:localhost:8080
user-agent:Mozilla/4.0 GET
accept:image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-
excel, application/vnd.ms-powerpoint, application/msword, application/x-
shockwave-flash, */*
accept-language:fr
...
public class LogServlet extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws IOException {
String login = request.getParameter("nom") ;
String password = request.getParameter("prenom") ;
//WhatYouWant
if (checkUserAndPassword(login, password)) {
grantAccessTo(login);
} else {
sendAuthentificationFailure(login);
}
}
}
Formulaire POST

<form method="post" action="Serv2">


<table border="0">
<tr>
<td>Nom: </td><td><input type="text" name="nom"></td>
</tr>
<tr>
<td>Prénom:</td><td><input type="text" name="prenom"></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="
Envoyer" </td>
</tr>
</table>
</form>
Traitement formulaire Post
Post http://localhost:8080/WebModule1/Serv2 HTTP/1.1
host:localhost:8080
user-agent:Mozilla/4.0
accept:image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-
GET
excel, application/vnd.ms-powerpoint, application/msword, application/x-
shockwave-flash, */*
accept-language:fr
...
content-type:application/x-www-form-urlencoded
content-length:27

public class LogServlet extends HttpServlet {


public void doPost(HttpServletRequest request,HttpServletResponse
response) throws IOException {
doGet(request, reponse);
}
}
Paramètres de formulaires
public class ParametresFormulaire extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse reponse) throws IOException,
ServletException{

out.println(doctype+ "<html><head><title>"+title+"</title><head>"+ "<body>");
Enumeration<?> paramètres = request.getParameterNames();
if(!paramètres.hasMoreElements())
out.println("il n'existe pas de paramètre dans la requête du client" +"</body>+</html>");
else{
out.println(request.getQueryString()+
"<br><table border=\"0\"><tr><th>Paramètre</th><th>Valeur</th></tr>");
while(paramètres.hasMoreElements()){
String param = (String) paramètres.nextElement();
out.println("<tr><td>"+param+"</td>");
String[] paramValues = request.getParameterValues(param);
for(int i=0; i<paramValues.length ; i++){
out.println("<td>"+ paramValues[i]+ ";"+"</td>");
}
out.println("</tr>");
}
out.println("</table>");
}
out.println("</body></html>");
out.close();
}
Vérification de données
manquantes
 Champ manquant dans le formulaire
• getParameter retourne null
 Champ renvoyé vide
• getParameter retourne une chaine vide (ou une chaine avec des
espacements)

String param = request.getParameter("someName");


if ((param == null) || (param.trim().equals(""))) {
doSomethingForMissingValues(...);
} else {
doSomethingWithParameter(param);
}
Upload de fichiers (avec Commons
FileUpload )
 Formulaire HTML
– <input type="file" name="nameFile" />
– <form method="post" enctype="multipart/form-data" action="/servlet">
– Le choix du enctype impacte les autres champs du formulaire
• request.getParameter("name") ne fonctionne plus
 Côté Servlet
– utiliser une librairie
Commons FileUpload du projet Jakarta
(http://commons.apache.org/fileupload/)
 Développement
– import org.apache.commons.fileupload.*
– import org.apache.commons.fileupload.servlet.*
 Déploiement
– Dans le module Web de l’application…
– …dans le répertoire WEB-INF/lib
• commons-fileupload-1.2.1.jar
• commons-io-1.4.jar
Exemple : Upload simple (½)
//Télécharger un fichier txt et l’afficher dans la réponse de la servlet

if ( ServletFileUpload.isMultipartContent(request) ) {

// create a factory for disk-based (large) file items


FileItemFactory fileItemFactory = new DiskFileItemFactory() ;
((DiskFileItemFactory) fileItemFactory).setSizeThreshold(40960); //the unit is
bytes

// create a new file upload handler


ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
servletFileUpload.setSizeMax(81920); // the unit is bytes
Exemple : Upload simple (2/2)
try {
List<?> fileItemsList = servletFileUpload.parseRequest(request);
// Process file items
Iterator<?> it = fileItemsList.iterator();
while (it.hasNext()){
DiskFileItem fileItem = (DiskFileItem)it.next();
if (fileItem.isFormField()){ // classic form field (name=value)
out.println("<b>Champs:</b><br />\n" + fileItem.getFieldName() +"=" +
fileItem.getString()+ "<br/>");
}
else{ // uploaded file
out.println("<b>Fichier:</b><br />\n<pre>" + fileItem.getString() +
"</pre><br/>");
}
}
} catch (FileUploadException e) {
out.println("Impossible de télécharger ce fichier");
e.printStackTrace();}}
Réponse HTTP (rappel)
 Une réponse HTTP peut contenir du HTML
 HTTP rajoute des (meta)informations en entête du contenu de la
réponse
Status Codes
response.setStatus(int statusCode)
– Utiliser les constantes, pas d’entiers directement
– Noms dérivés du message standard
• Ex : SC_OK, SC_NOT_FOUND, etc

• response.sendError(int code, String msg)


– Englobe le message dans un petit document HTML

• response.sendRedirect(String url)
– Le code de status est alors 301
– L’attribut « Location » est également généré dans
l’entête de la réponse
Exemple sendError
public class LogServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
String login = request.getParameter("param1") ;
String password = request.getParameter("param2") ;
if ((login == null) || (login.trim().equals(""))) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,“champs
login
vide");
return;
}
if (checkUserAndPassword(login, password)) {
grantAccessTo(login);
} else {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, “accès
refuser
au compte" + login);
}
}
}
Exemple sendRedirect
public class WrongDestination extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
String userAgent = request.getHeader("User-Agent");
if ((userAgent != null) &&(userAgent.contains("MSIE")) {
response.sendRedirect("http://home.netscape.com");
}
else {
response.sendRedirect("http://www.microsoft.com");
}
}
}

Même URL de départ ensuite une redirection ...


Générer un fichier Excel
public class FichierExcel extends HttpServlet {
public void doGet(HttpServletRequest requete, HttpServletResponse
reponse) throws IOException,ServletException{
reponse.setContentType("application/vnd.ms-excel");
PrintWriter out = reponse.getWriter();
out.println("\tQ1\tQ2\tQ3\tQ4\tTotal");
out.println("Apples\t78\t87\t92\t29\t=SOMME(B2:E2)");
out.println("Oranges\t77\t86\t93\t30\t=SOMME(B3:E3)");
}
}
TP: introductions aux
Servlets
Introduction aux JSP

JSP: Java Server Pages


Problème : HTML dans Java
 C’est laid !

out.println(docType);
out.println("<html>");
out.println("<head>\n<title>Clock</title>\n</head>");
out.println("<body>\n" +
"<h1>Time on server</h1>\n" +
"<p>" + today + "</p>\n" +
"</body>");
out.println("</html>");

 Les ingénieurs connaissent Java, mais les


développeurs Web, NON !!

 Difficile de séparer les différentes tâches du


développement
(code Web vs. code métier)
Solution : Java dans HTML

 Une JSP est identique à une page HTML sauf


que l’on peut rajouter du Java dedans

<!DOCTYPE HTML PUBLIC"-//W3C//DTD HTML 4.0


Transitional//EN">
<html>
<head><title>Clock</title></head>
<body>
<h1>Time on server</h1>
<p> <%= new java.util.Date() %> </p>
</body>
</html>
Une JSP en 1 étape
 Ecrire une JSP Clock.jsp et la mettre à la racine
du dossier web au même endroit que les fichier
HTML.

webContent
Les JSP c’est quoi?
 Les servlets facilitent le traitement avec java des
requêtes et réponses HTTP, mais ils ne sont pas
appropriés à l’écriture de code HTML
out.println("<html><head><title>"+title+"</title>…");
 Les JSP permettent d’intégrer du code java dans
une page HTML
<p><%= new java.util.Date() %></p>
 Mais au final une JSP n’est qu’une servlet !
Cycle de vie d’une JSP
Correspondance JSP/Servlet
• JSP d’origine

• Servlet générée par Tomcat


• $ECLIPSEWORKDIR\.metadata\.plugins\org.eclipse.wst.server.core\tmpX\
work\Catalina\localhost\MonProjet\org\apache\jsp
Stratégie de conception :
Limiter le code Java dans les JSP
 Deux options
 Ecrire 25 lignes de code directement dans une JSP
 Ecrire ces 25 lignes dans une classe Java à part et1 ligne dans
une JSP
pour l’invoquer

 Pourquoi la 2e option est vraiment meilleure ?


 Développement. Ecriture de la classe dans un environnement
Java et pas HTML
 Débogage. S’il y a des erreurs, elles sont visibles à la
compilation
 Test. L’accès à la classe Java facilite le test
 Réutilisation. Utilisation de la même classe dans différentes
pages JSP
Syntaxe de base
 Texte HTML
<h1>Blah</h1>
Passé au client. Réellement traduit en servlet par le code
out.print("<h1>Blah</h1>");
 Commentaires HTML
<!-- Commentaire -->
Pareil que les autres éléments HTML : passés au client
 Commentaires JSP
<%-- Commentaires --%>
Ne sont pas envoyés au client

 Pour obtenir <% dans la sortie, utiliser <\%


Types des éléments de scripts
 Expressions
 Format : <%= expression %>
 Evaluée et insérée dans la sortie du servlet se traduit par
out.print(expression)
 Scriptlets
 Format : <% code %>
 Inséré tel quel dans la méthode _jspService du servlet
(appelée par
service)
 Déclarations
 Format : <%! code %>
 Insérée telle quelle dans le corps de la classe servlet, en
dehors
de toute méthode existante
 Syntaxe XML
Voir la fin des transparents pour la compatibilité avec XML
Expressions JSP:
<%= valeur %>
Expressions JSP
 Format
<%= Expression Java %>

 Résultat
 Expression évaluée, convertie en String, et placée dans la page
HTML à la place qu’elle occupe dans la JSP
 L’expression est placée dans _jspService en paramètre du
out.print()

 Exemples
 Heure courante : <%= new java.util.Date() %>
 Hostname: <%= request.getRemoteHost() %>

 Syntaxe compatible XML


 <jsp:expression>Java Expression</jsp:expression>

On ne peut pas mixer les deux versions dans une même page. Il
faut
utiliser XML pour la page entière si on utilise jsp:expression (Voir
les
Correspondance JSP/Servlet
 JSP d’origine

<h1>Un nombre aléatoire</h1>


<%= Math.random() %>

 Code du servlet résultant de la traduction

public void _jspService(HttpServletRequest request,


HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
JspWriter out = response.getWriter();
out.println("<h1>Un nombre aléatoire</h1>");
out.println(Math.random());
...
}
Expressions JSP : Exemple
<body>
<h2>JSP Expressions</h2>
<ul>
<li>Current time: <%= new java.util.Date() %> </li>
<li>Server: <%= application.getServerInfo() %> </li>
<li>The <code>testParam</code> form parameter:
<%= request.getParameter("testParam") %>
</ul>
</body>
</html>
Variables prédéfinies
 request
Instance de HttpServletRequest (1e argument de
service/doGet)
 response
Instance de HttpServletResponse (2e argument de service/doGet)
 out
Intance de JspWriter (une version bufferisée de Writer) utilisée
pour
envoyer des donnés sur la sortie vers le client
 session
Instance de HttpSession associée à la requête (sauf si
désactivée avec
l’attribut session de la directive de la page)
 application
Instance de ServletContext (pour partager des données) telle
que
obtenue via getServletContext()
Exemple : Lire 3 paramètres (JSP)
<!DOCTYPE …>
<html>
<head>
<title>Reading Three Request Parameters</title>
</head>
<body>
<h1>Reading Three Request Parameters</h1>
<ul>
<li><b>param1</b>:
<%= request.getParameter("param1") %></li>
<li><b>param2</b>:
<%= request.getParameter("param2") %></li>
<li><b>param3</b>:
<%= request.getParameter("param3") %></li>
</ul>
</body></html>
Scriptlets JSP:

<% Code %>


Scriptlets JSP
 Format
<% Code Java %>

 Résultat
Code inséré tel quel dans _jspService()

 Exemple
<%
String queryData = request.getQueryString();
out.println("Attached GET data: " + queryData);
%>
<% response.setContentType("text/plain"); %>

 Syntaxe XML
<jsp:scriptlet>Code Java</jsp:scriptlet>
Correspondance JSP/Servlet
JSP d’origine
<h2>foo</h2>
<%= bar() %>
<% baz(); %>

Code du servlet résultant de la traduction

public void _jspService(HttpServletRequest request,HttpServletResponse


response) throws
ServletException, IOException {
response.setContentType("text/html");
HttpSession session = request.getSession();
JspWriter out = response.getWriter();
out.println("<h2>foo</h2>");
out.println(bar());
baz();
...
}
Scriptlets JSP: Exemple
 On veut permettre à l’utilisateur de choisir la couleur de fond de la page
HTML

<!DOCTYPE …>
<html>
<head>
<title>Color Testing</titl>
</head>
<%
String bgColor = request.getParameter("bgColor");
if ((bgColor == null)||(bgColor.trim().equals(""))){
bgColor = "WHITE";
}
%>
<body bgcolor="<%= bgColor %>">
<h2 align="CENTER">Testing a Background of "<%= bgColor %>".</h2>
</body></html>
Utilisation des scriptlets pour
créer des parties conditionnelles
 Postulat
– Les scriplets sont insérés tels quels dans le servlet
– Pas besoin d’avoir des expressions Java complètes
– Cependant, les expressions complètes sont la plupart du temps plus
claires et faciles à
maintenir
 Exemple
<% if (Math.random() < 0.5) { %>
Vous avez <b>gagné</b> !
<% } else { %>
Vous avez <b>perdu</b> !
<% } %>
 Code du servlet résultant de la traduction
if (Math.random() < 0.5) {
out.println("Vous avez <b>gagné</b> !");
} else {
out.println("Vous avez <b>perdu</b> !");}
Déclaration JSP
<%! Code %>
Déclarations JSP
 Format
<%! Java Code %>
 Résultat
Insérées telle quelle dans la définition de la classe du
servlet, en
dehors de toute méthode existante
 Exemples
<%! private int someField = 5; %>
<%! private void someMethod(...) {...} %>
 Remarque de conception
Les attributs sont clairement utiles. Pour les méthodes, il
est la
plupart du temps préférable de les définir dans une classe
Java
séparée
 Syntaxe XML
<jsp:declaration>Code Java</jsp:declaration>
Correspondance JSP/Servlet
 JSP d’origine

<h1>Some Heading</h1>
<%!
private String randomHeading() {
return("<h2>" + Math.random() + "</h2>");
}
%>
<%= randomHeading() %>

(Alternative : créer randomHeading en méthode


statique dans
une classe Java séparée)
Correspondance JSP/Servlet
 Code du servlet résultant de la traduction

public class MyJSP_jsp implements HttpJspPage {


private String randomHeading() {
return("<h2>" + Math.random() + "</h2>");
}

public void _jspService(HttpServletRequest request,


HttpServletResponse
response) throws ServletException, IOException {
response.setContentType("text/html");
HttpSession session = request.getSession();
JspWriter out = response.getWriter();
out.println("<h1>Some Heading</h1>");
out.println(randomHeading());

}

}
Déclarations JSP : Exemple
<!DOCTYPE …>
<html>
<head>
<title>JSP Declarations</title>
<link rel=STYLESHEET
href="JSP-Styles.css"
type="text/css">
</head>
<body>
<h1>JSP Declarations</h1>
<%! private int accessCount = 0; %>
<h2>Accesses to page since server reboot:
<%= ++accessCount %></h2>
</body></html>
Méthodes jspInit et jspDestroy
 Les méthodes jspInit() and jspDestroy() sont à
définir par l’auteur de la page JSP, contrairement
à la méthode _jspService() qui est générée
automatiquement par le conteneur.

 jspDestroy() est exécuté à la fin de cycle de la


JSP.
 jspInit() est exécuté lors du premier appel de la
JSP.

 La servlet auto-générée garantie que ces deux


méthodes seront appelées depuis init et destroy.
Déclarations JSP et variables
prédéfinies
 Rq1: Problème
– Les variables prédéfines (request, response, out, session,
etc.)
sont locales à la méthode _jspService.
Ainsi, elles ne sont pas disponibles pour les méthodes définies
par
des déclarations JSP et les méthodes des classes externes.
– Que peut-on faire ?
 Solution : les passer en paramètres. Ex :
<%!
private void someMethod(HttpSession s) {
doSomethingWith(s);
}
%>
<% someMethod(session); %>
 Rq 2 : println de JSPWriter lance une IOException
– Utiliser “throws IOException” pour les méthodes qui utilisent
println
Types des éléments de scripts JSP :
les directives de page

 Donnent des informations sur le servlet qui sera


généré pour la page JSP

 Principalement utilisées pour :


– L’importation de classes et paquetages
– Le type MIME généré par la JSP
L’attribut import
 Format
<%@ page import="paquetage.classe" %>
<%@ page import="paquetage.classe1,...,paquetage.classeN"
%>

 But
Générer les instructions d’importation

 Remarque
Bien que les pages JSP peuvent être n’importe où sur le
serveur, les classes
utilisées par les pages JSP doivent être dans le répertoire des
classes de
l’application Web
– C’est-à-dire : …/WEB-INF/classes
Les attributs « contentType » et
« pageEncoding »

 Format
– <%@ page contentType="MIME-Type" %>
– <%@ page contentType="MIME-Type;charset=Character-Set"
%>
– <%@ page pageEncoding="Character-Set" %>

 But
– Spécifier le type MIME de la page générée par le servlet
résultant de la page JSP
Intégration
des servlets et des JSP :
Application du design pattern
Model-View-Controller (MVC)
Pourquoi combiner Servlets & JSP?
 Classiquement : utilisation des JSP pour faciliter le
développement et la maintenance du contenu HTML

– Pour du code dynamique simple, appel du code


d’un servlet à
partir de scripts JSP
– Pour des applications un peu plus complexes,
utilisation de
classes appelées à partir de scripts JSP

 Mais ça n’est pas suffisant


– Pour des traitements complexes, démarrer avec
des JSP n’est
pas pratique du tout
Pourquoi combiner Servlets & JSP?
 Servlet seuls. Marche bien quand :
– L’output est de type binaire. Ex : une image
– Il n’y a pas d’output. Ex : redirections
– La forme/présentation est variable. Ex : portail
 JSP seules. Marche bien quand :
– L’output est de type caractère. Ex : HTML
– La forme/présentation est stable.
 Architecture MVC. Nécessaire qd:
– Une même requête peut donner des résultats visuels
réellement
différents
– On dispose d’une équipe de développement
conséquente avec
une partie pour le dev. Web et une autre pour la logique
métier
– On a un traitement complexe des données mais une
présentation relativement fixe.
Design-pattern: MVC
MVC model 2:Application dans le
cadre d’Internet
Exemple: liste de promotion
MVC : étape 1
 Le client récupère un formulaire (form.html) pour
passer une requête avec paramètres (1, 2 puis
3).
Formulaire : form.html
<body>
<h1>L'école virtuelle de L'ENSAT</h1>
<form action="controller">
<table>
<tr><td>Sélectionner la promo à afficher</td>
<td><SELECT name= "promo">
<OPTION VALUE="info3">info3</OPTION>
<OPTION VALUE="gstr3">gstr3</OPTION>
<OPTION VALUE="gsea3">gsea3</OPTION>
</SELECT>
</td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Envoyer"></td>
</tr>
</table>
</form>
</body>
MVC : étape 2
1. Le client envoie son formulaire (GET/POST avec paramètres)
2. Le conteneur transmet au servlet correspondant (le controller)
Controller : SelectPromo.java

import javax.servlet.http.HttpServletResponse;
import ensat.cours.logiquemetier.Promo;
public class SelectPromo extends HttpServlet {
public void doGet(HttpServletRequest re,
HttpServletResponse pe)
throws IOException, ServletException{
...
String param = re.getParameter("promo");
...
}
}
MVC : étape 3
3. La servlet controller interroge le model sur « info3 »
4. Le model retourne au controller le résultat
correspondant
Model: une classe Java
public class Promo {
public List<String> getPromo(String param){
List<String> reponse = new ArrayList<String>();
if(param.equals("info3")){
reponse.add("Houda");
reponse.add("Rachida");
}
else if(param.equals("gsea3")){
reponse.add("Saida");
reponse.add("Ahmed");
}
else
reponse = null;
return reponse;
}
}
MVC : étape 4
5. Le controller utilise les données du model pour sa
réponse
6. Le controller transmet sa réponse à la view (JSP)
Controller : SelectPromo.java

String param = request.getParameter("fonction");


//Promo retourn la liste correpondante au controleur
Promo ob = new Promo();
List<String> list = ob.getPromo(param);
System.out.println(" " + (list == null));
//construit la requête puis l'envoie à la vue
request.setAttribute("liste", list);
request.getRequestDispatcher("reponse.jsp").forward(request,reponse);
MVC : étape 5
7. La JSP (view) traite la réponse transmise par le
controller
8. La page HTML résultante est reçue par le client
View: resultat.jsp
<body>
<%
List<String> l = (List<String>) request.getAttribute("liste");
System.out.println(l==null);
Iterator i = l.iterator();
while(i.hasNext()){
out.println("<br>" + i.next());
}
%>
</body>
Les pages JSP et les
JavaBeans
Architecture Web JEE: model2
(MVC)

Relation indirecte
Architecture Web JEE: model1
(pas MVC)
JavaBeans ?
 Les JavaBeans sont des classes Java (POJO) qui
suivent certaines conventions :
– Doivent avoir un constructeur vide (zero argument)
• On peut satisfaire cette contrainte soit en définissant
explicitement un tel
constructeur, soit en ne spécifiant aucun constructeur
– Ne doivent pas avoir d’attributs publics
• Une bonne pratique réutilisable par ailleurs…
– La valeur des attributs doit être manipulée à travers des
méthodes getXxx et setXxx
• Si une classe possède une méthode getTitle qui retourne une
String, on dit que le bean possède une propriété String nommée
title
• Les propriétés Boolean utilisent isXxx à la place de getXxx

 Référence sur les beans, cf.


http://java.sun.com/beans/docs/
Pourquoi faut-il utiliser des
accesseurs ?
 Dans un bean, on ne peut pas avoir de champs
publics
 Donc, il faut remplacer
public String prenom;
par
private String prenom;
public String getPrenom () {
return(prenom);
}
public void setprenom (String prenom) {
This.prenom = prenom ;
}
Pourquoi faut-il faire cela pour tout code Java ?
Pourquoi faut-il utiliser des
accesseurs ?
1. On peut imposer des contraintes sur les données
2. On peut rajouter du code annexe

public void setPrenom(String prenom) {


this.prenom = prenom.substring(0, 1).toUpperCase()
+ prenom.substring(1, prenom.length()).toLowerCase();
enregistrerBD();
}

3. On peut changer de représentation interne sans changer d’interface

public void setPrenom(String prenom) {


this.prenom = prenom.toUpperCase()
enregistrerBD();
}
Utilisation basique des Beans
 jsp:useBean
– Cet élément permet de rendre un JavaBean accessible
dans la page JSP.
Utilisation :
<jsp:useBean id="beanName" class="package.Class" />
 jsp:setProperty
– Cet élément modifie une propriété d’un bean (i.e., appel
d’une méthode setXxx).
Utilisation :
<jsp:setProperty
name="beanName" property="propertyName"
value="propertyValue" />
 jsp:getProperty
– Cet élément lit et retourne la valeur d’une propriété d’un
bean.
Utilisation :
<jsp:getProperty name="beanName" property="propertyName"
/>
Approche générale avec des JSP
et les tags jsp:useBean …
 Dans les pages JSP, il est toujours très difficile de lire
le mélange à la fois de code HTML et de code Java.
 L’approche la plus judicieuse est d'utiliser une
écriture plus proche du HTML en utilisant la syntaxe
du XML tout en faisant référence, malgré tout, à des
classes Java.
Ex: <jsp:useBean id="beanName" class="package.Class" />
 Le webmaster s'occuperait alors des balises à mettre
en place sur ces différentes pages Web dynamiques,
alors que le développeur s'occuperait essentiellement
de mettre en place toutes les classes nécessaires à
l'application Web.
 Les JavaBeans permettent de composer une structure
particulière sur ces classes respectant un schémas
standard afin qu'ils puissent être utilisés par le
webmaster au moyen de balises spécifiques et donc
sans code Java.
Approche générale avec des JSP
et les tags jsp:useBean …
 L’utilisateur soumet un formulaire vers une JSP
– <FORM ACTION="SomePage.jsp">

 La page JSP instancie un bean


– <jsp:useBean id= " Personne" class="…"/>

 On passe des données de la requête au bean


– <jsp:setProperty name="Personne"property="prenom"
value="…"/>

 On affiche des valeurs issues des données de la


requête
– <jsp:getProperty name=“Personne"
property="prenom"/>
Création de Beans: jsp:useBean
 Format:
– <jsp:useBean id="name" class="package.Class" />

 But:
– Permettre l’instanciation de classes Java sans
programmation Java explicite (syntaxe compatible XML)
 Remarques:
– Interpretation simple :
<jsp:useBean id="book1" class="coreservlets.Book" />
peut être vu comme équivalent au scriptlet :
<% coreservlets.Book book1 = new coreservlets.Book(); %>

 Mais jsp:useBean a deux avantages supplémentaires


:
1. Facilite l’utilisation des paramètres de requête
2. Facilite le partage des objets entre pages ou servlets
Modification de propriétés de Bean :
jsp:setProperty
 Format
–<jsp:setProperty name="name"
property="property"value="value" />
 But
– Permettre de modifier les propriétes d’un bean
properties (i.e.,
appel de méthodes setXxx) sans programmation
Java explicite
 Remarques
– <jsp:setProperty name="book1" property="title" value=" JEE "
/>
est équivalent au scriptlet :
– <% book1.setTitle(“JEE"); %>
Accès aux propriétés de Bean :
jsp:getProperty
 Format
– <jsp:getProperty name="name" property="property" />

 But
– Permettre d’accéder propriétés d’un bean (i.e., appel
de méthodes getXxx) sans programmation Java
explicite

 Remarques
– <jsp:getProperty name="book1" property="title" />

est équivalent à l’expression JSP :


– <%= book1.getTitle() %>
Exemple d’utilisation: étape 1
package serverbeans;
public class StringBean {
private String message = "No message specified";
public String getMessage() {
return(message);
}
public void setMessage(String message) {
this.message = message;
}
}
• Les Beans doivent être déployés dans le même répertoire
que les autres
classes Java
– WEB-INF/classes/serverbeans
• Les Beans doivent toujours être dans des packages !
Exemple d’utilisation: étape 2
<jsp:useBean id=“testBean" class=“serverbeans.StringBean" />

<OL>
<LI>Initial value (from jsp:getProperty):
<I><jsp:getProperty name=“testBean" property="message" /></I>
<LI>Initial value (from JSP expression):
<I><%= testBean.getMessage() %></I>
<jsp:setProperty name=“testBean" property="message" value=“Exemple d’un autre
message" />
<LI> Value after setting property with jsp:setProperty:
<I><jsp:getProperty name=“testBean" property="message" /></I>

<% stringBean.setMessage(“Mon message favoris est bonjour"); %>


<LI> Value after setting property with scriptlet:<I><%=
stringBean.getMessage()%></I>
</OL>
jsp:setProperty (cas1) :
conversion explicite & affectation (as
String)
<!DOCTYPE ...>
...
<jsp:useBean id=“monBean" class=“Ensat.Personne"
/>

<%-- setItemID expects a String --%>


<jsp:setProperty name="monBean" property=
"prénom"
value='<%= request.getParameter(“champ1") %>' />
jsp:setProperty (cas1) :
conversion explicite & affectation (type int)
<%
try {
age = Integer.parseInt(request.getParameter(“champ2"));
} catch(NumberFormatException nfe) {}
%>

<%-- setNumItems expects an int --%>

<jsp:setProperty name="monBean" property= "age" value="<%= age %>"


/>
jsp:setProperty (cas1) :
conversion explicite & affectation (type double)
<%
try {
double salaire =
Double.parseDouble(request.getParameter(“champs3"));
} catch(NumberFormatException nfe) {}
%>

<%-- setDiscountCode expects a double --%>

<jsp:setProperty name=" monBean" property=" salaire " value="<%=


salaire %>" />
jsp:setProperty (cas2) :
association propriété/paramètre
 Utilisation de l’attribut param de jsp:setProperty

– On indique que la valeur doit provenir du paramètre


de requête spécifié

– Une conversion automatique de type est opérée


pour les valeurs de types standard
boolean, Boolean, byte, Byte, char, Character, double,
Double, int, Integer,
float, Float, long, ou Long.
jsp:setProperty (cas2) :
association propriété/paramètre
<jsp:useBean id = "utilisateur" class = "Personne" />
<jsp:setProperty name = "utilisateur" property = "nom" value = "REMY" />
<jsp:setProperty name= "utilisateur" property = "prénom"
value = '<%= request.getParameter("prénom") %>' />

<jsp:useBean id = "utilisateur" class = "Personne" />


...
<jsp:setProperty name
= "utilisateur" property = "prénom" param = "prénom" />

<jsp:useBean id = "utilisateur" class = "Personne" />


...
<jsp:setProperty name = "utilisateur" property = "prénom" />
jsp:setProperty (cas3) : associer
toutes les propriétés aux paramètres
 Utilisation de "*" pour la valeur de l’attribut property de
jsp:setProperty
– On indique que la valeur doit provenir des paramètres de requête
qui correspondent aux noms des propriétés
– Un conversion automatique de type est également opérée
– Particulièrement pratique pour réaliser des « Beans formulaires »
-- objets dont les propriétés sont remplies par les données d’un
formulaire
– Ce processus peut même être décomposé entre différents
formulaires, chaque soumission remplissant une partie de l’objet

<jsp:useBean id= "monBean" class=" serverBean.Personne" />


<jsp:setProperty name="monBean" property="*" />
Implémentation du MVC avec
RequestDispatcher
1. Définir les beans pour représenter les données
2. Utiliser une servlet pour gérer les requêtes
– La servlet lit les paramètres de requêtes, vérifie les
données
manquantes ou malformées, appelle le code métier, etc.
3. Créer les beans
– La servlet invoque le code métier (spécifique à
l’application) ou
accède à une base de données pour obtenir les
résultats. Les résultats
sont dans les beans définis à l’étape 1
4. Placer le bean dans la requête, la session, ou le
servlet context
– La servlet appelle setAttribute sur la requête, la
session, ou le
Implémentation du MVC avec
RequestDispatcher
5. Transmettre la requête à la JSP (forward)
– La servlet détermine quelle JSP est appropriée à la
situation et
utilise la méthode forward du RequestDispatcher
pour
transférer le contrôle à la JSP
6. Extraire les données des beans
– JSP 1.2: la JSP accède aux beans avec
jsp:useBean et l’attribut
scope correspondant au choix de l’étape 4. La JSP
utilise
ensuite jsp:getProperty pour afficher les propriétés
des beans
– JSP 2.0: la JSP utilise
${nameFromServlet.property} pour
Utilisation de jsp:useBean : MVC
La JSP ne doit pas créer les objets
– La servlet, pas la JSP, doit créer tous les objets-
données. Donc,
pour guarantir qu’une JSP ne créera pas d’objets, il
faut utiliser
<jsp:useBean ... type="package.Class" />
au lieu de
<jsp:useBean ... class="package.Class" />

La JSP ne doit pas modifier les objets


– Il faut donc utiliser jsp:getProperty mais pas
jsp:setProperty.
Différents scopes pour jsp:useBean

 request
– <jsp:useBean id="..." type="..." scope="request" />
 session
– <jsp:useBean id="..." type="..." scope="session" />
 application
– <jsp:useBean id="..." type="..." scope="application"
/>
 page
– <jsp:useBean id="..." type="..." scope="page" />
ou juste
<jsp:useBean id="..." type="..." />
– Ce scope n’est pas utilisé dans MVC
Exemple : Partage de données sur
requête
 Servlet
ValueObject value = new ValueObject(...);
request.setAttribute("key", value);
RequestDispatcher dispatcher =
request.getRequestDispatcher("SomePage.jsp");
dispatcher.forward(request, response);
 JSP 1.2
<jsp:useBean id="key" type="somePackage.ValueObject"
scope="request" />
<jsp:getProperty name="key" property="someProperty" />
 JSP 2.0
${key.someProperty}
Partage de données sur requête :
exemple simple
 Servlet
Customer myCustomer = new
Customer(request.getParameter("customerID"));
request.setAttribute("customer", myCustomer);
RequestDispatcher dispatcher =
request.getRequestDispatcher("SomePage.jsp");
dispatcher.forward(request, response);
 JSP 1.2
<jsp:useBean id="customer" type="somePackage.Customer"
scope="request" />
<jsp:getProperty name="customer" property="firstName"/>
 JSP 2.0
${customer.firstName}
Partage de données sur session
 Servlet
ValueObject value = new ValueObject(...);
HttpSession session = request.getSession();
session.setAttribute("key", value);
RequestDispatcher dispatcher =
request.getRequestDispatcher("SomePage.jsp");
dispatcher.forward(request, response);
 JSP 1.2
<jsp:useBean id="key" type="somePackage.ValueObject"
scope="session" />
<jsp:getProperty name="key" property="someProperty" />
 JSP 2.0
${key.someProperty}