6. Interactions Homme
Transcription
6. Interactions Homme
6. Interactions HommeMachine Olivier Curé UMLV [page 170 ] Introduction ● ● ● Les programmes informatiques nécessitent des interactions avec les utilisateurs : questionner, saisir et afficher. Cette interaction (homme-machine – IHM) peut s'effectuer en mode console ou graphique. Cette partie du cours porte sur les GUI (Graphical User Interface) en Java. Olivier Curé UMLV [page 171 ] IHM ● Utilisabilité : ● Accessibilité : proposer efficacement et garantir la facilité d'apprentissage pour l'utilisateur de manipuler ses entrées et interpréter les sorties. naturellement l'accès à différentes fonctionnalités. ● Approprié : ● Versatilité : garantir une réponse appropriée et pertinente aux différentes situations rencontrées. garantir une utilisation optimale dans différents contextes et situations. Olivier Curé UMLV [page 172 ] IHM et programmation ● Eléments graphiques ● ● Fenêtre, bouton, zones de texte et saisie, menu, liste, etc.. Programmation événementielle ● Écouteurs - listeners ● Écoutés – handleEvent Olivier Curé UMLV [page 173 ] Modèle Vue Contrôleur (MVC) ● ● ● Le modèle représente les données de l'application. La vue représente visuellement les données. Le contrôleur gère l'interaction utilisateur avec le modèle. Olivier Curé UMLV [page 174 ] MVC (suite) ● ● ● Le modèle contient les données et gère la miseà-jour et le renseignement des données. La vue affiche les composants et les données. Elle gère la mise-à-jour (graphique, textuelle), la notification des modifications au contrôleur et le renseignement. Le contrôleur écoute les actions produites dans la vue et récupère des informations de la vue, met à jour le modèle, récupère les nouvelles données de la vue pour les transmettre à la vue. Olivier Curé UMLV [page 175 ] MVC (fin) ● Avantages : – Séparation entre les données et la présentation. – Données stockées à un endroit connu. – Modifications plus faciles Olivier Curé UMLV [page 176 ] GUI et Java ● ● Trois toolkits pour les GUI en Java : – AWT (Abstract Windowing Toolkit) – Swing – SWT (Standard Widget Toolkit) Les programmes de GUI sont dirigés par événements. Olivier Curé UMLV [page 177 ] Toolkits GUI Java ● ● ● ● AWT, développé par SUN et présent depuis le JDK 1.0. Swing, développé par SUN et présent depuis le JDK 1.2. SWT, développé par IBM et présent depuis JDK 1.2. Le cours porte essentiellement sur Swing et un peu sur AWT. Olivier Curé UMLV [page 178 ] Swing ● ● ● Swing est construit au-dessus de AWT : la gestion des événements est identique et les classes Swing héritent de AWT. Les composants Swing ont un nom qui débute par un "J". Swing offre une palette bien plus large, plus élaborée fonctionnellement et esthétiquement mais est plus lent et plus lourd que AWT. Olivier Curé UMLV [page 179 ] Composant et Container ● AWT et Swing utilisent des classes différentes pour représenter chaque composant graphique. ● Pour AWT : Component ● Pour Swing : JComponent ● Container : un composant contenant des composants. Olivier Curé UMLV [page 180 ] Composant et Container Attention : Tout JComponent est un Container ! Olivier Curé UMLV [page 181 ] Composants Swing ● 3 types de composants : – Les composants lourds qui correspondent à des fenêtres de la plateforme : JFrame, JDialog, JWindow, JApplet. – Les composants légers sont du code "pur Java" qui les dessinent : JButton , JTextfield, JLabel, etc.. La plupart correspondent à des sous-classes de la classe JComponent. – les conteneurs intermédiaires : JPanel, JScrollPane, JTabbedPane, etc.. Olivier Curé UMLV [page 182 ] Look and Feel ● ● Avec Swing, il est possible de modifier l'aspect graphique (look and feel) d'un ensemble de composants. Des exemples : – Windows (com.sun.java.swing.plaf.windows.WindowsLookAndFeel). – Motif (com.sun.java.swing.plaf.motif.MotifLookAndFeel). – Metal (javax.swing.plaf.metal.MetalLookAndFeel). – GTK (com.sun.java.swing.plaf.gtk.GTKLookAndFeel). Olivier Curé UMLV [page 183 ] Exemple JFrame import javax.swing.*; import java.awt.*; import java.awt.event.*; class FrameTd1 extends JFrame { public FrameTd1() { setTitle("Ma JFrame"); setSize(200,200); addWindowListener(new WindowAdapter() public void windowClosing(WindowEv { System.exit(0); } }); } } public class FrameTd1Test { public static void main(String args[]) { JFrame frame1 = new FrameTd1(); frame1.show(); } Olivier Curé UMLV [page 184 ] } Exemple 2 JFrame import javax.swing.*; import java.awt.*; import java.awt.event.*; public class FrameTd2Test { public static void main(String args[]) { JFrame frame2 = new FrameTd1(); Container contentPane2 = frame2.getContentPane(); JButton jb1 = new JButton("Bouton #1"); jb1.setBackground(Color.red); contentPane2.add(jb1); frame2.show(); JFrame frame21 = new FrameTd1(); Container contentPane21 = frame21.getContentPane(); JLabel jl1 = new JLabel("Un label dans le second cadre"); contentPane21.add(jl1); frame21.show(); } } Olivier Curé UMLV [page 185 ] Layout manager ● ● ● Le placement des composants est réalisé à l'aide de layout manager et non au pixel près. Utilisabilité pour l'agrandissement/réduction de composants lourds. Un layout manager est associé au container. Olivier Curé UMLV [page 186 ] Layout (2) ● ● Un layout manager utilise les tailles d'un composants pour les placer dans son container, les méthodes sont : – getPreferredSize() – getMaximalSize() – getMinimalSize() La méthode pack() de JFrame redimensionne sa taille en fonction de la taille préférée de chacun des container. Olivier Curé UMLV [page 187 ] Layout (3) ● On peut redimmensionner un composant : – setSize(largeur, hauteur) – setPreferredSize(dimension) Olivier Curé UMLV [page 188 ] Layout (4) ● 2 types de layout : – sans contrainte : FlowLayout, GridLayout et BoxLayout. – avec contraintes : BorderLayout et GridBagLayout. Olivier Curé UMLV [page 189 ] FlowLayout ● ● Affiche les composants de la gauche vers la droite en passant à la ligne s'il n'y a plus de place. La disposition est recalculée après chaque redimensionnement. Olivier Curé UMLV [page 190 ] GridLayout ● Affiche les composants sur une grille, ligne par ligne et les cellules ont toutes la même taille. GridLayout (int li, int co, int hgap, int vgap); ● Respectivement le nombre de lignes, colonnes et distances horizontale et verticale (nulles par défaut). ● Si li=0, le nombre de lignes est ignoré. ● Si li > 0, co est ignoré. Olivier Curé UMLV [page 191 ] GridLayout ● Affiche les composants sur une grille, ligne par ligne et les cellules ont toutes la même taille. GridLayout (int li, int co, int hgap, int vgap); Olivier Curé UMLV [page 192 ] GridLayout ● Respectivement le nombre de lignes, colonnes et distances horizontale et verticale (nulles par défaut). ● Si li=0, le nombre de lignes est ignoré. ● Si li > 0, co est ignoré. Olivier Curé UMLV [page 193 ] BorderLayout ● Affiche les composants dans 5 zones (nord, sud, est, ouest et centre) où 'nord' et 'sud' occupent toute la largeur; 'est' et 'ouest' occupent la hauteur restante. Olivier Curé UMLV [page 194 ] BoxLayout ● Exemple, BoxLayout (horizontal) correspond à des cellules de même hauteur mais de largeur variable. Olivier Curé UMLV [page 195 ] GridBagLayout ● Affiche les composants dans une grille selon un ensemble de contraintes (exprimé par la classe GridBagConstraints) : – La zone réservée de la grille. – La place occupée dans cette zone. Olivier Curé UMLV [page 196 ] Layout (5) ● ● JPanel utilise par défaut un FlowLayout. JFrame utilise par défaut un BorderLayout. Olivier Curé UMLV [page 197 ] Exemple 3 JFrame import javax.swing.*; import java.awt.*; import java.awt.event.*; public class FrameTd3Test { public static void main(String args[]) { JFrame frame3 = new FrameTd1(); Container contentPane3 = frame3.getContentPane(); contentPane3.setLayout (new java.awt.GridLayout (2, 2)); /* GridLayout avec 2 lignes et 2 colonnes */ JButton jb1 = new JButton("Bouton #1"); jb1.setBackground(Color.red); JButton jb2 = new JButton("Bouton #2"); jb2.setBackground(Color.green); JLabel jl1 = new JLabel("Un label en bas"); contentPane3.add(jb1); contentPane3.add(jb2); contentPane3.add(jl1); frame3.setLocation(300,300); frame3.show(); } } Olivier Curé UMLV [page 198 ] Evénements ● ● ● ● L'utilisateur utilise le clavier et la souris pour interagir sur le déroulement du programme. Le programme doit lier des traitements aux actions de l'utilisateur. On distingue les événements de "bas niveau", actions élémentaires de l'utilisateur, et les événements de "haut niveau", qui correspondent à une action logique de l'utilisateur. Un exemple, la frappe d'un "A": – en bas niveau ; 4 evts : appui sur shift, appui sur a, relachement de a et relachement de shift. – en haut niveau ; 1 evt : frappe de "A". Olivier Curé UMLV [page 199 ] La classe ActionEvent ● ● ● Cette classe décrit des événements de haut niveau très utilisés qui correspondent à un type d'action de l'utilisateur qui va déclencher un traitement. C'est le cas, pour : le clic d'un bouton, la frappe de la touche return dans une zone de texte, ● un choix dans un menu, ● un double clic dans une liste. Olivier Curé UMLV [page 200 ] Comment utiliser les listeners ● Pour enregistrer un listener, il faut instancier une classe implémentant une certaine interface. Olivier Curé UMLV [page 201 ] import javax.swing.*; import java.awt.*; import java.awt.event.*; class FrameTd4 extends JFrame implements ActionListener { JButton jb1; JLabel jl1; public FrameTd4() { setTitle("Ma JFrame avec des evenements"); setSize(200,200); Container contentPane = this.getContentPane(); contentPane.setLayout (new java.awt.GridLayout (2, 2)); jb1 = new JButton("Mon bouton avec evt"); jb1.addActionListener(this); jb1.setBackground(Color.yellow); jl1 = new JLabel("Pas de message"); contentPane.add(jb1); contentPane.add(jl1); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); }}); } public void actionPerformed(ActionEvent evt) { jl1.setText("Un clic sur bouton #1"); } } public class FrameTd4Test { public static void main(String args[]) { JFrame frame1 = new FrameTd4(); frame1.show(); } } Ex. 4 JFrame Olivier Curé UMLV [page 202 ] JPanel ● ● Sert à regrouper des composants dans une zone écran. Ne possède pas d'aspect visuel déterminé; son aspect visuel est conditionné par ses composants. Olivier Curé UMLV [page 203 ] Plug-in VE Olivier Curé UMLV [page 204 ] 8. Java et les bases de données Olivier Curé UMLV [page 205 ] ODBC ● ● ● ● ● Open DataBase Connectivity. Une API standard pour l'accès aux bases de données. En utilisant des instructions ODBC dans un programme, on peut accéder à de nombreux SGBD. Permet au programme l'exploitation de SQL. ODBC gère une requête SQL et transforme celleci dans un format compréhensible par le SGBD. Olivier Curé UMLV [page 206 ] JDBC ● ● Java DataBase Connectivity. Une API Java pour connecter des programmes java à des SGBD. ● Un ensemble de classes et interfaces java. ● JDBC va permettre – D'établir une connexion à la BD. – D'envoyer des requêtes SQL. – De récupérer les résultats des requêtes. Olivier Curé UMLV [page 207 ] JDBC (2) ● ● Il faut charger un driver pour le SGBD. Il est possible d'utiliser l'interface JDBC pour accéder aux BD accessibles via ODBC => "pont" JDBC-ODBC. Olivier Curé UMLV [page 208 ] JDBC (3) ● Etapes : – Importer le package (import java.sql.*;). – Faire connaître le pilote JDBC du SGBD – Ouvrir une connexion à la BD. – Créer un objet 'Statement'. – Exécuter une requête et obtenir un objet ResultSet. – Fermer les objets ResultSet et Statement. – Fermer la connexion à la BD. Olivier Curé UMLV [page 209 ] Pilote JDBC ● ● Le pilote JDBC est un composant logiciel qui satisfait aux spécifications JDBC établies par Sun. Ce pilote est spécifique à un fabriquant de base de donnée. On trouvera par exemple un pilote pour les bases de données Oracle, un pilote pour la base MySQL. On traite dans ce cours du SGBDR MySQL. Ce pilote est une classe Java qui implémente l’interface java.sql.Driver. Pour le driver MySQL, cette classe est : com.mysql.jdbc.Driver. Nous devons donc charger cette classe. Pour cela, la méthode Class.forName() est généralement utilisée (cf. Page suivante). Olivier Curé UMLV [page 210 ] Chargement du pilote ● Il convient d'importer le package java.sql import java.sql.*; public class QueryExample { ... try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { System.err.println("Driver loading error : " + e); } ... } Olivier Curé UMLV [page 211 ] URL de connection ● ● ● Afin de localiser la base de donnée sur le serveur de base de donnée, il est indispensable de spécifier une adresse de connexion sous la forme d'une URL. Ces URL commenceront toutes par "jdbc:". Généralement, il faudra se référer à la documentation du fournisseur du driver afin de connaître le format de l'URL à utiliser. Pour MySQL, l'URL est la suivante : jdbc:mysql://host:port/database. ● Host : correspond à l'adresse IP du serveur. ● port : port MySQL ou port par défaut. ● Database : le nom de la base de donnée à laquelle on doit se connecter. Olivier Curé UMLV [page 212 ] Etablir une connexion ● Etablir une connexion en utilisant la classe java.sql.DriverManager. Son rôle est de créer des connexions en utilisant le driver préalablement chargé. Cette classe dispose d'une méthode statique getConnection() prenant en paramètre l'URL de connexion, le nom d'utilisateur et le mot de passe. String url = "jdbc:mysql://localhost/tp"; try { Connection connection = DriverManager.getConnection(url, "root", "secret"); } catch (SQLException e) { System.err.println("Error opening SQL connection: " + e.getMessage()); } Olivier Curé UMLV [page 213 ] Les requêtes ● Afin d'exécuter des requêtes, il convient d'utiliser un object Statement. Une instance de cet objet est retourné par un appel à la méthode Connection.createStatement() : try { Statement statement = connection.createStatement(); } catch (SQLException e) { System.err.println("Error creating SQL statement: " + e.getMessage()); } Olivier Curé UMLV [page 214 ] Les requêtes (2) ● Il existe deux types de requêtes : – des requêtes de sélection (SELECT), accessibles par la méthode Statement.executeQuery(). Cette méthode retourne un résultat de type java.sql.ResultSet contenant les lignes sélectionnées. – des requêtes de modification (UPDATE), d'insertion (INSERT) ou de suppression (DELETE), accessibles par la méthode Statement.executeUpdate(). Cette méthode retourne un résultat de type int correspondant au nombre de lignes affectées par la requête. Olivier Curé UMLV [page 215 ] Les requêtes (3) String query = "SELECT name,email FROM users;"; try { ResultSet resultSet = statement.executeQuery(query); } catch (SQLException e) { System.err.println("Error executing query: " + e.getMessage()); } String query = "UPDATE users SET email='[email protected]' WHERE name='JOHN SMITH';"; try { int result = statement.executeUpdate(query); } catch (SQLException e) { System.err.println("Error executing query: " + e.getMessage()); } Olivier Curé UMLV [page 216 ] Traitement des résultats ● L'objet ResultSet permet d'avoir un accès aux données résultantes de notre requête en mode ligne par ligne. La méthode ResultSet.next() permet de passer d'une ligne à la suivante. Cette méthode renvoie false dans le cas où il n'y a pas de ligne suivante. Il est nécessaire d'appeler au moins une fois cette méthode, le curseur est placé au départ avant la première ligne (si elle existe). Olivier Curé UMLV [page 217 ] Traitement des résultats (2) ● ● ● La classe ResultSet dispose aussi d'un certain nombres d'accesseurs (ResultSet.getXXX()) qui permettent de récupérer le résultat contenu dans une colonne sélectionnée. On peut utiliser soit le numéro de la colonne désirée, soit son nom avec l'accesseur. La numérotation des colonnes commence à 1. XXX correspond au type de la colonne. Le tableau suivant précise les relations entre type SQL, type JDBC et méthode à appeler sur l'objet ResultSet. Olivier Curé UMLV [page 218 ] Les types Type SQL Type JDBC Méthode d'accès char String getString() varchar String getString() integer Integer getInt() double, Double getDouble() float Float getDouble() Date Date getDate() Blob Blob getBlob() Olivier Curé UMLV [page 219 ] Exemple try { while (rs.next()) { System.out.println(rs.getString("NAME") + " – " + rs.getString("EMAIL")); } } catch (SQLException e) { System.err.println("Error browsing query results: " + e.getMessage()); } Olivier Curé UMLV [page 220 ] Fermeture de la connexion ● Objectif : Libérer les ressources try { resultSet.close(); connection.close(); } catch (SQLException e) { System.err.println("Error closing connection: " + e.getMessage()); } Olivier Curé UMLV [page 221 ] Exemple 'SELECT' import java.sql.*; public class Query1 { public Query1() { String url = "jdbc:mysql://localhost:3306/film"; // film est le nom de la base de donne'es Connection con; String query = "SELECT director,nat from director;"; Statement stmt; try { Driver mySQLDriver = new org.gjt.mm.mysql.Driver(); con = DriverManager.getConnection(url,"o" ,"ol" ); System.out.println("Con = " + con); stmt = con.createStatement(); Olivier Curé UMLV [page 222 ] Exemple 'SELECT' (2) ResultSet rs = stmt.executeQuery(query); while (rs.next()) { System.out.println(rs.getString(1)+" ("+rs.getString(2)+")"); } stmt.close(); con.close(); } catch(SQLException ex) { System.err.println("SQLException: " + ex.getMessage()); } } public static void main(String args[]) { Query1 query1 = new Query1(); } } Olivier Curé UMLV [page 223 ] Instruction SQL paramétrée ● ● ● La plupart des SGBD (dont Oracle) ne peuvent analyser qu'une seule fois une requête exécutée un grand nombre de fois JDBC permet de profiter de ce type de fonctionnalité par l'utilisation de requêtes paramétrées ou de procédures stockées. Les requêtes paramétrées sont associées aux instances de l'interface PreparedStatement qui hérite de l'interface Statement Olivier Curé UMLV [page 224 ] Création d'une requête paramétrée PreparedStatement pstmt = conn.preparedStatement("UPDATE emp SET sal=? WHERE nom=?;"); ● ● ● ● Les '?' indiquent les emplacements des paramètres. Les valeurs des paramètres sont données par les méthodes setXXX(n,valeur). On choisit la méthode setXXX suivant le type SQL de la valeur que l'on veut mettre dans la requête. C'est au développeur de passer une valeur Java cohérente avec le type. Olivier Curé UMLV [page 225 ] Requête paramétrée Exemple PreparedStatement pstmt = conn.preparedStatement("UPDATE emp SET sal=? WHERE nom=?;"); for(int i=1; i<=10,i++) { pstmt.setDouble(i, salaire[i]); pstmt.setString(i,nom[i]); pstmt.executeUpdate(); } ● On peut passer la valeur NULL avec setNull (n,type) (type de la classe Types). Olivier Curé UMLV [page 226 ] Avantages des requêtes paramétrées ● ● Traitement plus rapide si elles sont utilisées plusieurs fois avec plusieurs paramètres. Amélioration de la portabilité (indépendance des setXXX avec les SGBD). Olivier Curé UMLV [page 227 ] C. Java et le Web Olivier Curé UMLV [page 228 ] Plan ● C.1. Java côté client : Applet ● C.2. Java côté serveur : Servlet et JSP Olivier Curé UMLV [page 229 ] Java côté client : Applet Olivier Curé UMLV [page 230 ] Une applet ? ● ● ● ● Une classe Java compilée (byte code). qui hérite de java.applet.Applet et lui donne une certaine interface : init(), start(), paint(), stop(), destroy(). qui réside sur un serveur. qui est véhiculée au sein d'une page HTML qui contient son URL. Olivier Curé UMLV [page 231 ] Mode de fonctionnement ● ● Soit un navigateur possédant une JVM recevant une page HTML avec une applet. Le navigateur va télécharger (via HTTP) le code de la classe et exécuter cette classe sur le poste client (invocation des méthodes init() et start()). Une application fonctionne alors sur le navigateur. Olivier Curé UMLV [page 232 ] Avantages ● ● ● ● indépendant de la plateforme modifier le comportement d'un programme sans toucher au code HTML. modifier les comportements de l'applet en fonction des paramètres associés à la page HTML. Sécurité : pas de lecture/écriture des données du client, pas d'exécution de programmes ni de chargement de codes natifs sur le poste client, pas de communication avec d'autres machines. Olivier Curé UMLV [page 233 ] Invocation, un peu d'HTML ● Une balise <applet> indique au navigateur qu'il doit charger une applet. <html> <applet code="HelloWorld.class" width=200 height=200>HelloWorld </applet> </html> Olivier Curé UMLV [page 234 ] Invocation, explications ● code : nom de la classe principale ● width et height : taille en pixels. ● hspace et vspace : espace autour de l'applet. ● codebase : URL de base de l'applet. ● name : nom donné à l'applet. ● align ={left|right|middle|top..} ● archive =*.jar ou *.zip Olivier Curé UMLV [page 235 ] Invocation, avec paramètres ● Avec la balise "param" : <applet code="UneClasse.class" width=150 height=150> <param name="nom1" value="toto"> <param name="nom2" value="titi"> ... </applet> Olivier Curé UMLV [page 236 ] Programmation des applets ● Une applet hérite de java.applet.Applet ● Pas de main() ● ● Redéfinir les méthodes héritées pour spécifier un comportement. Cycle de vie : init() → start()↔ stop() → destroy() Olivier Curé UMLV [page 237 ] Les méthodes d'une applet ● Les applets répondent aux messages suivants : – init() : appelée une fois à la création de l'applet. – start() : appelée une fois après l'init, et appelée à chaque fois que l'applet est stoppée. – stop() : appelée lorsque l'on change de page. Olivier Curé UMLV [page 238 ] Les méthodes d'une applet (2) – destroy() : appelée lorsque l'on quitte le navigateur. – paint() : appelée chaque fois que le navigateur doit se redessiner. Pour une applet graphique (héritant de java.awt.Panel), cette méthode contient l'essientiel de son activité. Elle reçoit comme paramètre un objet de la classe Graphics. Olivier Curé UMLV [page 239 ] Autres méthodes graphiques ● ● repaint() pour le rafraîchissement du programme graphique, provoque l'appel de la méthode paint. Ne pas surcharger. update() appelée par le navigateur pour redessiner une zone du programme graphique. Olivier Curé UMLV [page 240 ] C.2. Java côté serveur : Servlet et JSP Olivier Curé UMLV [page 241 ] Servlet Les servlets sont du code java déployé sur un serveur HTTP afin d'étendre les capacités de ce dernier. Principe : Ce sont des classes java qui s'exécutent sur un serveur dans le cadre d'un modèle requêteréponse. Ecriture repose sur l'implémentation de l'interface javax.servlet.Servlet. Principales méthodes : init (lancée après le chargement), service (reçoit une requête ServletRequest et construit une réponse ServletResponse) et destroy. Olivier Curé UMLV [page 242 ] Servlet (suite) Les servlets fournissent une infrastructure technique de base pour construire des applications java dans une contexte web, généralement associé au protocole HTTP. Ils garantissent : - la gestion transparente de la parallélisation (multithreading). - la gestion des contextes des requêtes (session client). - la manipulation simple des requêtes et réponses associées aux invocations clients. Inconvénient : séparation logique applicative / présentation Olivier Curé UMLV [page 243 ] Fonctionnement avec HTTP Olivier Curé UMLV [page 244 ] Cycle de vie d'un Servlet ● ● ● Méthode appelée au démarrage du servlet : init. Elle peut : – Initialiser le Servlet – Propager l'initialisation par super.init(..) – Pas de constructeur. Différenciation des méthodes HTTP : – service() pour toutes les requêtes HTTP – doGet(), doPost(), doDelete(), doHead(), doPut(), doTrace() pour chaque requête HTTP. Détruire le Servlet : destroy(). Olivier Curé UMLV [page 245 ] Exemple HelloWorld import java.io.*; Obligatoire import javax.servlet.*; import javax.servlet.http.*; public class HelloWorld extends HttpServlet { } public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletExceptionImposé par l'API { Le contenu est du HTML response.setContentType("text/html"); PrintWriter out = response.getWriter(); Génération d'un flux pour l'affichage out.println("<html>"); des résultats out.println("<head>"); out.println("<title>Hello World!</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Hello World!</h1>"); out.println("</body>"); out.println("</html>"); } Olivier Curé UMLV [page 246 ] Servlet ● Chaque Servlet est instanciée 1 seule fois. Il y a donc persistance des données entre les invocations. Olivier Curé UMLV [page 247 ] Exemple formulaire : form.html <html> <body> <form action="form.class" method="get"> nom : <input name="nom"/><br/> prenom : <input name="prenom"/><br/> <input type="submit" value="Valider"/> </form> </body> </html> Olivier Curé UMLV [page 248 ] Exemple formulaire : form.java import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class Form extends HttpServlet { } public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); String nom = request.getParameter("nom"); String prenom = request.getParameter("prenom"); out.println("<html>"); out.println("<body>"); out.println("<h1>Salut "+ nom + " "+ prenom +"</h1>"); out.println("</body>"); out.println("</html>"); } Olivier Curé UMLV [page 249 ] Session et HTTP ● ● ● ● HTTP est un protocole "déconnecté" ou "sans état". C'est une limite importante pour les nouvelles approches du Web (e-commerce par exemple). Mécanisme de session : lors de chaque échange, il s'agit de vérifier à qui le serveur a à faire. Les requêtes provenant d'un même utilisateur sont associées à la même session. Une session expire après un certain delai. Olivier Curé UMLV [page 250 ] Session et Servlet ● API des Servlets permet la gestion de sessions : HttpSession session = request.getSession(true); ● Retourne la session courante de l'utilisateur ou une nouvelle session. Méthodes de HttpSession : void setAttribute(String name, Object value); Object getAttribute(String name); void removeAttribute(String name); java.util.Enumeration getAttributeName(); Olivier Curé UMLV [page 251 ] JSP Les JSP (Java Server Pages) sont des documents du type texte, très similaires dans leur forme aux pages HTML. Contenant à la fois des balises HTML et des balises spécifiques. Elles sont transformées dynamiquement en servlet par le moteur de JSP lors de leur invocation. Olivier Curé UMLV [page 252 ] JSP (suite) Intérêt : Exploitation des outils WYSIWIG. L'objectif des JSP est de permettre l'interaction avec des objets métiers et non d'inclure massivement du code java au sein de balises HTML. L'encapsulation des composants dans l'application sous forme de JavaBeans permettent aux JSP et aux objets de coopérer. Olivier Curé UMLV [page 253 ] Etapes du déroulement d'une page JSP Olivier Curé UMLV [page 254 ] Structure d'une page JSP ● Des balise HTML ● Plus : – directives – declarations – expressions – scriptlets Olivier Curé UMLV [page 255 ] Directives ● Apparaissent en début de page. ● Syntaxe : <%@ ... %> ● Exemple : <%@ page import="java.util.Date, java.io.*" extends="myPage" %> Olivier Curé UMLV [page 256 ] Declarations ● Définitions de propriétés et méthodes locales à la page. ● Syntaxe : <%! ... %> ● Exemple <%! int cpt=0; %> <%! public int getValue() { ... return val; } %> Olivier Curé UMLV [page 257 ] Expressions ● ● Une instruction d'exécution au web container et affichage du résultat. Syntaxe : <%= getValue() %> Olivier Curé UMLV [page 258 ] Scriptlets ● Du fragment de code Java ● Syntaxe : <% ... %> Olivier Curé UMLV [page 259 ] JSP standard actions ● ● ● Le serveur (Tomcat) exécute les directives au moment de la transformation des pages. Le serveur exécute les actions au moment du traitement des requêtes HTTP. Syntaxe standard: <jsp:actionname actionattributelist/> Olivier Curé UMLV [page 260 ] JSP standard actions ● ● action-attribute-list: une séquence de couples attribute-name=''value'' Principales actions: forward: pour «forwarder » la requête à une autre page. <jsp:forward page=''autrePage.jsp''> – <jsp:param name=''par'' value=''5''/> </jsp:forward> Olivier Curé UMLV [page 261 ] JSP standard actions include: pour exécuter une autre page et inclure sa sortie dans la page courante. <jsp:include page=''autrePage.jsp''> – – useBean: déclaration d'une nouvelle variable en l'associant à un objet java. <jsp:useBean id=''client'' scope=''application'' class=''Personne''/> – setProperty: pour fixer la valeur d'une propriété d'un bean. – getProperty Olivier Curé UMLV [page 262 ] Exemple formulaire JSP <html> <head> <style type="text/css"> @import url("com.css"); </style> </head> <body> <%@ include file="header.html" %> <form action="formAuth2.jsp" method="GET"> login<input type="text" name="login" /> password <input type="password" name="pass"/> <input type="submit" name="Valider" /> </form> <%@ include file="footer.html" %> </body> </html> Olivier Curé UMLV [page 263 ] Exemple formulaire JSP <html> <head> <style type="text/css"> @import url("com.css"); </style> </head> <body> <%@ include file="header.html" %> <% String login = request.getParameter("login"); String pass = request.getParameter("pass"); if (login.equals("toto") && pass.equals("123")) out.println("Bienvenue"); else out.println("Refuse"); %> <%@ include file="footer.html" %> </body> </html> Olivier Curé UMLV [page 264 ] <%@ page import="java.sql.*" %> <html> <head> <style type="text/css"> @import url("com.css"); </style> </head> <body> <%@ include file="header.html" %> <% String login = request.getParameter("login"); String pass = request.getParameter("pass"); String query = "SELECT nomcli, prenomcli FROM client WHERE login LIKE '"+login+"' AND pass LIKE '"+pass+"';"; Connection con; java.sql.Statement stt; try { Class.forName("org.postgresql.Driver"); con = DriverManager.getConnection("jdbc:postgresql:cours","oliv e" ,"" ); stt = con.createStatement(); ResultSet rs = stt.executeQuery(query); Authentification avec une BD Olivier Curé UMLV [page 265 ] Authentification avec une BD if (rs.next()) { out.println("Bienvenue "+ rs.getString(1) +" (fin) "+rs.getString(2)+" <br />"); } else out.println("Refuse"); stt.close(); con.close(); } catch(SQLException ex) { out.println("SQLException: " + ex.getMessage()); } catch(java.lang.ClassNotFoundException e) { out.println("=> "+ e.getMessage()); } %> <%@ include file="footer.html" %> </body> </html> Olivier Curé UMLV [page 266 ] Gestion des sessions <html> <body> <%= session.getId() %> <% session.setAttribute("val1","10"); SessionPage1.jsp session.setAttribute("val2","Toto"); %> <a href="SessionPage2.jsp">page2</a> </body> </html> SessionPage2.jsp <html> <body> <%= session.getId() %> <% out.println("Valeur de val1 ="+session.getAttribute("val1")); out.println("Valeur de val2 ="+session.getAttribute("val2")); %> <a href="SessionPage2.jsp">page2</a> </body> </html> Olivier Curé UMLV [page 267 ] Session ● ● ● ● Les requêtes provenant d'un utilisateur sont associées à une même session. Expiration d'une session après un certain délai. Objet prédéfini : session Pour définir une nouvelle session ou bien pointer sur la session courante. Olivier Curé UMLV [page 268 ] Méthodes de session ● void setAttribute(String name, Object value) – ● Object getAttribute(String name) – ● Ajoute un couple nom, valeur pour la session courante Retourne la valeur d'un couple associé à la clé name. void removeAttribute(String name) – Supprime le couple Olivier Curé UMLV [page 269 ] Exploitation de Java Beans <%@ page import="monpackage.*" %> Bean.jsp <html> <body> <jsp:useBean id="myBean" scope="session" class="monpackage.Bean"/> <jsp:setProperty name="myBean" property="nom" value="toto"/> <% out.println("Valeur = "+myBean.getNom()); %> </body> </html> package monpackage; public class Bean { private String nom; public String getNom() { return nom; } public void setNom(String nom) { this.nom = nom; } Bean.java } Olivier Curé UMLV [page 270 ] Les paramètres de jsp:useBean ● ● ● id : donne un nom au Java Bean scope : fixe la durée de vie de l'objet. Valeurs possibles : class (ou type) : le nom de la classe source du Bean. Olivier Curé UMLV [page 271 ] Architecture ● ● ● L'architecture des applications basées sur l'utilisation de JSP/Servlet est importante Sans une bonne architecture, on se retrouve rapidement avec beaucoup (trop) de scriptlets (<% ..%>) dans les pages HTML. Il existe plusieurs modèles Olivier Curé UMLV [page 272 ] JSP Modèle 1 ● ● La logique applicative est implémentée au sein de classes Java (Java Beans) qui peuvent être utilisées au sein des JSP. Cette approche est valable si l'aspect design de la page n'est pas prépondérant. Olivier Curé UMLV [page 273 ] JSP Modèle 2 ● ● La logique applicative et l'aspect présentation de la page sont séparés. On parle d'architecture MVC (Model View Controller) Cette approche également valable pour des applications volumineuses. Olivier Curé UMLV [page 274 ] JSP Modèle 2 ● ● Le servlet gère la requête HTTP, s'occupe de la couche applicative, instancie les Java Beans. JSP obtient les données depuis les beans et formate la réponse, sans se soucier des autres détail (connexion à la base de données). Olivier Curé UMLV [page 275 ] Tomcat ● Tomcat est un moteur de JSP et Servlet opensource du projet Apache-Jakarta. ● Contient également un serveur HTTP. ● Référence dans le domaine. ● ● Très réactif, version 6 est compatible avec les nouvelles versions des servlets et JSP (2.1) Comporte de nombreux fichiers (xml) de configuration. Olivier Curé UMLV [page 276 ] Tomcat ● ● web.xml permet de décrire la structure de l'application. MANIFEST.MF n'est pas écrit en XML. Il permet la création d'un document Web ARchive (WAR). Il est utilisé pour déployer l'application sur un autre serveur. Olivier Curé UMLV [page 277 ] Tomcat ● définition implicite de plusieurs variables: – application : accès au contexte du servlet – config – out : like System.out for the web env. – pageContext – request : provides info on the request (parameters, headers, client,etc.). – response – session Olivier Curé UMLV [page 278 ] JSTL: Java Standard Tag Library ● ● ● JSP propose un mécanisme d'extension des balises (tag) permettant de créer des librairies d'actions. Elles peuvent être exploitées dans de nombreuses applications. On peut appeler ces actions avec une syntaxe XML Il en existe un standard: JSTL Olivier Curé UMLV [page 279 ] JNDI: Java Naming and Directory Interface ● ● ● une interface Java permettant l'accès à des annuaires et des répertoires hétérogènes permet un accès simple à des EJBs, les sources JDBC, les files JMS, les transactions JTA, etc.. permet une indépendance vis-à-vis des annuaires et répertoires. Olivier Curé UMLV [page 280 ] JNDI ● ● un service d'accès: des variables d'environnement d'applications Web, des EJBs, des pools de connections sur les sources de données, .. Représentation sous la forme d'un arbre (en mémoire, pas une BD). Olivier Curé UMLV [page 281 ] JNDI ● Atteindre JNDI au sein du serveur Context ctx = new InitialContext(); ● Accéder à une ressource: DataSource ds = (DataSource) ctx.lookup(''java:/comp/env/jdbc/mybd''); Connection connection = ds.getConnection Olivier Curé UMLV [page 282 ]