Struts 1 & 2 Tlohi ibtissam Tabit boutaina Ilias bouras Réalisé par : Tlohi ibtissam Tabit boutaina Ilias bouras Elouakyly hajar Kharmouch fatima ezzahra Encadré par: MR Ali ELHORE
INTRODUCTION
Plan: introduction Rappel sur MVC Struts 1: Définition Struts1 et MVC2 Composants ActionServlet Action ActionForm DynaActionForm ActionErrors / ActionMapping Struts-config.xml Struts2: Struts1 VS Struts2 Filtre Inercepteur Struts.xml Exemple
Rappel MVC:
Struts1
Struts 1: Définition Struts est un Framework MVC utilisé pour développer des applications WEB. Il s’agit donc d’un squelette d’application s’appuyant sur le modèle vue contrôleur et fournissant des outils supplémentaires pour aider le développeur à réaliser ses applications. Un framework : architecture et ensemble d’outils de development
Struts1 et le MVC2 Struts s’appuie en réalité sur le MVC2, on distingue donc un contrôleur principal qui aiguille les requêtes reçues du client vers des sous contrôleurs qui vont alors effectuer le traitement correspondant. Les 3 composants : Le modèle : Struts ne fournit aucune implémentation pour le modèle. Le développeur doit donc définir lui-même le(s) modèle(s). En revanche, cela permet d’appliquer la couche ‘Struts’ à n’importe quel projet déjà existant. Les vues : dans Struts, ce sont principalement des pages JSP. Pour cela, Struts fournit plusieurs bibliothèques de ‘taglibs’ permettant de réaliser les pages JSP rapidement. Le contrôleur : Struts implémente un contrôleur principal (représenté par la classe ActionServlet) et des sous contrôleurs (correspondant aux classes Action).
Schéma explicatif: Le schéma ci-dessous représente la structure de Struts et son fonctionnement.
Composants du struts1 : ActionServlet : c’est le contrôleur principal. Il joue le rôle de servlet et reçoit donc les requêtes du client qu’il renvoie ensuite vers les sous contrôleurs. Action : il s’agit des sous contrôleurs. Ils effectuent le traitement correspondant à une requête précise. ActionForm : ce sont des conteneurs pour les pages JSP. Ils peuvent être utilisés par les Action lors du traitement. Le fichier de configuration ‘Struts-config.xml’ : C’est le composant principal de Struts puisqu’il permet de faire le lien entre tous les composants précédents.
Cycle de vie d’une opération : Le client envoie une requête à l’ActionServlet. Grâce au fichier de configuration ‘Struts-config.xml’, l’ActionServlet aiguille la requête vers l’Action appropriée. L’Action réalise alors le traitement adéquat. Si besoin, cette Action utilise les ActionForm nécessaires et effectue les opérations utiles sur le modèle. L’action renvoie ensuite le résultat du traitement (réussite, échec…) a la servlet A partir de cette valeur, la servlet est alors capable de déterminer le résultat à renvoyer au client (redirection vers une autre page JSP…).
Le contrôleur principal : l’ActionServlet Comme son nom l’indique, il s’agit d’une servlet. Celle-ci reçoit toutes les requêtes du client et dispache ensuite ces requêtes vers les sous contrôleur grâce aux informations contenues dans le fichier de configuration ‘Struts-config.xml’. Une application Struts contient généralement une seule implémentation de la classe ActionServlet. Il s’agit alors de la servlet principale de notre application, et comme pour toute application WEB, cette servlet doit être déclarée et instanciée dans le fichier ‘web.xml’.
Déclarer la servlet principal dans Web.xml: <web-app> <servlet> <servlet-name> action <servlet-name> <servlet-class>org.apache.struts.action.ActionServlet </servlet-class> … </servlet> <servlet-mapping> <servlet-name> action </sevlet-name> <url-pattern> *.do </url-pattern> </servlet-mapping> </web-app>
Ici, la balise servlet mapping permet de préciser que toutes les requêtes se terminant par ‘.do’ devront être traitées par la servlet action (instance de ActionServlet). L’ActionServlet sert ensuite de ‘Factory’ pour les sous contrôleurs (Action) puisqu’elle instancie les Actions en fonction des requêtes reçues et par rapport au ficher de configuration ‘Struts-config.xml’. Dans la majeure partie des cas, ce mécanisme est automatique et transparent pour l’utilisateur qui doit seulement implémenter les sous contrôleurs et renseigner le fichier de configuration de Struts. Il est possible d’étendre de la classe ActionServlet pour définir son propre contrôleur principal et ainsi personnaliser ses actions
Les sous contrôleurs : les Actions La classe Action va nous permettre de définir un traitement spécifique. Le développeur doit donc étendre de cette classe afin d’implémenter les différents sous contrôleurs de l’application. Cette classe définie une méthode execute() qui est automatiquement appelée par le contrôleur principal lorsque le traitement doit être effectué. Le développeur peut donc redéfinir cette méthode pour effectuer les opérations nécessaires (traitement, interactions avec un modèle…). Chaque Action créée doit être déclarée dans le fichier de configuration struts-config.xml grâce à la balise <action-mappings> au moyen de la balise <action>
Déclaration du sous-contrôleur dans struts-config Déclaration du sous-contrôleur dans struts-config.xml : (requête sans paramètre ) <action path=‘’/actionPerso’’ Input= ‘’ /index.jsp’’ Name=‘’MyForm’’ // Facultatif Type=‘’myPackage.MyAction’’ > <forward name=‘’action_failed’’ path = ‘’ /inedx.jsp ‘’ /> <forward name=‘’action_ok’’ path=‘’/autre.jsp’’ / > </action> ---------------------------------------------------------------------------------------- ------ path: représente le chemin d’accès de la requête(L’URL)il est utilisé pour désigner l’action à appeler (il doit être unique et commencer par ‘/’). input: permet de spécifier la page retournée en cas d’erreur. name: correspond au nom de l’ActionForm utilisé pour effectuer l’action (il s’agit du nom de l’instanciation également déclaré dans le fichier de configuration). type: indique le nom de la classe Action qui fera le mapping
Déclaration du sous-contrôleur <forward name="action_failed" path="/index.jsp" /> <forward name="action_ok" path="/autre.jsp" /> ----------------------------------------------------------- ----------- Les éléments forward reprennent les différentes valeurs pouvant être retournées par l’action et définissent la redirection associée. Ce composant est utilisé par l’ActionServlet pour renvoyer un résultat au client
Déclaration du sous-contrôleur dans struts-config Déclaration du sous-contrôleur dans struts-config.xml : (requête avec paramètre ) Si la requête envoyée par le client comprend des paramètres, La balise <action> dispose, en plus des attributs mentionnés ci-dessus, les attributs suivants: String scope: préciser la portée de l’objet ActionForm instancié par la servlet (request , session, application…) String name: nom de l’objet de type ActionForm qui va encapsuler les données contenues dans la requête. String validate: permet de préciser si la validation des données sera faite par appel de validate() ou non. (par défaut = true) String input: la page affichée en cas d’échec de validation des données.
Les conteneurs : les ActionForm Si la requête du client contient des paramètres, ceux- ci sont transmis dans un objet de type ActionForm. Un objet de type ActionForm est un objet qui permet de mapper automatiquement les données saisies dans une page HTML avec les attributs correspondants dans l'objet. Il peut aussi réaliser une validation des données saisies par l'utilisateur. Comme pour les Action, le développeur étend de cette classe pour créer ses propres conteneurs.
Classe ActionForm C'est la servlet faisant office de contrôleur qui instancie un objet de type ActionForm et alimente ses propriétés avec les valeurs contenues dans la requête émise à partir de la page. Chaque paramètre du formulaire est défini comme une propriété de l'objet ActionForm associé qui doit être un JavaBean Pour chaque donnée, il faut définir un attribut private ou protected qui contiendra la valeur, un getter et un setter public , il faut définir un attribut private ou protected qui contiendra la valeur, un getter et un setter public Proprietés Accesseur du parametre Modificateur du parametre
Reset (): Peut être redéfinie pour initialiser les attributs à chaque nouvelle instanciation de l’objet ActionForm. ------------------------------------------------------------------------------------- public void reset(ActionMapping mapping, HttpServletRequest request) { this.mdpUtilisateur = null; this.nomUtilisateur = null; } ------------------------------------------------------------------------------------------- NB: La classe ActionMapping encapsule les données définies dans un tag <Action> du fichier de configuration.
Validate () : peut être redéfinie pour permettre de réaliser des traitements de validation des données contenues dans l'ActionForm. Elle renvoie une instance de la classe ActionErrors qui encapsule les différentes erreurs détectées ou renvoie null si aucune erreur n'est rencontrée. ------------------------------------------------------------------------------------------------ public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { Redéfinition de la méthode validate ActionErrors errors = new ActionErrors(); Création d'un objet erreur vide if ((nomUtilisateur == null) || (nomUtilisateur.length() == 0)) errors.add("nomUtilisateur",new ActionError("erreur.nomutilisateur.obligatoire")); Selon le paramètre ajout de message d'erreur if ((mdpUtilisateur == null) || (mdpUtilisateur.length() == 0)) errors.add("mdpUtilisateur", new ActionError("erreur.mdputilisateur.obligatoire")); Selon le paramètre ajout de message d'erreur return errors; Renvoie des erreurs (vide si la validation a réussi) }------------------------------------------------------------------------------------------------- NB: Si validate vaut « true » et que l’objet ActionErrors n’est pas null le contrôleur redirige vers la vue de l’attribut input
Déclaration de l’ActionForm: Les ActionForm ne contiennet aucun traitement métier. les ActionForm doivent être déclarés dans le fichier de configuration struts-config.xml à l’aide des lignes suivantes : ----------------------------------------------------------- ------------- <form-beans type="org.apache.struts.action.ActionFormBean"> <form-bean name="loginForm" type="com.jmd.test.struts.data.LoginForm" /> </form-beans> Mon objet ActionForm Ma classe ActionForm
ActionForms VS DynaActionForm Les objets ActionForm sont des Beans qui permettent de stocker des propriétés statiques et de les valider il faut redéfinir à chaque fois des «get» et des «set» pour les propriétés La solution est d’utiliser des formulaires: dont la structure est déclarée dans le fichier struts- config.xml qui sont créés dynamiquement par l’environnement Strut Utilisation de la classe DynaActionForm Modification de la balise <form-bean>
Class DynaActionForm: Elle possède la même méthode validate() que ActionForm: Utilise Les méthodes: get(String): donne la valeur de la proprieté donnée en paramètre: String ma_prop= (String)this.get(“nom”); Set(String, object): modifie la valeur de la proprieté donnée en paramètre
Les DynaActionForm doivent obligatoirement être déclarés dans le fichier de configuration struts-config.xml: ---------------------------------------------------------------------------- <form-beans> < form-bean name="NomDuFormulaire" type="org.apache.struts.action.DynaActionForm " > <<form-property name="reference" type="java.lang.String <form-property name="libelle" type="java.lang.String"/> <form-property name="prix" type="java.lang.String" initial="0 “ /> </form-bean> </form-beans>
Le fichier de configuration: struts-config.xml Ce fichier est le descripteur de déploiement, il permet de faire le lien entre les différents composants de Struts. Il permet de déclarer les différents éléments, dont : - les beans du formulaire (ActionForm) - les Actions - les ressources - les redirections… Il est placé dans le répertoire WEB-INF au même niveau que web.xml La balise de départ est <struts-config>
intégration dans l’application web Ce fichier de configuration est précisé et est déclaré dans le fichier web.xml de l’application à l’aide des lignes suivantes : (à ajouter dans la balise <servlet > ) ------------------------------------------------------------------------- <init-param> <param-name> config </param-name> <param-value> /WEB-INF/struts-config.xml </param-value> </init-param>
Description du mécanisme: L'ActionServlet, après avoir reçue une requête effectue les actions suivantes : Instancie un objet de type ActionForm et alimente ses données avec celles correspondantes dans la requête Appel de la méthode validate de la classe LoginForm pour valider les données saisies par l'utilisateur (stocker) Détermination de l'Action à utiliser en fonction des informations contenues dans le fichier struts-config.xml. Appel de la méthode execute() de la classe LoginAction qui contient les traitements à effectuer pour répondre à la requête. Elle renvoie un objet de type ActionForward L'ActionServlet détermine la page à afficher à l'utilisateur en réponse en fonction de la valeur renvoyée par la méthode execute() et des informations du fichier de configuration La page déterminée est retournée au navigateur de l'utilisateur pour être affichée
Struts 2
Struts 2: Définition Struts 2 est aussi un Framework , et qui vient pour palier au problème de compatibilité ascendante qui a freiné l’évolution de struts1. Ce Framework est plus puissant que struts 1 et offre plus de fonctionnalités et de souplesse. Mais contrairement a ce qu’on peut penser il n’a de commun avec struts 1 qu’une partie du nom n'est pas une extension ou une autre version de Struts 1. Struts 2 est un résultat d'association entre Struts1 et Webwork. En effet, les deux frameworks ont été fusionnés pour créer le framework Struts Titanium qui devient rapidement Struts 2 apportant la puissance du Webwork et la popularité de Struts 1.
Cycle de vie d’une requête HTTP 1) Le client envoie des requêtes à partir d’URLs adaptées. Il peut éventuellement envoyer des paramètres dans l’URL ou par l’intermédiaire d’un formulaire de saisie 2) Struts consulte son fichier de configuration struts.xml afin de retr ouver la configuration de l’action 3) Chaque intercepteur associé à l’action est déclenché. L’ un de ces intercepteurs est chargé d’assigner automatiquem ent les valeurs reçues dans la requête aux propriétés de la classe d ’action, en fonction des noms (ex : identifiant, motdepasse). 4) Struts exécute la méthode d’action associée à la classe. 6)l’intercepteur vérifie le résultat retourner par l’action. 6) Le résultat adapté est retourné à l’utilisateur demandeur.
Struts2: Architecture
Dans le fichier web.xml (fichier de configuration générale de l’application) on configure le filtre par lequel passeront toutes les requêtes (/*)associées à l’application. Ce dernier va analyser systématiquement le fichier struts.xml ,(fichier de configuration de struts) pour voir les intercepteurs associée a la requête . web.xml et Filtre
Login-validate.xml et Filtre Analyse du contenu du fichier Login- validate.xml.
Intercepteur: Définition Un intercepteur (interceptor) Struts est un filtre qui peut effectuer différents traitements sur une action. Le code présent dans un intercepteur est modulable et peut être ajouté ou supprimé directement dans le fichier de configuration struts.xml. Il est juste nécessaire de comprendre qu’un intercepteur est un filtre jouant un rôle spécifique et permet par exemple de gérer les cookies, paramètres HTTP, le débogage, le chargement de fichiers (upload) .
Struts.xml Une application Struts possède un fichier de configuration Dans Ce fichier nous allons définir la configuration générale de struts2 : Les paramètres de configuration de Struts. Les actions. Les intercepteurs. Les résultats des actions. Le fichier struts.xml permet de configurer le mapping entre l’URL et l’implémentation de l’action. Ce fichier doit être dans le dossier /WEB-INF
Les Actions: Dans Struts2 les beans formulaires « ActionForm » ont disparu. Ils se retrouvent directement intégrés aux classes Action. Les actions struts 2 héritent de la classe ActionSupport
Les Action:
Struts2: Exemple
Description du mécanisme (Exemple): La page d’authentification: (Login.jsp)
Intercepteur: (vérifier la validité de l’authentification d’un utilisateur) -------------------------------------------------------------------------------- ---------------------- public class AuthenticationInterceptor implements Interceptor { public String intercept(ActionInvocation actionInvocation) { if (isAuthenticated(user)) { // Authentication OK return actionInvocation.invoke(); } else { // Redirection sur la page de login return Action.LOGIN; }
Déclaration de l’intercepteur dans Strut.xml L’intercepteur est défini dans le fichier de configuration (struts.xml par défaut) et est appliqué au sein de ce même fichier sur chaque action : < interceptors> < interceptor name=“authentication” class=“project.interceptors.AuthenticationInterceptor”/> < /interceptors> < action name=“Login” class=“example.Login”> < interceptor-ref name=“authentication”/> < result name="input"> /example/Login.jsp < /result> < result name="error"> /example/Erreurjsp < /result> < result> /example/affichageAnnuaire.jsp < /result> < /action> On a la possibilité de déclarer plusieurs action, ceci doit être inclus dans une balise <package> qui a les attributs suivant: Les attributs de la balise <package/> sont les suivants : name : attribut obligatoire précisant le nom du paquetage. namespace : attribut précisant l’espace de nommage pour toutes les actions du paquetage. extends : attribut obligatoire précisant le paquetage parent à hériter. abstract : attribut peu utilisé précisant si le paquetage peut être hérité ou non.
Description du mécanisme (Exemple): La classe Login.java ( l’action): Struts s'aperçoit que le fichier java associé à cette action est Login.java qui se trouve dans le dossier example (example.Login). Cette classe étend la classe ActionSupport et doit donc implémenter la méthode "execute( )". C'est cette méthode qui est appelée lorsque l'on clic sur le bouton.
Description du mécanisme (Exemple): Execute ():Cette méthode effectue le travail demandé (dans notre cas, elle vérifie le login et le mot de passe) puis renvoie un résultat. Dans notre cas, il y a 2 résultats possibles: "ERROR" et "SUCCESS", mais il peut y en avoir autant que l'on souhaite: Si execute() retourne ERROR, Struts nous renverra sur la page Erreur.jsp Si execute() retourne SUCCESS qui est le retour par défaut, Struts nous renverra sur la page affichageAnnuaire.jsp
Description du mécanisme (Exemple): la ligne < result name="input"> /example/Login.jsp< /result> Struts appelle la méthode execute() par le biais d'une requête. Mais cette requête est d'abord "filtrée" par des intercepteurs pour savoir si la requête contient des erreurs. Si il y a une erreur, l'intercepteur retournera un résultat, tout comme le fait la méthode execute() sinon, il laisse la requête effectuer son travail (et donc appeler la méthode execute()). Dans notre cas, les intercepteurs vont repérer si les champs ont été saisis correctement. Si un champ n'a pas été rempli ou a mal été rempli, l'intercepteur retourne "INPUT".
Cycle de vie d’une requête HTTP
Struts1 VS Struts 2 Classes d'actions Tests Struts1 oblige à hérite de classes abstraites dont nos classes actions doivent hériter, ce qui créé une dépendance forte avec Struts. Dans la version 2, Struts utilise des interfaces que nous pouvons implémenter ou non. Struts2 fournit une interface « ActionSupport » permettant de profiter de la plupart des fonctionnalités nécessaires. Mais ces implémentations ne sont pas obligatoires. Tests Le plus grand défaut de Struts1 sur le test est que sa classe a besoin de l'API Servlet.Afin de tester ses actions, Struts2 instancie l'objet, définit les attributs et invoque les méthodes. Ceci est appelé l'injection de dépendance et permet une plus grande capacité aux tests.
Dépendances aux Servlets De manière globale, dans tout projet Java, l'objectif est de réduire au minimum les dépendances du projet à des frameworks ou autre classes et API. Les actions dans Struts1 sont dépendantes de l'API Servlet puisque leurs méthodes reçoivent en paramètre les objets HttpServletRequest et HttpServletResponse. Le servlet d'applications ne considère pas les actions Struts comme une Servlet. Les contextes de Servlet sont le plus souvent représentées par de simples Map dans une action. Les actions Struts2 peuvent tout de même avoir accès aux objets de requêtes et de réponses originaux si besoin. Cette architecture permet de s'affranchir de la dépendances aux classes HttpServletRequest et HttpServletResponse.
Gestion des saisies Struts 1 gère les saisies via un objet « ActionForm » contenant toutes les informations saisies par l'utilisateur dans le formulaire. Comme les classes action, toutes les classes de gestion de formulaires doivent héritées la classe ActionForm. Tout autre classe de type JavaBean ne peut être utilisé en tant que ActionForm alors que les développeurs pourraient créer des classes personnalisées pour gérer les différentes saisies. DynaBeans est la meilleure alternative pour gérer les classes ActionForm conventionnelles. Dans Struts2, ce sont les attributs de la classe action qui sont utilisés pour les saisies, ils sont définis directement par Struts en utilisant les accesseurs. Ces attributs peuvent être des objets riches puisque ceux-ci peuvent avoir leur propres attributs (utilisateur.identifiant par exemple). Struts2 supporte aussi les ActionForm.
Contrôle du flux d'exécution Conversion de types Les ActionForm de Struts1 ne supportent quasiment que des String. Les classes de BeanUtils sont utilisées pour les conversions de types. Ces dernières sont donc faites par classe, à la main. Struts2 utilise OGNL(Object Graph Notation Language) pour les conversions de type et les converteurs sont capables de convertir tous les types qu'ils soient primitifs ou complexes. Contrôle du flux d'exécution Dans Struts1, chaque module a son propre cycle de vie mais toutes les actions partagent le même cycle de vie. Dans Struts2, des cycles de vie différents sont créés par action avec des piles d'intercepteurs. Des piles personnalisées peuvent être créées et utilisées avec différentes actions, en fonction de vos besoins.
conclusion
Merci pour votre attention