Software">
J2EE
J2EE
J2EE
h.Benlahmer@gmail.com
Le tiers du milieu Le tiers ressource
Le tiers client
(Middle tier) (EIS)
Le côté serveur
Clients
web Le tiers
Le tiers ressource
Web web
(EIS)
services
Web Services
Le tiers client
Le côté serveur
Clients
web Le tiers
Le tiers ressource
Web web
(EIS)
services
Web Services
Le tiers client
Le côté serveur
Un web browser
▪ HTTP, HTTPS / HTML, XML
Un PDA
▪ HTTP , HTTPS / WML, XML
Un client lourd (fat client), applets, apps
▪ IIOP / RMI, CORBA
▪ JRMP / RMI
▪ autres…
Un Web-service
▪ HTTP , HTTPS / ebXML (Elect. Business Exchange
Specification , SOAP (XML)
Clients
web Le tiers
Le tiers ressource
Web web
(EIS)
services
Web Services
Le tiers client
Le côté serveur
reçoit les requêtes HTTP des clients et renvoie les
réponses
permet la séparation entre présentation
(spécifique au client) et «business logic»
génère du contenu dynamiquement
transforme des requêtes HTTP dans un format
compris par l’application
contient la logique du flot de présentation
identifie la session de l’utilisateur
supporte plusieurs types de clients
Clients HTML, XML /
HTTP, HTTPS
Web
SQL,
propriétaire
Le tiers
web
Container ressource
Web Serveur
Web SOAP / HTTPS
Scripts XML, RMI /
(EIS)
services
(Fast CGI) HTTP,
IIOP,
Autres
JRMP,
JMS Le tiers du
extensions milieu
Contenu CGI
statique scripts SOAP /
Le tiers client
HTTPS
Web
Le tiers web
Services
Le côté serveur
CGI/FastCGI (Common Gateway Interface)
▪ Peut-être écrit en JAVA, C, C++, Perl...
ASP (Active Server Pages)
▪ Scripting interprété dans des pages HTML (Microsoft)
Java Servlets
▪ nécessite un conteneur Java
JSP (Java Server Pages)
▪ Scripting dans des pages HTML compilé en Servlet
PHP, Python
JavaScript (Server Side)
Clients
web Le tiers
Le tiers ressource
Web web
(EIS)
services
Web Services
Le tiers client
Le côté serveur
Gestion de composants
▪ fourni tous les services et outils pour gérer les composants du système et
l implémentation de la «business logic» comme
management de session
synchrone et asynchrone notification
Tolérance de fautes, haute disponibilité
▪ Capacité de l’application de résister à une possible panne sans point unique
de panne. Définie les polices de récupération.
▪ …
Passage à l'échelle
▪ Capacité pour le système d'accroître ses ressources matérielles pour
supporter un nombre accru d’utilisateur avec un temps de réponse constant
Balance de charge
▪ Capacité d ’envoyer une requête a différents serveurs en fonction de la
disponibilité des serveurs
Ressources pooling
▪ Protège le tiers ressource en utilisant des groupes de connections
partagées entre tous les clients
Transaction Management
▪ Une transaction est une unité indivisible de travail comprenant
plusieurs opérations, dont toutes ou aucune doivent être effectuées
pour protéger l’intégrité des données
▪ Assure les propriétés ACID des transactions (atomicité, consistance,
isolation and durabilité)
Console de management
▪ Unique point de management permettant de contrôle l’ensemble du
système incluant tous les serveurs
Sécurité
▪ Authentification
▪ Autorisation
Web Information Serveurs
A la frontière du tiers web et du tiers du milieu
Pas de transactions
Serveurs sans états
Utilise des templates et un langage de script pour
générer les pages HTML dynamiquement tout en
accédant le tiers ressource
Exemples
▪ IIS + ASP
▪ Web serveur + PHP, Python, CGI
Serveurs de composants
Permet l'accès au tiers ressource
Gère les transactions
Serveurs sans états
Sont maintenant au cœur des serveurs
d’applications
Exemples
▪ Microsoft Transaction Server (MTS, dans .net)
▪ Sybase Jaguar (dans Sybase EAServer)
▪ IBM Component broker (dans WebSphere)
Serveur d’applications
▪ Environnement complet de développement coté serveur
▪ Comprends toujours un serveur de composants
▪ Serveurs avec états
▪ Supporte «business logic» décrite à l ’aide d ’objets, de règles
et de composants
▪ Exemples
▪ Microsoft .net Enterprise Servers
▪ J2EE Serveurs : IBM WebSphere, BEA WebLogic, JBoss
▪ ORB Corba Servers : Borland VisiBroker, IONA ORBacus
▪ Notez que les serveurs d’applications Corba complet intègrent J2EE.
▪ Pour une comparaison MTS-EJB regardez
http://www.execpc.com/~gopalan/misc/ejbmts/ejbmtscomp.html
Clients
web Le tiers
Le tiers ressource
Web web
(EIS)
services
Web Services
Le tiers client
Le côté serveur
Base de données (databases)
▪ JDO, SQL/J, JDBC, ADO.NET
Source : http://www.sdmagazine.com/documents/s=733/sdm0103a/0103a.htm
.NET propose le même ensemble de
services sous l'appellation de
ServicedComponent. Le conteneur
utilisé dans le Framework est COM+
COM+ fonctionne dans un
environnement non managé avec une
gestion de type différente de celle
de .NET (Common Type System)
Source : http://www.dotnetguru.org/articles/architecturedotnet.htm
Microsoft.
J2EE différences essentielles
NET
C# a certains des JavaBeans et ajoute les metadata tags. L'intégration dans la
C#, Multi-
Langage Java syntaxe est différente. J2EE est plate-forme indépendant mais langage spécifique,
Langage
.NET est langage indépendant mais plate-forme spécifique.
Java core
Services BCL Similaire services
API
ASP.NET utilise tout les langages supportes dans .NET et est compile en code natif
Servlet
Présentation ASP.NET par le CLR. JSPs utilisent Java code (snippets, ou JavaBean références), compile en
JSP
bytecodes.
CLR permet a du code de plusieurs langages d'utiliser un ensemble de composants
Interprète CLR JVM
partages.
Win
GUI Forms Composants Web similaire ne sont pas disponible en Java. WinForms et WebForms
Swing
composants Web sont complètement intègre a VisualStudio .net
Forms
JDBC,
DB accès ADO.NET JDO, ADO.NET est construit a partir d'une architecture XML
SQL/J
.NET web services supposent un model de message base sur SOAP tandis que
WebServices oui oui
J2EE laisse le choix au developpeur.
Implicit
oui oui
middleware
Technologie Produit Standard J2EE est une specification, .NET est une strategie de produits
Java est un excellent candidat pour le
développement d’applications de bases de
données:
robuste et sécurisé
facile à comprendre
automatiquement téléchargeable par le réseau
mais avant JDBC, il était difficile d’accéder à
des bases de données SQL depuis Java :
obligé d’utiliser des API natives comme ODBC
Permettre aux programmeurs Java d’écrire
un code indépendant de la base de données
et du moyen de connectivité utilisé
Réalisé par l’API JDBC :
une interface uniforme permettant un accès
homogène aux SGBD
simple à mettre en œuvre
indépendant de la SGBD cible
supportant les fonctionnalités de base du langage
SQL
Liés a Java :
portabilité sur de nombreux O.S. et sur de
nombreuses SGBDR (Oracle, Informix,
Sybase, ..)
uniformité du langage de description des
applications, des applets et des accès aux
bases de données
liberté totale vis a vis des constructeurs
Java DataBase Connectivity (Core API 1.1)
API Java adaptée à la connexion avec les
bases de données relationnelles (SGBDR)
Fournit un ensemble de classes et
d’interfaces permettant l’utilisation sur le
réseau d’un ou plusieurs SGBDR à partir d’un
programme Java.
Tout programme comporte 3 composants :
Le code de l'application (ou de l'applet)
▪ Les requêtes doivent être au standard JDBC
Le JDBC Driver Manager
▪ Fourni par SUN
▪ Lien entre l'application et les pilotes (ou drivers) JDBC
Le driver JDBC
▪ Fourni par le fournisseur de la base ou autre
▪ Adapté à la BD
▪ Convertit les requêtes JDBC en requêtes propres à la base
4 types de drivers (taxonomie de JavaSoft) :
Type I : JDBC-ODBC bridge driver
Type II : Native-API, partly-Java driver
Type III : Net-protocol, all-Java driver
Type IV : Native-protocol, all-Java driver
Tous les drivers :
ttp://www.javasoft.com/products/jdbc/
drivers.html
Type 1 ( JDBC-ODBC bridge ) : le pont JDBC-ODBC qui s'utilise avec
ODBC et un pilote ODBC spécifique pour la base à accéder. C'est la
solution idéale pour des développements avec exécution sous Windows
d'une application locale.
inconvénients :
la multiplication du nombre de couches rend complexe l'architecture
(bien que transparent pour le développeur) et détériore un peu les
performances
lors du déploiement, ODBC et son pilote doivent être installé sur tous
les postes ou l'application va fonctionner.
la partie native (ODBC et son pilote) rend l'application moins portable
et dépendant d'une plateforme.
Type 3 : un driver écrit en Java utilisant le
protocole natif de la base de données.
Ce type de driver utilise un protocole réseau
propriétaire spécifique à une base de données. Un
serveur dédié reçoit les messages par ce protocole
et dialogue directement avec la base de données.
Ce type de driver peut être facilement utilisé par
une applet mais dans ce cas le serveur
intermédiaire doit obligatoirement être installé
sur la machine contenant le serveur web.
Type 4 : un driver Java natif
Ce type de driver, écrit en java, appelle
directement le SGBD par le réseau. Ils sont fournis
par l'éditeur de la base de données.
Avantage : tout le code est chargé sur le poste
client sous forme de classes java.
Inconvénient : La base de données reste sur le
serveur d’applets.
Une application Java peut travailler avec tous les
types de drivers
Pour une applet (untrusted) :
type I ou II : impossible
▪ une applet ne peut pas charger à distance du code natif (non
Java) sur son poste d’exécution
type III : possible
▪ si le serveur middleware se situe au même endroit que le
serveur Web (car communication par sockets avec l’applet)
type IV : possible
▪ si le SGBDR installé au même endroit que le serveur Web
2-tiers : 2 entités interviennent
1. une application Java ou une applet
2. le SGBDR
Exemple:
String url=jdbc:odbc:Mabase
La classe DriverManager dispose d’une méthode statique
permettant d’obtenir une connexion à l’URL, la méthode
getConnection() qui retourne un objet de type Connexion.
Cette méthode peut, si la connexion échoue ou si aucun
pilote ne prend en charge l’URL spécifiée, une exception de
type SQLException.
Exemple :
Import java.sql.* ;
…
try {
Connection con = DriverManager.getConnection(url,userId,password) ;
}
catch(SQLException sqle) {
System.err.println(« Erreur lors de la connexion : » + sqle) ;
}
Une transaction est un ensemble de traitements qui
sont regroupés pour être validés ou invalidés
simultanément
Par défaut une nouvelle connexion fonctionne en
validation automatique « auto-commit». Chaque
opération est validée individuellement.
Pour gérer des transactions il faut donc modifier l’état
par défaut.
public abstract void setAutoCommit(boolean autoCommit) throws
SQLException
Les transactions seront ensuite validées ou invalidées
par l’appel des méthodes commit() ou rollback().
Afin d’accéder ou de modifier les informations
contenues dans la base de données, il convient d’utiliser
un objet de type Statement.
Une instance de cet objet est retournée par la méthode
Connexion.createStatement() comme ceci :
Statement statement = con.createStatement() ;
3 types de Statement :
Statement : requêtes statiques simples
PreparedStatement : requêtes dynamiques pré-compilées
(avec paramètres d’entrée/sortie)
CallableStatement : procédures stockées
Pour une requête de type interrogation (SELECT), la
méthode à utiliser de la classe Statement est
exécuteQuery(). retourne un ResultSet (tuples
résultants) String query = "SELECT * FROM Employés";
ResultSet resultset = statement.executeQuery(query);
getInt(int) retourne le contenu de la colonne dont le numéro est passé en paramètre sous
forme d'entier.
getInt(String) retourne le contenu de la colonne dont le nom est passé en paramètre sous forme
d'entier.
getFloat(int) retourne le contenu de la colonne dont le numéro est passé en paramètre sous
forme de nombre flottant.
getFloat(String)
getDate(int) retourne le contenu de la colonne dont le numéro est passé en paramètre sous
forme de date.
getDate(String)
next() se déplace sur le prochain enregistrement : retourne false si la fin est atteinte
}
catch (Exception e) { e.printStackTrace(); }
finally { try {con.close();}
catch(SQLException e) {e.printStackTrace();}
}
} //Fin de la methode main
}//Fin du programme
import java.sql.*;
public class Connexion {
private Connection connexion;
private Statement instruction;
protected ResultSet résultat;
String DB="mabase";
public Connexion() { //constructeur
try {
Class.forName("com.mysql.jdbc.Driver");
connexion = DriverManager.getConnection("jdbc:mysql://localhost:3333/mabase", "root", "");
instruction = connexion.createStatement();
}
catch (ClassNotFoundException ex) {
System.err.println("Problème de pilote");
}
catch (SQLException ex) {
System.err.println("Base de données non trouvée ou requête incorrecte");
}
}
public void lire(String requête) { //--- }
public void miseAJour(String requête) { //--- }
public boolean suivant() { //--- }
}
import java.sql.SQLException;
}
public ListePersonne() {
lire("SELECT * FROM personne");
}
public String nom() {
try {
return résultat.getString("nom");
} catch (SQLException ex) {
return "";
}
}
public String prenom() { //-- }
while (LP.suivant()) {
System.out.println(LP.prenom());
System.out.println(LP.nom());
System.out.println(LP.email());
}
LP.arrêt();
}
Lors de l'envoi d'une requête pour exécution 4 étapes
doivent être faites :
1. analyse de la requête
2. compilation de la requête
3. optimisation de la requête
4. exécution de la requête
et ceci même si cette requête est la même que la
précédente!! Or les 3 premières étapes ont déjà été
effectuées dans ce cas.
Les bases de données définissent la notion de requête
préparée, requête où les 3 premières étapes ne sont
effectuées qu'une seule fois.
modéliser cette notion: l'interface PreparedStatement
interface dérive de l'interface Statement.
on ne peut pas avec un Statement construire
des requêtes paramétrées. Il faut pour cela
utiliser un PreparedStatement.
Syntaxe:
PreparedStatement pSmt = conX.prepareStatement("SELECT * FROM
Livres" );
ResultSet rs = pSmt.executeQuery();
Exemple :
PreparedStatement pSmt = conX.prepareStatement("SELECT
nom FROM Personnes WHERE age > ? AND adresse = ?" );
pSmt .setInt(1, 22);
pSmt .setString(2, "Turin");
setType(numéroDeLArgument, valeur)
ResultSet rs = smt.executeQuery();
L'interface CallableStatement définit les
méthodes pour un objet qui va permettre
d'appeler une procédure stockée.
Cette interface hérite de l'interface
PreparedStatement.
Un objet qui implémente l'interface
CallableStatement est obtenu en utilisant la
méthode prepareCall() d'un objet de type
Connection.
On lance l'éxécution d'une procédure stockée à
l'aide de la syntaxe :
{call nom_procedure_stockees} : cette forme la
plus simple permet l'appel d'une procédure
stockée sans paramètre ni valeur de retour
{call nom_procedure_stockees(?, ?, ...)} : cette
forme permet l'appel d'une procédure stockée
avec des paramètres·
{? = call nom_procedure_stockees(?, ?, ...)} :
cette forme permet l'appel d'une procédure
stockée avec des paramètre et une valeur de
retour·
Pour exécuter la requête, l'interface
PreparedStatement propose deux méthodes:
executeQuery() : cette méthode permet d'exécuter
une requête de type interrogation et renvoie un
objet de type ResultSet qui contient les données
issues de l'exécution de la requête·
executeUpdate() : cette méthode permet
d'exécuter une requête de type mise à jour et
renvoie un entier qui contient le nombre
d'occurrences impactées par la mise à jour·
La version 2.0 de l'API JDBC a été intégrée au JDK 1.2.
Cette nouvelle version apporte plusieurs fonctionnalités
très intéréssantes dont les principales sont :
support du parcours dans les deux sens des résultats ·
support de la mise à jour des résultats ·
possibilité de faire des mises à jour de masse (Batch Updates) ·
prise en compte des champs définis par SQL-3 dont BLOB
(BinaryLargeOBject ) et CLOB (CharacterLargeOBject)
L'API JDBC 2.0 est séparée en deux parties :
la partie principale (core API) contient les classes et interfaces
nécessaires à l'utilisation de bases de données : elles sont
regroupées dans le package java.sql·
la seconde partie est une extension utilisée dans J2EE qui
permet de gérer les transactions distribuées, les pools de
connection, la connection avec un objet DataSource ... Les
classes et interfaces sont regroupées dans le package javax.sql·
Méthode Rôle
boolean isBeforeFirst() renvoie un booleen qui indique si la position
courante du curseur se trouve avant la première ligne
boolean isAfterLast() renvoie un booleen qui indique si la position courante du
curseur se trouve après la dernière ligne
boolean isFirst() renvoie un booleen qui indique si le curseur est
positionné sur la première ligne
boolean isLast() renvoie un booleen qui indique si le curseur est
positionné sur la dernière ligne
boolean first() déplace le curseur sur la première ligne
boolean last() déplace le curseur sur la dernière ligne
boolean absolute() déplace le curseur sur la ligne dont le numéro est fournie
en paramètre à partir du début si il est positif et à
partir de la fin si il est négatif. 1 déplace sur la première
ligne, -1 sur la dernière, -2 sur l'avant dernière ...
boolean relative(int) déplace le curseur du nombre de lignes fourni en
paramètre par rapport à la position courante du
curseur. Le paramètre doit être négatif pour se déplacer vers
le début et positif pur se déplacer vers la fin. Avant
l'appel de cette méthode, il faut obligatoirement que le curseur
soit positionné sur une ligne.
boolean previous() déplace le curseur sur la ligne précédente. Le booleen
indique si la première occurrence est dépassée.
void afterLast()
déplace le curseur après la dernière ligne
void beforeFirst()
déplace le curseur avant la première ligne
int getRow()
renvoie le numéro de la ligne courante
Méthode Rôle
updateXXX(String, XXX) permet de mettre à jour la colonne dont le nom
est fourni en paramètre. Le type Java de cette colonne est XXX
updateXXX(int, XXX) permet de mettre à jour la colonne dont
l'index est fourni en paramètre. Le type Java de cette colonne est XXX
updateRow() permet d'actualiser les modifications réalisées avec
des appels à updateXXX()
boolean rowsUpdated() indique si la ligne courante a été modifiée
deleteRow() supprime la ligne courante
rowDeleted() indique si la ligne courante est supprimée
moveToInsertRow() permet de créer une nouvelle ligne dans
l'ensemble de résultat
inserRow() permet de valider la création de la ligne
La méthode getMetaData () permet d’obtenir
des informations sur les types de données du
ResultSet
elle renvoie des ResultSetMetaData
on peut connaître entre autres :
le nombre de colonne : getColumnCount()
le nom d’une colonne : getColumnName(int col)
le nom de la table : getTableName(int col)
si un NULL SQL peut être stocké dans une
colonne : isNullable()
ResultSet rs = stmt.executeQuery("SELECT *
FROM emp");
ResultSetMetaData rsmd = rs.getMetatData();
int nbColonnes = rsmd.getColumnCount();
for(int i = 1; i <= nbColonnes; i++) {
// colonnes numerotées à partir de 1 (et non 0)
String nomCol = rsmd.getColumnName(i);
}
Pour récupérer des informations sur la base de
données elle-même, utiliser la méthode
getMetaData() de l’objet Connection
dépend du SGBD avec lequel on travaille
elle renvoie des DatabaseMetaData
on peut connaître entre autres :
▪ getDriverVersion(), getDriverName(),
▪ getDatabaseProductName(), getDatabaseProductVersion()
▪ les tables de la base : getTables()
▪ le nom de l ’utilisateur : getUserName()
A démarré avec JDBC 2
Interfacé vers un containeur pour tabuler les
données
Souvent associé avec un ResultSet
Peut être n'importe quelle donnée, tableau,
fichier à plat, etc.
Étend l'interface de ResultSet
Contient un ensemble complet de propriétés
Supporte les interactions basées sur les
évènements
Il a la possibilité de se remplir lui-même avec
des données
Définition de l'emplacement de la base de
données dans une propriété principale
Peut aussi être rempli à partir d'un ResultSet
existant
Chaque classe qui implémente une RowSet
dispose d'une lecture et d'une écriture
associées :
La lecture extrait les données à partir de la source
de données pour remplir le RowSet : appliquer
l'interface RowsetReader
L'écriture extrait les données du RowSet et les
envoie dans la source de données : appliquer
RowSetWriter
Les types définis par les fournisseurs :
CachedRowSet :
Déconnecte le RowSet qui stocke ces données dans la
mémoire
Ne convient pas à des données volumineuses
Idéal pour les client java légers ou les PDA
JDBCRowSet :
Sert de fin emballage autour du ResultSet
Utilise un driver JDBC
WebRowSet :
Connecte le RowSet qui utilise le protocole HTTP
Permet une interaction avec les servlets à partir du client
léger à la manière d'un tableau
Les RowSet peuvent être utilisés de la même
manière que les ResultSet standards
Peuvent être reliés à une source de données en
permanence
Peuvent aussi être déconnectés de la source de
données
Se comportent comme source de données pour le
client (données cachées)
Peuvent être séralisés et transmis à travers le réseau
▪ Utile pour les clients légers (PDAs, les périphériques non
connectés)
Une servlet est un programme qui s'exécute
côté serveur en tant qu'extension du serveur.
La technique des CGI en Java, MAIS
Sans créer de processus + toute la puissance de
Java (accès aux divers domaines de l'informatique:
BD, multimédia, réseau, objets distribués,
composants, etc.)
+ indépendance de la plate-forme et du serveur
Servlets
Scripts serveur écrit en Java
Servlets de Base : FileServlet, CGIServlet, …
HttpServlet
Exécution dans un espace isolé (Web Application)
Spécification : Sun (sous partie de J2EE)
Implémentation de référence : Apache Group
(Jakarta Tomcat)
Différence avec les CGI et les LD (NSAPI, ISAPI)
performance sur les passages des paramêtres (vs CGI)
sûreté de fonctionnement (NSAPI, ISAPI)
Pour exécuter des servlets, il faut un moteur
de servlets dans le serveur Web.
Ces moteurs sont des plug-in pour des serveurs
Web existants
ou bien des serveurs Web aux mêmes
Plug-in : deux candidats : Jrun (www.allaire.com),
tomcat (jakarta.apache.org)
Utilise deux paquetages :
javax.servlet : paquetage générique
javax.servlet.http : paquetage pour serveurs Web
Ces paquetages ne sont pas dans J2SE 1.3
Sont des paquetages supplémentaires.
Il sont aussi intégrés dans J2EE voir à
http://java.sun.com/j2ee/
import java. io.*;
import javax. servlet.*;
import javax. servlet. http.*;
public class HelloServlet extends HttpServlet {
public void doGet( HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res. setContentType(" text html"); //Set the Content- Type header
PrintWriter out = res. getWriter(); // Get the output
String pname = req. getParameter(" name"); //Get a parameter
if( pname== null) pname=" World !";
out. println("< HTM >");
out. println("< HEAD>< TIT E> Hello, " + pname + "< TIT E>< HEAD>");
out. println("< BODY>");
out. println(" Hello, " + pname);
out. println("< BODY>< HTM >");
out. flush();
}
public void doPost( HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException { doGet( req, res); }
}
L'API servlet regroupe un ensemble de
classes dans deux packages :
javax.servlet : contient les classes pour développer
des serlvets génériques indépendantes d'un
protocole.
javax.servlet.http : contient les classes pour
développer des servlets qui reposent sur le
protocole http utilisé par les serveurs web.
javax.servlet Nom Role
Enumeration liste
=req.getParameterNames();
String [] valeurs = req.getParameterValues();
String val1 = req.getParameter(''param1'');
<HTML>
<HEAD><TITLE> ANNUAIRE Mastere </TITLE></HEAD>
<BODY BGCOLOR="#FFFFFF"<CENTER>
<CENTER><H1>ANNUAIRE DU DESS TIIR </H1></CENTER>
<HR><CENTER>
<H2>Recherche de coordonnées </H2></CENTER>
<P> Tapez le début du nom de la personne recherchée:
<P><FORM METHOD=POST
ACTION=http://localhost:8080/examples/servlets/annuaire
method=post>
<INPUT TYPE=TEXT NAME="nom" SIZE=20 MAXLENGTH=30
VALUE="">
<P><INPUT TYPE=SUBMIT NAME="go" VALUE="RECHERCHER">
<INPUT TYPE=RESET NAME="reset" VALUE="ANNULER">
</FORM>
</BODY></HTML>
import java.io.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Annuaire extends HttpServlet{
public void doPost( HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException{
res.setContType("text/html");
PrintWriter out=res.getWriter();
out.println("<HEAD><TITLE>Réponse annuaire </TITLE></HEAD><BODY>");
out.println("<HR>");
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
String url ="jdbc:odbc:mabase";
java.sql.Connection c=DriverManager.getConnection(url,"","");
java.sql.Statement st = c.createStatement();
java.sql.ResultSet rs =
st.executeQuery("Select * from matable where nom like '"
+req.getParameter("nom"+"*'"));
rs.next();
out.println(rs.getString("prenom")+" "+rs.getString("nom") );
}
catch (SQLException e){
out.println("Cette personne n'existe pas");
}
out.println("<P><A href = annuaire.html> Retour</A>"</P>);
out.println("</BODY>");
out.close();
}
public String getServletInfo(){
return "Servlet Annuaire";
}
Ajout de cookies à l ’entête de la réponse
void HttpServletResponse.
addCookie( Cookie cookie)
Le cookie peut être un cookie récupéré dans la
requête
Et modifié avant d’être ajouté à la réponse
Garder la mémoire des informations d'une page à l'autre :
Utiliser les cookies (sécurité!)
Syntaxe CGI : paramètres dans l'URL
Champs ``HIDDEN'' de formulaires
<INPUT TYPE=''HIDDEN'' NAME=''PARAM1''VALUE=''VAL1''>
Objet HttpSession
HttpSession session=request.getSession(true);
Classe objet = (Classe) session.getValue(''param1'');
Méthodes : getValue(), putValue(), removeValue()
HttpSession session = req.getSession(true);
If (session.isNew()){
session.putValue('‘toto'', new int[] {0});
}
Int[] toto = (int[]) session.getValue('‘toto'');
Le serveur maintient une session de 2 manières :
Cookie (Name: SESSIONID Value: To1010mC8601021835741167At)
▪ les cookies peuvent être désactivés sur le navigateur
Réécriture des URLs
Ouverture/récupération d ’une session
javax. servlet. http. HttpSession session = req. getSession( false);
// la session est récupérée ou null si elle n ’existait pas déjà
javax. servlet. http. HttpSession session = req. getSession( true);
//la session est récupérée ou ouverte si elle n ’existait pas déjà
Invalidation d ’une session
javax. servlet. http. HttpSession session = req. getSession( false);
session. invalidate(); la session est invalidée ( i. e. fermée)
javax. servlet. http. HttpSession session = req. getSession( false);
L ’identifiant
String sessionid= session. getId(); // par exemple: To1010mC8601021835741167At
La date de création
long datecreation= session. getCreationTime(); // nb de ms depu s 1/ 1/ 1970: 00: 00
La date du dernier accès
long datelastaccess= session. get astAccessedTime();
Exemple
HttpSession session = req. getSession( true);
if( session. get astAccessedTime() - session. getCreationTime() > 5* 60* 1000 ) {
session. invalidate();
}
javax. servlet. http. HttpSession session = req. getSession( false);
Méthode de suivi de session
boolean HttpServletRequest. isRequestedSessionIdFromCookie()
// test si le suivi de session utilise un cookie
boolean HttpServletRequest. isRequestedSessionIdFromUR ()
// test si le suivi de session utilise la réécriture d ’UR
Réécriture des URL (cas isRequestedSessionIdFromURL )
les URL générées doivent être encodées pour intégrer le suivi de session
String HttpServletResponse. encodeRedirectUR (String url)
String HttpServletResponse. encodeUR (String url)
Exemple
res. sendRedirect( res. encodeRedirectUR (" servlet login");
javax. servlet. http. HttpSession session = req.
getSession( true);
Ajout/remplacement d ’une valeur
void HttpSession. setAttribute( String name, Object value)
Suppression d ’une valeur
void HttpSession. removeAttribute( String name)
Récupération des valeurs/d ’une valeur
String[] HttpSession. getAttributeNames()
Object HttpSession. getAttribute( String name)
import mycybermarket. Cart; …
public void doGet( HttpServletRequest req, HttpServletResponse
res) … {
Cart cart;
HttpSession session = req. getSession( true);
if(( cart=( Cart) session. getAttribute(" CART"))!= null) {
cart= CartFactory. create(); // new rt( ... ); ou = c rtHome. cre te();
session. setAttribute("CART", cart);
} ...
...
if( action. equals(" exit") {
cart. releaseProducts();
session. removeAttribute(" CART");
}
...
Motivations
réagir face à des événements intervenants dans la/les sessions
4 interfaces Listeners
HttpSessionActivationListener
la session peut être passivée puis réactivée
HttpSessionListener
changement sur la liste des sessions actives de l'application Web.
HttpSessionAttributeListener
changement sur les attributs d’une des sessions de l’application
Web.
HttpSessionBindingListener
un objet peut être notifié de sa liaison rupture à un session
HttpSessionActivationListener
la session peut être passivée puis réactivée
void sessionDidActivate( HttpSessionEvent se)
void sessionWillPassivate( HttpSessionEvent se)
HttpSessionListener
changement sur la liste des sessions actives de l'application Web.
void sessionCreated( HttpSessionEvent se)
Void sessionDestroyed( HttpSessionEvent se) invalidation
HttpSessionAttributeListener
attribute lists of sessions within this web application.
void attributeAdded( HttpSessionBindingEvent se)
void attributeRemoved( HttpSessionBindingEvent se)
void attributeReplaced( HttpSessionBindingEvent se)
HttpSessionBindingListener
un objet peut être notifié de sa liaison rupture à un session
void valueBound( HttpSessionBindingEvent event)
void valueUnbound( HttpSessionBindingEvent event)
Motivations
faire réagir les objets liés aux liaisons et « déliaisons »
fermer des fichiers, des connexions, valider des transactions, ...
API
interface HttpSessionBinding istener
public void valueBound( HttpSessionBindingEvent event)
public void valueUnbound( HttpSessionBindingEvent
event)
class HttpSessionBindingEvent extends EventObject
public Session getSession() la session concernée
public String getName() le nom de la liaison
Principe
l ’objet lié doit implanté HttpSessionBinding istener
valueBound () est invoqué quand l ’objet est lié ( putValue ())
valueUnbound () est invoqué quand la session est invalidé ou expire ou
quand l ’objet est délié ( setAttribute ()/ removeAttribute ()).
class CartBinding istener implements HttpSessionBindingListener {
rt c rt= null;
public CartBinding istener( ... ) { this. cart = new Cart( ... ); }
public void valueBound( HttpSessionBindingEvent event) {}
public void valueUnbound( HttpSessionBindingEvent event) {
cart. releaseProducts();}
public void doGet( HttpServletRequest req, HttpServletResponse res) {
CartBinding istener cart;
HttpSession session = req. getSession( true);
CartBinding istener cart=( Cart) session. getValue(" CART");
if( cart== null) { cart= new CartBinding istener( ... );
session. setAttribute(" CART", cart); // v lueBound est invoqué sur l ’objet
lié
}…
session. removeAttribute (" CART"); // v lueUnbound est invoqué sur l ’objet
lié
Motivation
partager une information commune entre
servlets, ...
Plusieurs
S1 : utilisez les Properties de java. lang. System
S2 : classe commune avec des membres statiques
S3 : utilisez le contexte de l’application
Solution 1 : utilise les Properties de java. lang. System
String java. lang. System. getProperty( String key)
String java. lang. System. setProperty( String key,
String value)
Remarque : les Properties sont partagées par toutes les
WebApps du serveur J2EE
Solution 2 : classe commune avec des membres statiques
l ’initialisation des membres statiques XXX peut se faire au
moment du premier accès par une des servlets
Remarque pour une meilleure programmation
les membres statiques sont privés et sont accédés par des
méthodes statiques setXXX() et getXXX()
la classe n ’est accessible que par les servlets du même package
et chargée par le même ClassLoader (un par WebApp)
Solution 3 : utiliser les <env- entry> du contexte JNDI de
l’application
Paires typées (name, value, classname) appartenant au
contexte de l’application Web
<env- entry>
<env- entry- name> defaultCurrency< env- entry- name>
<env- entry- value> EUR< env- entry- value>
<env- entry- type> java. lang. String< env- entry- type>
< env- entry>
<env- entry>
<env- entry- name> default anguage< env- entry- name>
<env- entry- value> 33< env- entry- value>
<env- entry- type> java. lang. Integer< env- entry- type>
< env- entry>
Récupération des <env- entry> via JNDI
Context ctx = new InitialContext();
Object value = ctx. lookup(" java: comp env defaultCurrency");
out. println(" Default currency value : " + value);
Context envCtx = ( Context) ctx. lookup(" java: comp env ");
NamingEnumeration enum = ctx. list(" java: comp env ");
while (enum. hasMoreElements()) {
out. print(" Binding : "+ ( enum. nextElement(). toString());
}
NamingEnumeration enumbinding = envCtx. listBindings(" java:
comp env ");
while (enumbinding. hasMoreElements()) {
out. print(" Binding : "+( enumbinding. nextElement(). toString());
Authentification
• Système :
HttpServletRequest. getAuthType(), HttpServletRequest. getRemoteUser()
▪ HTTP - BASIC ou DIGEST challenge
WWW-Authenticate
▪ SSL 3.0 authentifie le client
Custom
▪ utilise des servlets vérifiant l’identité de l ’utilisateur avec des moyens
externes au serveur (annuaire LDAP, BD, GSM, …)
Autres
java. security. Principal HttpServletRequest. getUserPrincipal()
//identité de l ’utilisateur dans le schéma général sécurité de
java
boolean HttpServletRequest. isUserInRole( String role)
//test si l ’utilisateur appartient à un role (i. e. classe d
’utilisateur)
Redirige la traitement de la requête vers une
autre servlet ou JSP
Utilisé pour le MVC
Exemple
public class ForwardServlet extends HttpServlet {
public void doGet (HttpServletRequest request,
HttpServletResponse response) {
//Set the attribute and forward to hello. jsp
request. setAttribute (" action", " hello");
ServletContext context= getServletConfig(). getServletContext().
context. getRequestDispatcher(" hello. jsp"). forward( request,
response);
}
}
Server Side Script
Insertion de SSS (syntaxe Java) dans les pages HTML
Avantage par rapport aux servlets
Ecriture moins verbeuse Orientée Web Designer
Insérable par des outils auteurs dans le code de pages
HTML
Extensible grâce aux JSTL
Spécification
JSR-52
JSR-152 JavaServer Pages 2.0 Specification
Implémentations
J2EESDK et Jakarta JASPER/TomCat
ASP est une technologie comparable à JSP développé par
Microsoft. Cependant, deux avantages sont dégagés par
JSP. Premièrement, les parties dynamiques sont
développées en JAVA et non en VisualBasic ou d’autres
langages spécifiques à Microsoft donc plus performantes
et faciles à utiliser. Deuxièmement, JSP est compatible
avec d’autres systèmes d’exploitation et serveurs web
développés par d’autres compagnies que Microsoft.
JavaScript peut générer dynamiquement du HTML sur le
côté client. Cette une fonctionnalité très utile mais elle
gère les situations où les informations se trouvent sur le
côté client seulement. De plus, le fait que les programmes
JavaScript s’exécutent sur le côté client, ils ne peuvent
accéder aux ressources situées sur le côté serveur comme
une base de données, un catalogue d’information, etc.
Directives
<%@page import="java.util.*" %>
<%@taglib prefix="c" uri="WEB-INF/tld/core.tld" %>
Éléments de script
Scriplets <% code java %>
Déclarations <%! Déclarations %>
Expressions <%= expression %>
TagLib
<jsp:forward page="forward.jsp" />
<jsp:include page="result.jsp" />
<c:if test="${applicationScope:booklist == null}" >
<c:import url="/books.xml" var="xml" />
<x:parse xml="${xml}" var="booklist" scope="application" />
</c:if>
<HTML >
<HEAD>< TITLE> Hello< TITLE>< HEAD>
<BODY>
<H1> Salut
<%
String pname; //déclaration de variable
pname = request. getParameter(" name"); // request :
objet implicite
if ( pname== null) { out. println(" World"); } else {
%>
Mr <%= pname%>
<% } // fin du else %>
< H1>
< BODY>< HTML >
<%@ method = " doPost" %>
<HTM >
<HEAD>< TITLE> Hello< TITLE>< HEAD>
<BODY>
<H1> Hello
<%
String pname; //déclaration de variable
pname = request. getParameter(" name"); //request : objet
implicite
if ( pname== null) { out. println(" World"); } else {
%>
Mr <%= pname%>
<% } // fin du else %>
< H1>
< BODY>< HTML >
<html>
<jsp: useBean id=" cart" scope=" session" class=" mycybermarket.
MyCart" >
<jsp: setProperty name=" cart" property="*" >
<%
cart. processRequest( request);
%>
<br> You have the following items in your cart:
<ol>
<% String[] items = cart. getItems();
for ( int i= 0; i< items. length; i++) { %>
<li> <%= items[ i] %>
<% } %>
< ol>< hr>
<%@ include file =" catalog. html" %>
< html>
Compilation des JSP en classes Java
génération et compilation d ’une classe étendant
HttpJspBase à la première invocation.
Au runtime
la servlet JspServlet invoque le compilateur
Jasper puis charge et exécute la méthode
_jspService de la classe HttpJspBase générée
Avant déploiement
Les JSP peuvent être aussi générées avant le
déploiement (tâche <jspc>)
Cette action vous permet de rediriger une
requête vers une autre page.
Syntaxe:
<jsp:forward page="{relativeURL | <%= expression %>}" />
ou
<jsp:forward page="{relativeURL | <%= expression %>}" >
<jsp:param name="parameterName"
value="{ parameterValue | <%= expression %>}" /> +
</jsp:forward>
Comme vu précédemment, l’action include vous permet
d’insérer un fichier pendant que le servlet est généré à
partir du fichier JSP.