© Développer des applications WEB avec Struts Applications Struts 1 © Plan du cours • Rappels sur les composants Java pour le WEB – Servlets – JSP – Architecture d’un site Web Applications Struts 2 • • • • Présentation de Struts Développement Utilisation avancée Conclusion © Les Servlets • • • • • Applications Struts 3 Présentation Cycle de vie Principe de fonctionnement Échange d’informations Gestion d’une session © Présentation des servlets • Exécution de traitements sur un serveur suite à une requête d’un client • Prévu pour tout type de protocole avec une implémentation pour HTTP • Génération de pages dynamiques orientée sur une logique de traitement • Concurrent aux technologies : Applications Struts 4 – CGI – NSAPI / ISAPI © Le principe Présentation Applications Struts 5 • Processus Java qui s’exécute côté serveur suite à une requête d’un client • Exploite les paramètres de la requête • Repose sur les classes de l’API servlet de l'environnement J2EE • S’exécute au sein d'un moteur de servlets couplé au serveur Web © Fonctionnement Présentation Client Response Response Request Web Server Moteur de servlets Request Applications Struts 6 Application Java © Moteurs de servlets Présentation • Les moteurs peuvent être directement intégrés aux serveurs Web ou ajoutés comme modules par la suite • Parmi tous les serveurs supportant les servlets, on peut noter : – Tomcat, Resin, JRun, BEA Weblogic Server, IBM Websphere, Oracle Application Server, ... Applications Struts 7 © Cycle de vie d’une servlet Cycle de vie Chargement et initialisation Serveur Client Client Servlet Échange de données avec les clients Serveur Servlet Déchargement Serveur Applications Struts 8 Servlet © Conteneur de servlet Cycle de vie Conteneur de servlet Thread Servlet init() Requête HTTP Affectation de la requête initialisation service() exécution du service Réponse HTTP destroy() Applications Struts 9 nettoyage © Mise en oeuvre (1) Mise en oeuvre Applications Struts 10 • Le package javax.servlet contient des interfaces et des classes pour l’écriture de servlets • Une servlet hérite de la classe HTTPServlet qui elle-même implémente l’interface Servlet • La servlet peut redéfinir des méthodes de HTTPServlet qui correspondent à des requêtes HTTP classiques : service(), doGet(), doPost() ... © Mise en oeuvre (2) Mise en oeuvre Applications Struts 11 • Les méthodes de type doGet() et doPost() reçoivent en paramètre deux objets : – Un objet HttpServletRequest qui encapsule la requête du client (renseignée automatiquement par le moteur) – Un objet HttpServletResponse qui encapsule la réponse qui sera retournée au client (à renseigner dans le code de la servlet) © public class ExempleServlet extends HttpServlet { /** * Réponse à une requête HTTP GET : retourne une simple page HTML */ public void doGet ( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { PrintWriter out; String titre = "Exemple simple de document généré par une servlet"; Mise en oeuvre // Renseigne la réponse sur le type du document retourné response.setContentType( "text/html" ); // Récupère un flux sur la réponse afin d’y écrire la page out = response.getWriter(); // Ecriture de la chaîne correspondant à la page HTML retournée out.println("<HTML><HEAD><TITLE>"); out.println( titre ); out.println("</TITLE></HEAD><BODY>"); out.println("<H1>" + titre + "</H1>"); out.println("<P>Cette page provient d’une servlet."); out.println("</BODY></HTML>"); out.close(); Ex 3 } Applications Struts } 12 © Surcharge des méthodes Mise en oeuvre void init() Applications Struts 13 GenericServlet Appelée au chargement de la servlet : initialisation, lecture des fichiers de conf… void GenericServlet service() Appelée à chaque invocation de la servlet void GenericServlet destroy() Appelée au déchargement de la servlet : destruction de tous les objets créés © Partage des données Mise en oeuvre • Chaque servlet n’est instanciée qu’une seule fois, il y a donc persistence des données entre deux appels de la servlet • La valeur d’un attribut de la classe dérivant d’HttpServlet dépend des autres invocations (multi-threads) – => Il ne faut pas utiliser les attributs pour stocker des informations ! Client 1 Client 3 Servlet Applications Struts 14 Client 2 Client 4 © Echange d’informations Echange d'informations • Trois objets peuvent servir d’intermédiaires pour échanger des informations entre composants Web : – La requête – La session – L’« application » • Ils se comportent comme des hashtables et disposent des méthodes : Applications Struts 15 – setAttribute() – getAttribute() © La requête Echange d'informations • La requête est passée en paramètre de la méthode service() (ou doGet(), doPost()…) • On y récupère l'URL d’appel, les paramètres HTTP et la session utilisateur – getRequestURL() – getParameter(String name) – getSession() Applications Struts 16 • Elle peut être transmise à une autre servlet lors d’une délégation de traitement (forward) • On y place des objets servant à la génération de la réponse © L’« application » Echange d'informations • L’« application » est un objet de la classe ServletContext récupéré à partir de la servlet ServletContext application = this.getServletContext(); Applications Struts 17 • L’« application » est partagée entre tous les objets Web et tous les clients d’une même application Web • On y place les objets servant pour toute l’application (ressources…) © La session Echange d'informations • La session peut être récupérée à partir de la requête HttpSession session = request.getSession(); Applications Struts 18 • La session est liée à un client. Elle existe tant qu’elle n’a pas été détruite volontairement ou par un time out • On y place les objets servant durant toute la connexion du client (typiquement : un caddie) © Les cookies Gestion de sessions • Permettent le stockage d’informations au niveau du client • Utilisation de la classe javax.servlet.http.Cookie – Création Cookie monCookie = new Cookie("nom", "valeur"); response.addCookie(monCookie); – Récupération Applications Struts 19 Cookie[] mesCookies = request.getCookies(); © URL Rewriting Gestion de sessions • Gestion des sessions pour des clients n’acceptant pas les cookies • Méthodes – HttpServletResponse.encodeURL() – HttpServletResponse.encodeRedirectURL() out.println( "<tr>" + ... + "<a href=\"" + response.encodeURL(monLien) + "\"> + books[i].getTitle() + "</a> ); Applications Struts 20 • Utilise le session ID pour retrouver la session de l’utilisateur © Déléguer des traitements Gestion de sessions • Possibilité de rediriger la requête HTTP sur une autre URL response.sendRedirect(<location>); • Possibilité de déléguer une partie de la réponse à une autre ressource : Ex 4-6 Applications Struts 21 – Par inclusion : include() – Par délégation complète : forward() ServletContext ctx = getServletContext(); RequestDispatcher rd; rd = ctx.getRequestDispatcher(<RelativeURLOfJSP>); rd.include( <RequestObject>, <ResponseObject> ); rd.forward( <RequestObject>, <ResponseObject> ); © Les Java Server Pages • Dans ce chapitre, nous allons : – Présenter l’architecture des JSP – Comprendre la syntaxe JSP – Développer un exemple de JSP Applications Struts 22 © Présentation des JSP Présentation des JSP • Génération de pages dynamiques orientée sur une logique de présentation • Ce sont des scripts interprétés côté serveur contenant du code Java • Insèrent de la logique de traitement dans des pages de présentation (HTML, WML, XML) • Concurrent aux technologies : – ASP – PHP Applications Struts 23 © Exemple de fichier JSP Présentation des JSP Applications Struts 24 • Une page JSP est écrite dans le langage cible de publication (HTML, …) • Elle contient des appels à du code Java <HTML> <HEAD> <TITLE> Exemple de page JSP </TITLE> </HEAD> <BODY> Un nombre aléatoire est : <%= Math.random() %> </BODY> </HTML> © Fonctionnement Présentation des JSP Applications Struts 25 • Les pages JSP sont exécutées par un moteur de JSP couplé au serveur Web • Elles accèdent à du code Java qui se charge de la logique et de l'accès aux données © Compilation des JSP Présentation des JSP • Modèle d'exécution : – Chaque page JSP est convertie en servlet – Lorsque la page JSP a déjà été compilée et exécutée une fois, la servlet reste en mémoire, elle est directement exécutée Applications Struts 26 © Format des Tags JSP Les tags JSP • L'écriture de pages JSP se base sur l'utilisation de balises (tags) prédéfinies • Il existe deux formats pour les tags JSP JSP (Short-hand) Directives Déclaration Expression Scriptlet XML Applications Struts 27 Actions © Expressions Les tags JSP • Permettent d’intégrer des valeurs directement dans le code HTML <%= value %> • Utilisées pour afficher une chaîne de caractères, typiquement une valeur de retour • Exemple : <P>Prix de l’article : <%= monArticle.getPrice() %></P> Applications Struts 28 Equivalent à l’utilisation du out.println() dans la méthode service() d’une servlet © Scriptlets Les tags JSP • Permettent d’insérer du code Java <% code java %> • Elles ont accès aux variables et aux composants déclarés dans la page • Exemple : <P> <% if (true) { %> Ce texte est affiché <% } else { %> Celui-ci n'est jamais pris en compte <% } %> </P> Applications Struts 29 Equivalent à du code simple dans la méthode service() d’une servlet © Déclarations Les tags JSP • Utilisées pour déclarer des variables ou des méthodes dans une page <%! declaration %> • Fortement déconseillé ! • Exemple : <%! String var1 =“x”; int count = 0; private void increment() { count++; } %> Applications Struts 30 Equivalent à une déclaration d'attribut ou d'une méthode dans la classe de la servlet © Directives JSP Les tags JSP • Permettent de configurer la JSP <%@ directive { attribute = “value” } %> • Sont souvent placées au début du fichier • Exemples : – Inclusion statique de fichiers : <%@ include file=“headers/copyright.html” %> – Import de classes : <%@ page import=“java.util.*” %> Applications Struts 31 Équivalent à l'écriture des imports de packages et de classes au début du code de la servlet © Directive pour les exceptions Les tags JSP • Possibilité d’intercepter toutes les exceptions non catchées • Redirection de tous les cas d'erreur vers une page unique • Utilisation de la directive page : <%@ page isErrorPage="false" errorPage="errorHandler.jsp" %> • Au début de la page errorHandler.jsp, il faut ajouter : Applications Struts 32 <%@ page isErrorPage="true"%> © Liste des directives Les tags JSP Applications Struts 33 • <%@ page language="java" %> • <%@ page extends="package.class" %> • <%@ page import= "{ package.class | package.* }, ..." %> • <%@ page session="true|false" %> • <%@ page buffer="none|8kb|sizekb" %> • <%@ page autoFlush="true|false" %> • <%@ page isThreadSafe="true|false" %> • <%@ page info="text" %> • <%@ page errorPage="relativeURL" %> • <%@ page isErrorPage="true|false" %> • <%@ page contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=ISO8859-1" %> © Actions Les tags JSP • Elles effectuent une tâche prédéfinie • Aucun codage en Java n’est nécessaire • Elles se caractérisent par une balise standard XML spécifique : – – – – Applications Struts 34 useBean setProperty/getProperty include forward © Utilisation de Beans Les tags JSP • useBean : Instancie un Bean sur le serveur <jsp:useBean id=“notreBean” scope=“application” class=“com.example.OurBean” /> • getProperty : Récupère la propriété d’un Bean <jsp:getProperty name="notreBean" property="unAttr"/> • setProperty : Met à jour la propriété d’un Bean (utilisé pour les formulaires) <jsp:setProperty name="notreBean" property="unAttr" value="uneValeur"/> <jsp:setProperty name="notreBean" property="unAttr" param="unParam"/> Applications Struts 35 <jsp:setProperty name="notreBean" property="*"/> © Actions - Scope Les tags JSP Applications Struts 36 • L’action useBean permet de récupérer ou de créer un bean suivant une portée • 4 portées différentes : – page : objet accessible seulement dans la page où il a été créé – request : objet accessible seulement pour les pages qui sont liées à une même requête – session : objet accessible par un seul client sur toutes les pages JSP pendant la même session – application : objet accessible par tous les clients pendant toute la durée de l’application © Utilisation d'autres ressources Les tags JSP • include : Permet d’insérer dynamiquement le contenu d'une autre ressource (servlet, JSP, HTML) <jsp:include page="shoppingcart.jsp" /> • forward : délègue le traitement de la requête à une autre ressource <jsp:forward page="shoppingcart.jsp" /> Applications Struts 37 • le sendRedirect reste possible, mais ce n'est pas une action © Variables implicites Variables implicites 9 variables implicites peuvent être utilisées dans les pages JSP : Variable (scope - classe) Méthodes courantes Commentaires request getParameter Répresente la ( request - Sous-classe getParameterNames requête HTTP de javax.servlet. getParameterValues ServletRequest ) response Applications Struts 38 (Page – Sous-classe de javax.servlet. ServletResponse) Représente la réponse HTTP Peu utilisé dans les JSP © Variables implicites Variables implicites pageContext (Page javax.servlet.jsp.Page Context) session (Session javax.servlet.http. HttpSession) application Applications Struts 39 (application javax.servlet. ServletContext) findAttribute getAttribute getAttributesScope getAttributeNamesInScope getId getAttribute putAttribute getAttributeNames Représente la session utilisateur getMimeType getRealPath Représente la Web application © Variables implicites Variables implicites out (Page - javax.servlet.jsp.Jsp Writer) config (Session - javax. servlet. ServletConfig) getInitParameter, getInitParameterNames page getMimeType, getRealPath (page - java.lang. Object) Applications Struts 40 clear, clearBuffer, flush, Représente la getBufferSize, réponse http sous getRemaining la forme d’un flux de caractères exception (page - java.lang. Throwable) getMessage, getLocalizedMessage, printStackTrace Peu utilisé © Ecrire des JSPs (1) Démarche • JSPs de présentation : – Générer dans un premier temps le code HTML de la partie présentation – Enregistrer le fichier avec l’extension .jsp – Programmer le code Java sur le serveur qui gère la partie fonctionnelle – Insérer les appels JSP pour la communication avec ce code Java Applications Struts 41 • Certaines JSPs servent uniquement à réaliser des traitements, l'écriture de la réponse est alors déléguée © Ecrire des JSPs (2) Démarche JSP Affichage de formulaire POST JSP Traitement du formulaire forward Applications Struts 42 JSP Affichage de résultat En fonction du résultat forward JSP Affichage de page d'erreur © Un exemple complet Démarche Ex 7-8 Applications Struts 43 package com.example ; public class OurBean { private String value; public void setValue (String s ) { value = s ; } public String getValue ( ) { return value ; } } <HTML> JavaBean <BODY> JSP <H2> cette page teste notre bean </H2> <jsp:useBean id= “notreBean” class= “com.example.OurBean” scope= “session” /> <% notreBean.setValue(“présent”); %> <P> notre bean est <%= notreBean.getValue(); %> </P> </BODY> </HTML> © Les différents modèles d’architecture technique Les architectures distribuées Les modèles • Système centralisé – limitation très forte du nombre d’utilisateurs – pas de communication distante • Client/Serveur – 2 tiers – 3 tiers – N tiers Applications Struts 44 © Architecture 2 tiers Les architectures distribuées 2 tiers Client Unité de communication Serveur Client serveur première génération : • le client gère uniquement la couche présentation • le serveur réalise l’ensemble des applications Applications Struts 45 La couche de présentation est très succincte Les performances du serveur s’écroulent au delà de quelques utilisateurs © Architecture 2 tiers Les architectures distribuées 2 tiers Client Unité de communication Serveur Client serveur deuxième génération : • pour utiliser la puissance des PC, les traitements applicatifs sont déportés sur ceux-ci • le serveur gère les accès à la base de données selon les requêtes des clients Applications Struts 46 Absence de standard Déploiement coûteux et difficile Trafic réseau important Difficultés d’administration © Architecture 3 tiers (Réponses aux limitations du 2 tiers ) Les architectures distribuées 3 tiers Client Serveur Agent Unité de communication Unité de communication L’architecture est composée • D’un niveau client gérant la présentation • D’un niveau agent, ou serveur d'applicatif, prenant en compte les applications et les objets métiers Applications Struts 47 • D’un niveau contenant les serveurs de base de données © Architecture 3 tiers (Réponses aux limitations 2 tiers ) Les architectures distribuées 3 tiers • Les postes clients sont pourvus • d’un navigateur Web utilisant des applets ou des contrôles ActiveX – le déploiement et la mise à jour logiciel sont facilités • d’une application • L’agent à pour rôle de : Applications Struts 48 – – – – – – fournir des services de routage de requêtes fournir des services de sécurité filtrer les requêtes fournir des services de collecte de données fournir des services de répartition de charge fournir des services transactionnels (moniteur transactionnel) – tolérance aux pannes © Architecture 3 tiers (Réponses aux limitations 2 tiers ) Les architectures distribuées 3 tiers • Les trois niveaux sont standardisés • La logique métier se déplace sur le serveur ce qui permet un meilleur contrôle de sa diffusion • Les montées en charge sont mieux gérées puisqu’il est possible d’ajouter des machines serveurs • L’administration du système distribué est centralisée Applications Struts 49 © Architecture multi-niveaux Les architectures distribuées Logique de présentation Logique applicative Multi-niveaux Services spécifiques Services Achats Logique d’accès aux données Gestion des données Services Vente (système existant) Périphérique ERP * Applications Struts 50 * (Enterprise Resource Planning = solution de gestion intégrée). © Architecture multi-niveaux Les architectures distribuées Multi-niveaux • L’architecture multi-niveaux est une généralisation de l’architecture 3 tiers à partir d’un modèle de composants • Les liens entre les composants sont rendus possibles par l’existence d’un bus logiciel Favorise l’intégration d’un système 3 tiers dans l’existant Permet la récriture d’un système par étapes en conservant l’existant Applications Struts 51 © Struts Applications Struts 52 © Généralités (1) Généralités • « Comment organiser les entités en charge de la gestion de l'interaction entre l'utilisateur et le système ? » • Le Framework Struts permet de réaliser une application Web basée sur – MVC2 – JSP/Servlet (ou XML/XSLT) • Principale implémentation du MVC2 Applications Struts 53 – Il en existe des alternatives © Généralités (2) Généralités • Struts n’est pas destiné aux applications Web très simple – Struts introduit un niveau de complexité et de mise en route trop important. – Dès qu'une application prends de l'importance, Struts peut rapidement simplifier les choses. • Struts est distribué sous licence ASF. Applications Struts 54 – Struts peut donc être utilisé dans des applications commerciales dans le respect de ce qui est inscrit dans cette licence. © Modèle MVC (1) Généralités Modèle MVC • MVC : Modèle – Vue – Contrôleur – Lié à l'origine des langages à objets. • Séparation en 2 couches verticales – Les objets métiers (Modèle) – Les objets IHM • Objets chargés de l'acquisition d'informations en provenance de l'utilisateur (Contrôleur) • Objets chargés de la restitution d'informations vers l'utilisateur (Vue) Applications Struts 55 © Modèle MVC (2) Généralités Modèle MVC 1 2 3 4 5 Applications Struts 56 © MVC et J2EE • Un contrôleur est implémenté sous forme de servlet Java. • Le modèle consiste en l'implémentation de la logique métier du site Web: – Composants Java Beans – Composants EJB (Enterprise Java Bean). • Chaque vue est implémentée via une servlet. Applications Struts 57 © Le modèle MVC II (1) Généralités Modèle MVC II • Dans MVC II : la servlet est unique : – Garantit l'unicité du point d'entrée de l'application – Prend en charge une partie du contrôle de l'application. • Les contrôleurs MVC se retrouvent alors partiellement déportés dans l'entité "dynamique de l'application" Applications Struts 58 – Assurent le contrôle de la dynamique de l'application – Gèrent les relations entre les objets métier et la présentation © Le modèle MVC II (2) Généralités Modèle MVC II 1 2 3 7 4 5 6 Applications Struts 59 © Struts Présentation • Un contrôleur facilement configurable – Permettant d’associer des actions (méthode d’un objet Java) à des requêtes HTTP • Des librairies de tags spécifiques pour créer facilement une vue • Un Digester, permettant de parser un fichier XML et d’en récupérer facilement les information voulues • Support de l’internationalisation, gestion des sources de données (DataSources) … Applications Struts 60 © Fonctionnement de Struts (1) Fonctionnement Applications Struts 61 © Fonctionnement de Struts (2) Fonctionnement • Un identifiant fait office de commande et indique le traitement à exécuter • Une table de correspondance permet de faire le lien entre commande et traitement à exécuter – La commande est déterminée par une partie de l'URL transmise au servlet contrôleur, ActionServlet Applications Struts 62 © Fonctionnement de Struts (3) Fonctionnement • Les traitements sont encapsulés dans les classes Actions. • La correspondance entre la commande et l'Action à exécuter est déclarée au sein du fichier de configuration Struts – Association URL/nom de la classe Action Applications Struts 63 © Fonctionnement de Struts (4) Fonctionnement • Automatisation des relations entre Actions et JSP par le biais des ActionForms – JavaBeans renseignés automatiquement à partir des paramètres des requêtes transmises au servlet contrôleur – Transmises telles quelles aux Actions. Applications Struts 64 © Fonctionnement Le contrôleur Applications Struts 65 Le point d’entrée: ActionServlet • Toutes les actions Struts passent par cette classe <!-- Action Servlet Configuration – Extrait de web.xml --> <servlet> <servlet-name>action</servlet-name> <servlet-class> org.apache.struts.action.ActionServlet </servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> © Les classes Action Fonctionnement Le contrôleur • Héritent de la classe org.apache.struts.action.A ction • Extensions du contrôleur • Permettent de traiter le modèle en réponse à une requête •public Implémentent méthode execute() : ActionForwardlaexecute( Applications Struts 66 ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) © Mapping des actions Fonctionnement Le contrôleur • Le fichier struts-config.xml – Détermine qui traite l’action – Détermine la navigation Applications Struts 67 <action path="/search" type="fr.softeam.intranet.SearchAction" scope="request" name="searchForm" validate="true" input="/search.jsp"> <forward name="success" path="/displayResult.jsp" /> <forward name="failure" path="/login.jsp" /> </action> © Les ActionForm Fonctionnement Les formulaires Applications Struts 68 • Classes faisant la liaison entre les vues et le contrôleur • Héritent de org.apache.struts.action.ActionForm • Possèdent des accesseurs/mutateurs sur les paramètres du formulaire • Implémentent la méthode validate() : public ActionErrors validate( ActionMapping mapping, HttpServletRequest request); © Les DynaActionForm Fonctionnement Les formulaires Applications Struts 69 • Définition via le fichier de configuration • Ne nécessitent pas de classe d’implémentation • A associer au « Validator » pour les contrôles de validité © Struts : La vue Fonctionnement La vue • La vue – La vue est constituée de pages JSP – Struts propose des librairies de tags (taglib) : Applications Struts 70 • html : pour créer du Html, des formulaires, des liens… • bean : pour accéder aux classes • logic : pour faire des tests, des boucles • tiles : pour créer des pages à base de composants réutilisables (header, footer, …) • nested : pour utiliser les autres taglib dans des contextes imbriqués © Page 1 JSP 1 JSP 2 JSP 3 Web browser Fonctionnement Web container Moteur JSP Requête / session Controller Form Bean 2 Form Bean 3 struts-config.xml • mappings • • • path action [form bean] [forwards] Composant métier 2 71 SGBD Data Applications Struts Composant métier 3 Métier Composant métier 1 Présentation Form Bean 1 © Développement Applications Struts 72 © Développer le contrôle Développer le contrôle • Le développement de la couche contrôle consiste à : – Écrire une classe action pour chaque type de requête pouvant être émise par l’utilisateur – Définir dans le fichier de configuration (strutsconfig.xml) un ActionMapping pour chaque type de requête – Mettre à jour le fichier de déploiement WEB pour qu’il intègre les composants Struts – Ajouter les composants Struts à l’application Applications Struts 73 © Les classes Action (1) Développer le contrôle Action • Le rôle d’une action: – Traiter une requête via l’exécution de sa méthode « execute » – Retourner un objet ActionForward • « execute » effectue généralement les traitements suivants : Applications Struts 74 – Vérification de l’état courant de la session utilisateur (vérifier que l’utilisateur a été identifié) – Valider les données d’un formulaire …/… © Les classes Action (2) Développer le contrôle Action – Traiter la requête – Mettre à jour les objets qui vont permettre de créer la page à afficher – Retourner l’objet ActionForward qui identifie la JSP responsable de la réponse • Utilisation de la méthode findForward Applications Struts 75 © Action : Recommandations (1) Développer le contrôle Action • La servlet de contrôle ne crée qu’une seule instance de chaque classe Action – Même problématique que la méthode service d’une servlet – Utilisation de variables locales (pas de variables d’instance) Applications Struts 76 © Action : Recommandations (2) Développer le contrôle Action • Éviter de coder de « trop » grosses classes Action – Signe du déplacement d’une partie de la logique métier dans la classe action – Problème de maintenance, perte de réutilisabilité Applications Struts 77 © Les classes ActionMapping Développer le contrôle ActionMapping Applications Struts 78 • Permet l’association entre une requête entrante (représentée par son URI) et la classe Action qui va la traiter • ActionMapping – Type : Le nom complet de la classe Action qui doit traiter la requête – Name : Le nom du formulaire utilisé pour exécuter l’action – Path : URI de la requête qui permet de sélectionner l’ActionMapping – Validate : boolean positionné à true si la méthode validate de l’ActionForm doit être appelée © Le fichier struts-config.xml (1) Développer le contrôle Struts-config.xml Applications Struts 79 © Le fichier struts-config.xml (2) Développer le contrôle Struts-config.xml • form-beans : définition des formulaires – name : Identifiant du bean – type : Nom complet de la classe du bean • action-mappings : définition des actions – path : Chemin d’accès à l’action – type : Nom complet de la classe Action – name : Nom du <form-bean> utilisé par l’action • global-forwards : définition des associations avec les pages JSP Applications Struts 80 © Développer le contrôle Struts-config.xml Applications Struts 81 <struts-config> <form-beans> <form-bean name="logonForm" type="org.apache.struts.example.LogonForm"/> <form-bean name=« subscriptionForm" type="org.apache.struts.action.DynaActionForm> <form-property name="email" type="java.lang.String"/> </form-bean> </form-beans> <global-forwards type="org.apache.struts.action.ActionForward"> <forward name="logon" path="/logon.jsp" redirect="false"/> </global-forwards> <action-mappings> <action path="/logon" type="org.apache.struts.example.LogonAction" name="logonForm" scope="request" input="/logon.jsp" unknown="false" validate="true"/> </action-mappings> </struts-config> © Le fichier struts-config.xml (4) Développer le contrôle Struts-config.xml • Élément forward – Permet de devenir indépendant des nom des JSP <action path="/editSubscription" type="org.apache.struts.example.EditSubscription" name="subscriptionForm" scope="request" validate="false"> <forward name="failure" path="/mainMenu.jsp"/> <forward name="success" path="/subscription.jsp"/> </action> Applications Struts 82 © Le fichier web.xml (1) Développer le contrôle Web.xml • Il s'agit d’inclure tous les composants Struts nécessaires – Exemple : Applications Struts 83 <servlet> <servlet-name>action</servlet-name> <servlet-class> org.apache.struts.action.ActionServlet </servlet-class> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> © Paramètres d’initialisation (1) Développer le contrôle Web.xml Paramètres d’initialisation Applications Struts 84 • Liste des paramètres d’initialisation : – application : Nom de la classe Java contenant les ressources utilisées [NONE] – bufferSize : Taille du buffer d’entrée [4096] – config : Chemin du fichier de configuration [/WEB-INF/strutsconfig.xml] – content : Type MIME des pages [text/html] © Paramètres d’initialisation (2) Développer le contrôle Web.xml Paramètres d’initialisation Applications Struts 85 – debug : Niveau de détail des traces de la servlet [0] – detail : Niveau de détail des traces du Digester [0] – maxFileSize : La taille maximale d’un fichier accepté lors d’un upload de fichier [250M] – nocache : Ajoute un header HTTP à chaque réponse pour qu’elle ne soit pas stockée sur le navigateur client [false] © Développer le contrôle Web.xml Mapping servlet de contrôle Configurer le mapping de la servlet de contrôle • Reconnaissance par préfixe <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>/execute/*</url-pattern> </servlet-mapping> – www.softeam.fr/monappli/execute/logon • Reconnaissance par suffixe <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> – www.softeam.fr/monappli/logon.do Applications Struts 86 © Développer le contrôle Web.xml Librairie struts Ex 9 Applications Struts 87 Configurer la librairie de balises struts • Ne configurer que les librairies réellement utilisées – Exemple : <taglib> <taglib-uri> /WEB-INF/struts-bean.tld </taglib-uri> <taglib-location> /WEB-INF/struts-bean.tld </taglib-location> </taglib> • Copier les fichiers .tld nécessaires dans le répertoire WEB-INF © Développer la vue Développer la vue Applications Struts 88 • Struts définit des balises pour gérer les champs de saisie suivants : – – – – – – – – – – Checkboxes Champs cachés Radios bouton Boutons de remise à zéro (« reset») Listes de sélection Options Boutons « submit » Champs de saisie de texte Champs de saisie de mot de passe Zones de texte © Développer le modèle Développer le modèle • Développement d’un ActionForm pour chaque formulaire • La déclaration des classes ActionForm dans le fichier de configuration rend automatique les services : – Vérification de la présence d’une instance de l’ActionForm • Si elle n’existe pas, elle est créée Applications Struts 89 – Pour chaque paramètre de la requête, mise à jour de l’attribut correspondant (setXXX) – Le Bean est ensuite passé en paramètre de la méthode execute © Les classes ActionForm Développer le modèle • Aucun développement de méthode spécifique – Pour chaque champ de saisie un getter et setter • Utiliser la méthode validate pour vérifier que tous les champs sont bien remplis Ex 10-12 Applications Struts 90 – Validité des informations saisies • Un formulaire n’est pas limité à une seule JSP © Les DynaActionForm (1) Développer le modèle • Struts utilisait des objets ActionForm pour stocker les valeurs des formulaires HTML – Pour chaque formulaire => une classe dérivée de ActionForm. – Lourd puisque pour chaque champ xx, il faut écrire deux méthodes setXx et getXx. • Struts nous offre la possibilité d'utiliser des formulaires dont la structure est déclarée dans le fichier struts-config.xml dans la section <form-beans> Applications Struts 91 – Créés dynamiquement par l'environnement Struts selon la structure déclarée © Les DynaActionForm (2) Développer le modèle • Dans struts-config.xml <form-beans> <form-bean name="frmPersonne" type="org.apache.struts.actions.DynaActionForm"> <form-property name="nom" type="java.lang.String" initial=""/> <form-property name="age" type="java.lang.String" initial=""/> </form-bean> </form-beans> Applications Struts 92 © Développer le modèle Validation des données d’un formulaire (1) • Struts offre deux mécanismes de validations des données saisies dans les formulaires – Le plug-in Validator – La méthode validate() des ActionForms. • Par validation, on entend deux choses : – Validation dite de « contrôle de surface » ou qualitative • Vérifier que les données saisies sont bien dans la forme attendue (ex : une donnée numérique ne contient que des chiffres) – Validation sémantique : Applications Struts 93 • Vérifier que la valeur saisie est bien celle qui est attendue par le système (ex : un numéro de carte bleue valide) © Développer le modèle Validation des données d’un formulaire (2) • Les deux systèmes sont à même de faire les deux, mais on utilise usuellement: – Le plug-in Validator pour les controles de surface, puisqu'il ne nécéssite pas d'allerretour entre le client et le serveur – La méthode validate() des ActionForms pour la validation sémantique Applications Struts 94 © Méthode validate() (1) Développer le modèle • Struts offre un mécanisme basique de validation des saisies utilisateurs • Pour utiliser ce mécanisme, il faut surcharger la méthode « validate » public ActionErrors validate( ActionMapping mapping, HttpServletRequest request); Applications Struts 95 © Méthode validate() (2) Développer le modèle • La méthode est appelée par la servlet de contrôle après que les propriétés de l’ActionForm aient été remplies – Avant l’appel à execute de la classe Action • Validate retourne – null si la validation est OK – Une instance de la classe ActionErrors contenant les ActionError sinon – Les messages d'erreurs sont alors affichés grâce à la balise <html:errors/> Applications Struts 96 © Méthode validate() (3) Développer le modèle • En cas d’erreur, le contrôle est donné à l’URL spécifiée par l’attribut « input » de l’action <action path="/logon" type="org.apache.struts.example.LogonAction" name="logonForm" scope="request" input="/logon.jsp" validate="true"> <forward name="success" path="/main.jsp"/> </action> Ex 13 Applications Struts 97 © Validation des DynaActionForm (1) Développer le modèle • Dans struts-config.xml <form-beans> <form-bean name="frmPersonne" type="com.softeam.struts.actions.PersonneDynaForm"> <form-property name="nom" type="java.lang.String" initial=""/> <form-property name="age" type="java.lang.String" initial=""/> </form-bean> </form-beans> Applications Struts 98 ©public class PersonneDynaForm extends DynaActionForm { public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { // gestion des erreurs ActionErrors erreurs = new ActionErrors(); Développer le // le nom doit être non vide modèle String nom = (String)this.get("nom"); if (nom == null || nom.trim().equals("")) { erreurs.add("nomvide", new ActionError("personne.formulaire.nom.vide")); } // l'âge doit être non vide String age = (String)this.get("age"); if (age == null || age.trim().equals("")) { erreurs.add("agevide", new ActionError("personne.formulaire.age.vide")); } else { // l'âge doit être un entier positif if (!age.matches("^\\s*\\d+\\s*$")) { erreurs.add("ageincorrect", new ActionError("personne.formulaire.age.incorrect", age)); // on rend la liste des erreurs } } //if // on rend la liste d'erreurs return erreurs; } Applications Struts }//classe 99 © Utilisation avancée Applications Struts 100 © Internationalisation via Struts Internationalisation • Définition de fichiers de ressources – Un fichiers par langue – Tous les noms de fichiers de ressources devront avoir le même préfixe – Spécifié dans le fichier web.xml Applications Struts 101 © Internationalisation Définition des fichiers de ressources • Dans le répertoire classes de l’application Web – Paires de données clé/valeur – L’application référence les clés afin d'injecter les valeurs associées • Exemple – ApplicationResources = fichier par défaut Applications Struts 102 Fichier "ApplicationResources.properties" CaddieVirtuel.Test.Title=Virtual Caddy Fichier "ApplicationResources_fr.properties" CaddieVirtuel.Test.Title=Caddie Virtuel © Internationalisation Déclaration des fichiers de ressources (1) • web.xml : Paramètre application : base des noms de fichiers de ressources <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>application</param-name> <param-value>ApplicationResources</param-value> Applications Struts </init-param> <load-on-startup>2</load-on-startup> </servlet> 103 © Déclaration des fichiers de ressources (2) • struts-config.xml : tag messageresources : base des noms de fichiers de ressources <message-resources parameter="foo.bar.MyResourceBundle"/> Applications Struts 104 © Utilisation des ressources Internationalisation • Utilisation du <html:html> – Paramètre locale à true <html:html locale="true"> <!-- Suite de la page --> Injection d'une valeur : <bean:message key="searchKey" /> <!-- Suite de la page --> </html:html> Applications Struts 105 © Internationalisation Changer de langue à la demande avec Struts (1) • Créer une action qui va mettre à jour la locale dans l'objet request. . href="switch.do?lang=fr&cty=FR">FR</html:link> <html:link <html:link href="switch.do?lang=en&cty=EN">EN</html:link> <html:link href="switch.do?lang=en&cty=US">US</html:link> Applications Struts 106 © Internationalisation public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException { //récupération des paramètres passés et de l'url du referer String country = request.getParameter("cty"); String language = request.getParameter("lang"); String source = request.getHeader( "REFERER"); HttpSession session = request.getSession(); ActionForward forward = null; // définition de la locale setLocale( request, new Locale( language, country ) ); // redirection vers une page définie par défaut if( source==null ) { forward = (mapping.findForward("success")); } // redirection vers l'url du referrer. else { forward = new RedirectingActionForward(); forward.setPath( source ); } Applications Struts 107 return forward; © Factoriser plusieurs actions (1) DispatchAction • Réaliser plusieurs actions sur un même formulaire – Par exemple, pour la gestion d'un panier virtuel, il est possible d'ajouter, de modifier ou de supprimer un élément • DispatchAction concentre en une seule action, l'ensemble des opérations réalisables sur une seule JSP Applications Struts 108 © Factoriser plusieurs actions (2) DispatchAction • On utilise un simple JavaScript qui modifie la valeur d'un champ caché lors de la soumission <SCRIPT> function setHidden(value){document.formulaire.hidden.value=value;} </SCRIPT> • Dans le formulaire <html:form name="formulaire"> ... <html:hidden property="hidden" value="default"/> ... <html:submit onclick="setHidden('add');">ADD ELEMENT</html:submit> Applications Struts </html:form> 109 © Factoriser plusieurs actions (3) DispatchAction • Dans l'Action concernée – Les méthodes portent les mêmes noms que les valeurs du champs hidden (à la place de la méthode execute(...)) public class CartAction extends DispatchAction { public ActionForward add(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { ... } public ActionForward remove(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { ... } public ActionForward modify(ActionMapping mapping, ActionForm form, request, HttpServletResponse response) ApplicationsHttpServletRequest Struts throws IOException, ServletException { ... } } 110 © Factoriser plusieurs actions (4) DispatchAction • Dans struts-config.xml – Ajouter à la déclaration de l'action l'attribut "parameter" et lui indiquer le nom du champ concerné <action path="/cartManagement" type="app.management.CartAction" name="cartForm" scope="request" validate="true" parameter="hidden"/> Applications Struts 111 © Factoriser plusieurs actions (5) LookupDispatchAction • LookupDispatchAction – Si JavaScript n'est pas actif ou pas souhaité(le DispatchAction ne peut fonctionner) – Reprends le mécanisme du DispatchAction Applications Struts 112 © Factoriser plusieurs actions (6) LookupDispatchAction • Dans le struts-config.xml – Déclaration du nom du bouton de soumission qui doit être "submit". <action path="/cartManagement" type="app.management.CartAction" name="cartForm" scope="request" validate="true" parameter="submit"/> Applications Struts 113 © Factoriser plusieurs actions (7) LookupDispatchAction • Dans la JSP, les boutons sont nommés grâce à une clé du ResourceBundle <html:form ...> <html:submit> <bean:message key="button.add"/> </html:submit> <html:submit> <bean:message key="button.delete"/> </html:submit> </html:form> Applications Struts 114 – Les valeurs passées sont ainsi localisées et changent donc en fonction de la locale © Factoriser plusieurs actions (8) LookupDispatchAction • Ajouter à l'Action une méthode qui est appelée lors de la soumission – Mapping des valeurs à une méthode particulière Applications Struts 115 protected Map getKeyMethodMap( ActionMapping mapping, ActionForm form, HttpServletRequest request) { Map map = new HashMap(); map.put("button.add", "add"); map.put("button.delete", "delete"); return map; } © Plug-in Plug_in • Moyen simple d’étendre Struts • Implémenter l’interface org.apache.struts.action.PlugIn – void destroy() – void init(ActionServlet servlet, ModuleConfig config) Applications Struts 116 • Peut être utilisé pour l’initialisation d’une application • Ex.: Validator et Tiles sont configurés de cette façon © Le plug-in Validator (1) Plug-in Validator • Validation avancée de formulaires – Validation coté client (Javascript) – Validation coté serveur • Seul moyen pour valider des DynaActionForm • Plus complet et plus souple que la validation de base • Cet environnement vient • Livré avec Struts Applications Struts 117 – commons-validator.jar et jakarta-oro.jar © Le plug-in Validator (2) Plug-in Validator • Pour utiliser le validator, il faut : – Que le plug-in validator soit déclaré dans le struts-config.xml – Que l'ActionForm hérite de ValidatorForm – Que la page JSP intègre le tag <html:javascript>. – Qu'une règle de validation soit définie dans le fichier xml de validation Applications Struts 118 © Le plug-in Validator (3) Plug-in Validator ActionForm DynaActionForm ValidatorForm Applications Struts 119 DynaValidatorForm © Le plug-in Validator (4) Plug-in Validator • Configuration à l’aide de deux fichiers – validator-rules.xml • Définition de règles réutilisables de validation – validation.xml • Défintion de l’application des règles, par formulaire – Un certain nombre de règles pré-définies livrées avec Struts: • required, minlength, maxlength, mask, date, … Applications Struts 120 © Le plug-in Validator (5) Plug-in Validator • Dans struts-config.xml <form-beans> <form-bean name="frmPersonne" type="org.apache.struts.validator.DynaValidatorForm"> <form-property name="nom" type="java.lang.String" initial=""/> <form-property name="age" type="java.lang.String" initial=""/> </form-bean> </form-beans> . . . <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/> </plug-in> Applications Struts 121 © Le plug-in Validator (6) Plug-in Validator • le validateur chargera : – validator-rules.xml est le fichier définissant les contraintes d'intégrité standard – validation.xml est le fichier définissant les contraintes d'intégrité des différents formulaires dynamiques de l'application. • Ces deux fichiers peuvent être placés n'importe où sous WEB-INF Applications Struts 122 © Le plug-in Validator (7) Plug-in Validator Applications Struts 123 • Dans validation.xml <form-validation> <global> <constant> <constant-name>entierpositif</constant-name> <constant-value>^\s*\d+\s*$</constant-value> </constant> </global> <formset> <form name="frmPersonne"> <field property="nom" depends="required"> <arg0 key="personne.nom"/> </field> <field property="age" depends="required,mask"> <arg0 key="personne.age"/> <var> <var-name>mask</var-name> <var-value>${entierpositif}</var-value> </var> </field> </form> </formset> </form-validation> © Le plug-in Validator (8) Plug-in Validator Applications Struts 124 • <form-validation> l'ensemble des règles • <global> sert à définir des informations à portée globale, c.a.d. valable pour tous les formulaires • Une constante est définie par son nom (balise <constant-name>) et sa valeur (balise <constant-value>) © Le plug-in Validator (9) Plug-in Validator • <formset> définit l'ensemble des formulaires pour lesquels il y a des contraintes d'intégrité à vérifier • <form name="unFormulaire"> sert à définir les contraintes d'intégrité d'un formulaire – Ce nom doit exister dans la liste des formulaires définis dans struts-config.xml • <form> contient autant de balises <field> que de contraintes d'intégrité à vérifier pour le formulaire • <field> a les attributs suivants : – property : nom du champ du formulaire pour lequel on définit des contraintes d'intégrité – depends : liste des contraintes d'intégrité à vérifier Applications Struts 125 © Le plug-in Validator (10) Plug-in Validator Applications Struts 126 • les contraintes possibles sont les suivantes : – required (le champ doit être non vide), – mask (la valeur du champ doit correspondre à une expression régulière,définie par la variable mask), – integer : la valeur du champ doit être entier, – byte (octet), – long (entier long), – float (réel simple), – double (réel double), – short (entier court), – date (la valeur du champ doit être une date valide), – range (la valeur du champ doit être dans un intervalle donné), – email : (la valeur du champ doit être une adresse mél valide), ... © Upload de fichiers (1) Upload des fichiers • Formulaire HTML : doit être de type « multipart » <html:form action="/upload.do?from=sender" method="post" enctype="multipart/form-data"> <html:file property="fichier"/> ... </html:form> Applications Struts 127 © Upload de fichiers (2) Upload des fichiers • Récupération automatique par Struts du contenu du fichier dans le form bean public class UploadActionForm extends ActionForm { protected FormFile file; public FormFile getFile() { return file; } public void setFile(FormFile file) { this.file = file; } ... Applications Struts } 128 © Datasource (1) Datasource • Pas recommandé de gérer la persistance des données dans la couche de présentation – il peut être utile d'accéder aux datasources • Tag <data-source> dans le fichier struts-config.xml Applications Struts 129 © Datasource (2) Datasource • Dans struts-config.xml <data-sources> <data-source key="FirstDataSource" type="org.apache.commons.dbcp.BasicDataSource"> <set-property property="driverClassName" value="org.postgresql.Driver" /> <set-property property="url" value="jdbc:postgresql://localhost/mydatabase" /> ... </data-source> <data-source key="SecondDataSource" type="org.apache.commons.dbcp.BasicDataSource"> ... Applications Struts </data-source> </data-sources> 130 © Datasource (3) Datasource • Dans les actions ... try { dataSourceA = getDataSource(request, "FirstDataSource"); myConnection = dataSourceA.getConnection(); ... dataSourceB = getDataSource(request, "SecondDataSource"); ... } ... Applications Struts 131 © Modules Modules Applications Struts 132 • Découpage d’une application en sousmodules • Facilite le développement / la maintenance • Un fichier de configuration par module • Navigation inter-modules possible • Pas de perte de contexte (session, application, …) © Modules (2) Modules • Déclaration des modules auprès de la servlet controleur (web.xml) <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>config/module1</param-name> <param-value>/WEB-INF/struts-config-module1.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> Applications Struts 133 © Modules (3) Modules • Navigation inter-module : attribut « contextRelative » d’une définition de « forward » <action ... > <forward name="success" contextRelative="true" path="/moduleB/index.do" redirect="true"/> </action> Applications Struts 134 © Gestion des exceptions Gestion des exceptions • Possibilité de spécifier des gestionnaires globaux d’exceptions • Doivent hériter de org.apache.struts.action.ExceptionHandler <global-exceptions> <exception type="java.io.IOException" handler="org.apache.struts.example.ExceptionHandler"/> </global-exceptions> Applications Struts 135 • Toute exception non catchée dans une action sera traitée par le gestionnaire correspondant © Conclusion Applications Struts 136 © Les contre Les pour et contre • Framework générique – Conçu pour répondre à tous les besoins, il offre de nombreuses fonctionnalités dont on n’a pas forcément besoin • Framework open source – Pas de support, mises à jour sporadiques Applications Struts 137 © Les pour Les pour et contre • Framework open source (Apache) – Gratuit, évolutif, adaptable • Respect de la séparation entre présentation (JSP) et contrôle du dialogue (Actions) – Excluant autant que possible code dans les JSPs Applications Struts 138 • Pool de connexions intégré • Richesse des taglibs • Flexibilité grâce à la configuration à base de fichiers XML • Internationalisation simple à mettre en oeuvre © Alternatives à Struts Alternatives à struts • Produits commerciaux : – Barracuda • Open source : – – – – – – Applications Struts 139 Cocoon Maverick Tapestry WebWork Jakarta Turbine Java Server Faces • Basés sur Struts : – Expresso