Struts 2

Transcription

Struts 2
Applications Web
STRUTS 2
Framework(s)
STRUTS
Cours IHM
Frédéric MOAL
Université d’Orléans
Master 1ère année
année 2012/2013
1
2
1
Struts 2
Ressources
 “Fusion” de deux frameworks : WebWork 2, avec
Struts.
 But : simplifier les développement.
 Le site officiel :
– http://struts.apache.org/
– lib : liste des librairies
– apps : exemples d’application (vide)
 Struts version 2, http://struts.apache.org/2.3.4.1/
 Tutoriaux developpez.com
– http://tahe.developpez.com/
 Livre « Struts 2 in action » par Donald Brown - Chad
Michael Davis - Scott Stanlick aux éditions Manning
 Différences importantes entre Struts 1 et Struts 2
3
4
2
Struts 2 : Architecture
Struts 2 : extensible par Plugins
5
6
3
De Struts 1 à Struts 2 …
Struts 1
Action
ActionForm
ActionForward
struts-config.xml
ActionServlet
RequestProcessor
Le modèle MVC de Struts 2
Struts 2






Action
Action or POJO’s
Result
struts.xml
FilterDispatcher
Interceptors
7
8
4
MVC de Struts 2 : configuration
MVC de Struts 2 : configuration
 Servlet contrôleur, dans web.xml :
 URLs demandées de la forme
http://machine:port/contexte/rep1/rep2/.../Action
 Définitions des URLs acceptées dans fichier XML :
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"…version="2.5">
Exemple :
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
<package name="actions" namespace="/actions"
extends="struts-default">
<action name="Action1" class="actions.Action1">
<result name="page1">/vues/Page1.jsp</result>
<result name="page2">/vues/Page2.jsp</result>
</action>
</package>
Pour http://machine:port/contexte/actions/Action1
9
10
5
MVC de Struts 2 : fonctionnement
MVC de Struts 2 : fonctionnement
1. Demande "http://machine:port/contexte/actions/Action1"
2. Traitement :
a. le contrôleur C consulte son fichier de configuration et vérifie que
b.
c.
l'action actions/Action1 existe (namespace + name)
le contrôleur C instancie [2a] une classe de type [actions.Action1]
Le nom et le package de cette classe peuvent être quelconques
si l'Url a des paramètres [param1=val1&param2=val2&...], le
contrôleur C affecte ces paramètres à la classe [actions.Action1] :
[actions.Action1].setParami(valeuri)
=> la classe [actions.Action1] doit avoir ces méthodes setParami
pour chacun des paramètres parami attendus
d.
le contrôleur C demande à la méthode [String execute()] de la classe
[actions.Action1] de s'exécuter : elle a accès aux paramètres parami,
et peut avoir besoin de la couche [metier] [2b]. Une fois la demande
du client traitée, celle-ci peut appeler diverses réponses. Un
exemple classique est :
• une page d'erreurs si la demande n'a pu être traitée correctement
• une page de confirmation sinon
e.
La méthode execute rend au contrôleur C un résultat de type chaîne
de caractères appelée clé de navigation. [actions.Action1].execute
peut produire deux clés de navigation "page1" et "page2". La
méthode [actions.Action1].execute va également mettre à jour le
modèle M [2c] que va exploiter la page JSP envoyée en réponse. Ce
modèle peut comporter des éléments de :
• la classe [actions.Action1] instanciée
• la session de l'utilisateur
11
12
6
MVC de Struts 2 : fonctionnement
Exemple simple
3. Réponse
 Le HelloWorld…
le contrôleur C demande à la page JSP correspondant à la clé de
navigation de s'afficher [3]. C'est la vue, le V de MVC. La page JSP
utilise un modèle M pour initialiser les parties dynamiques de la
réponse qu'elle doit envoyer au client.
13
14
7
Struts 2 : clés de navigation
Struts 2 : clés de navigation
 Définies dans struts.xml
 Utilisées dans l’Action :
<struts>
public class Action1 extends ActionSupport{
<package name="default" namespace="/" extends="struts-default">
private String param1="valeur1";
<default-action-ref name="index" />
private String param2="valeur2";
<action name="index">
<result type="redirectAction">
@Override
<param name="actionName">Action1</param>
<param name="namespace">/actions</param>
public String execute(){
</result>
</action>
int i=(int)(Math.random()*2); // choix aléatoire entre deux vues
</package>
if(i==0){
<package name="actions" namespace="/actions" extends="struts-default">
return "page1";
<action name="Action1" class="actions.Action1">
}else{
<result name="page1">/vues/Page1.jsp</result>
return "page2";
<result name="page2">/vues/Page2.jsp</result>
}
</action>
}
</package>
// getters et setters
</struts>
...
15
}
16
8
Struts 2 : clés de navigation
Struts 2 : clés de navigation
 Utilisées dans l’Action :
 Valeurs prédéfinies :
 La définition d’une Action héritant de ActionSupport offre des
constantes prédéfinies de clés de navigation
public class Action1 extends ActionSupport{
private String param1="valeur1";
private String param2="valeur2";
@Override
public String execute(){
Constante
Valeur
int i=(int)(Math.random()*2); // choix aléatoire entre deux vues
SUCCESS
"success"
if(i==0){
ERROR
"error"
INPUT
"input"
LOGIN
"login"
return "page1";
}else{
return "page2";
}
 Plus internationalisation (getText…)
}
// getters et setters
...
}
17
18
9
Exemple simple 2
Exemple simple : struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="false" />
<package name="exemple.actions" namespace="/" extends="struts-default">
<!-- Action de l'action de réference -->
<default-action-ref name="saisir_Personne"/>
<action name="saisir_Personne">
<result>/jsp/saisir_Personne.jsp</result>
</action>
…
19
20
10
Exemple simple : struts.xml
Exemple simple : PersonneAction.java
<action name="enregistrer_Personne" class="exemple.actions.PersonneAction"
method="enregistrer">
<result name="success" >/jsp/enregistrer_Personne.jsp</result>
<result name="input">/jsp/saisir_Personne.jsp</result>
</action>
<action name="lister_Personne" class="exemple.actions.PersonneAction"
method="lister">
<result name="success">/jsp/lister_Personne.jsp</result>
</action>
<action name="supprimer_Personne" class="exemple.actions.PersonneAction"
method="supprimer">
<result name="success">/jsp/lister_Personne.jsp</result>
</action>
Bean Personne + Action :
package exemple.actions;
public class PersonneAction extends ActionSupport {
private int identifiant;
private String pseudo;
private String mail;
private String codePostal;
private java.util.Date dateInscription;
private static ArrayList<Personne> listPersonnes
= new ArrayList<Personne>( );
// getters et setters
</package>
</struts>
21
22
11
Balises d’appels
Exemple simple : PersonneAction.java
public String enregistrer() {
if(this.pseudo.equals("")) {
addFieldError("pseudo", "le pseudo ne doit pas être vide");
return INPUT;
}
Personne pers = new Personne ();
pers.setIdentifiant(identifiant);
pers.setPseudo(pseudo);
pers.setMail(mail);
pers.setCodePostal(codePostal);
pers.setDateInscription(dateInscription);
listPersonnes.add(pers);
return SUCCESS;
}
public String lister(){
return SUCCESS;
}
public String supprimer(){
listPersonnes.removeAll(getListPersonnes());
return SUCCESS;
}
}
23
 Appels depuis une JSP : balises Struts
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><s:text name="formulaire.titre1"/></title>
</head>
<body>
<h1><s:text name="formulaire.titre2"/></h1>
<s:form action="DoSomething">
<s:submit key="formulaire.execute"/>
<s:submit key="formulaire.action1" method="action1"/>
<s:submit key="formulaire.action2" action="DoSomethingElse" method="action2"/>
</s:form>
<s:url id="url" action="DoSomething" method="action3"/>
<s:a href="%{url}"><s:text name="formulaire.action3"/></s:a>
</body>
24
</html>
12
Autre méthode
Autre méthode
 Pour l’accès aux données d’un formulaire, création d’une
classe Data avec UNIQUEMENT les données
 Puis de la classe de Action :
public class Form2 extends ActionSupport implements ModelDriven {
public class Data {
// constructeur sans paramètre
// constructeur sans paramètre
public Data() {
public Form2() {
}
}
// champs du formulaire
// modèle de l'action
private String textfield = "texte";
public Object getModel() {
return new Data();
private String password = "secret";
}
private String textarea = "ligne1\nligne2\n";
}
private String select1 = "zéro";
private String[] select1Values = new String[]{"zéro", "un", "deux"};
…
// valeurs sélectionnées dans champ select3
public String getSelect3SelectedValues() {
return getValue(select3);
} … // getters et setters
25
26
13
Autre méthode
Gestion des sessions
public class Confirmer extends ActionSupport implements SessionAware{
// modèle
private String nom;
// session
private Map<String, Object> session;
 Dans la JSP :
<s:form name="formulaire">
<s:textfield name="textfield" key="Form.textfield" />
<s:password name="password" key="Form.password"/>
// getters et setters
…
@Override
public void setSession(Map<String, Object> session) {
this.session=session;
}
<s:textarea name="textarea" key="Form.textarea" cols="40" rows="5"/>
<s:select name="select1" list="select1Values" size="1" key="Form.select1" headerValue="<--select 1 -->
<s:select name="select2" size="3" list="select2Values" key="Form.select2"/>
<s:select name="select3" size="3" list="select3Values" key="Form.select3" multiple="true"/>
<s:radio name="radio" list="radioValues" key="Form.radio"/>
@Override
public String execute(){
// on met un attribut « nom » dans la session
session.put("nom",nom);
// navigation
return SUCCESS;
}
<s:checkbox name="checkbox" key="Form.checkbox"/>
<s:checkboxlist name="checkboxlist" list="checkboxlistValues“
<s:submit key="Form.submitText" name="submitText"/>
</s:form>
}
27
28
14
Intercepteurs
Intercepteurs par défaut
Avant l’appel à la méthode execute, traverse les
intercepteurs
29
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="debugging"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param
name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
30
15
Intercepteurs utilisation
Intercepteurs exemple
 Utilisés pour la conversion de type et la validation
de paramètres
 Intercepteur Validation : pas appelé si méthode
input, back, cancel ou browse
31
 Déclaration Integer dans Modèle - formulaire
<action name="FormInt" class="example.FormInt">
<result name="input">/example/FormInt.jsp</result>
<result name="cancel“
type="redirect">/example/Accueil.jsp</result>
<result name="success">
/example/OKFormInt.jsp</result>
</action>
32
16
Intercepteurs exemple
Intercepteurs exemple
 Déclaration int dans Modele - formulaire
 Déclaration formulaire
public class FormInt extends ActionSupport implements ModelDriven,
SessionAware {
// constructeur sans paramètre
public FormInt() {
}
// modèle de l'action
public Object getModel() {
if (session.get("model") == null) {
session.put("model", new FormIntModel());
…
// validation
@Override
public void validate() {
// saisie int6 valide ?
if (getFieldErrors().get("int6") == null) {
int int6 = Integer.parseInt(((FormIntModel) getModel()).getInt6());
if (int6 < 2 || int6 > 20) {
addFieldError("int6", getText("int6.error"));
}
}
33
<body background="<s:url value="/ressources/standard.jpg"/>">
<h2><s:text name="FormInt.message"/></h2>
<s:form name="formulaire" action="FormInt">
<s:textfield name="int1" key="int1.prompt"/>
<s:textfield name="int2" key="int2.prompt"/>
<s:textfield name="int3" key="int3.prompt"/>
<s:textfield name="int4" key="int4.prompt"/>
<s:textfield name="int5" key="int5.prompt"/>
<s:textfield name="int6" key="int6.prompt"/>
<s:submit key="Form.submitText" method="execute"/>
</s:form>
<br/>
<s:url id="url" action="FormInt" method="cancel"/>
<s:a href="%{url}"><s:text name="Form.cancelText"/></s:a>
<br/>
<s:url id="url" action="FormInt" method="clearModel"/>
<s:a href="%{url}"><s:text name="Form.clearModel"/></s:a>
</body>
34
17
Intercepteurs exemple
Intercepteurs exemple
 FormInt-validation.xml : chaîne
 FormInt-validation.xml : Integer
<validators>
<validators>
<field name="int1" >
<field-validator type="requiredstring" short-circuit="true">
<message key="int1.error"/>
</field-validator>
<field-validator type="regex" short-circuit="true">
<param name="expression">^\d{2}$</param>
<param name="trim">true</param>
<message key="int1.error"/>
</field-validator>
</field>
<field name="int5" >
<field-validator type="required" short-circuit="true">
<message key="int5.error"/>
</field-validator>
<field-validator type="conversion" short-circuit="true">
<message key="int2.error"/>
</field-validator>
<field-validator type="int" short-circuit="true">
<param name="min">1</param>
<param name="max">10</param>
<message key="int5.error"/>
</field-validator>
</field>
</validators>
<field name="int2" >
...
</field>
...
</validators>
35
36
18
Struts 1 vs Struts 2
Struts 1 vs Struts 2
 Comparaison en 10 points :
 Action classes
 Struts 1 impose aux Actions d’hériter d’une classe
abstraite.
 Struts 2 Action peuvent implémenter l’interface
Action, et/ou d’autres interfaces. Struts 2 fournit une
classe de base ActionSupport d’implémentation.
Sinon, utilisation d’objet POJO.
– Action classes
– Threading Model
– Servlet Dependency
– Testability
– Harvesting Input
– Expression Language
– Binding values into views
– Type Conversion
– Validation
– Control Of Action Execution
37
38
19
Struts 1 vs Struts 2
 Threading Model
 Struts 1 Actions are singletons and must be threadsafe since there will only be one instance of a class
to handle all requests for that Action. The singleton
strategy places restrictions on what can be done
with Struts 1 Actions and requires extra care to
develop. Action resources must be thread-safe or
synchronized.
 Struts 2 Action objects are instantiated for each
request, so there are no thread-safety issues. (In
practice, servlet containers generate many throwaway objects per request, and one more object does
not impose a performance penalty or impact
garbage collection.)
39
Struts 1 vs Struts 2
 Servlet Dependency
 Struts 1 Actions have dependencies on the servlet
API since the HttpServletRequest and
HttpServletResponse is passed to the execute
method when an Action is invoked.
 Struts 2 Actions are not coupled to a container. Most
often the servlet contexts are represented as simple
Maps, allowing Actions to be tested in isolation.
Struts 2 Actions can still access the original request
and response, if required. However, other
architectural elements reduce or eliminate the need
to access the HttpServetRequest or
HttpServletResponse directly.
40
20
Struts 1 vs Struts 2
Struts 1 vs Struts 2
 Testability
 A major hurdle to testing Struts 1 Actions is that the
execute method exposes the Servlet API. A thirdparty extension, Struts TestCase, offers a set of
mock object for Struts 1.
 Struts 2 Actions can be tested by instantiating the
Action, setting properties, and invoking methods.
Dependency Injection support also makes testing
simpler.
.
41
 Harvesting Input
 Struts 1 uses an ActionForm object to capture input.
Like Actions, all ActionForms must extend a base
class. Since other JavaBeans cannot be used as
ActionForms, developers often create redundant
classes to capture input. DynaBeans can used as an
alternative to creating conventional ActionForm
classes, but, here too, developers may be
redescribing existing JavaBeans.
 Struts 2 uses Action properties as input properties,
eliminating the need for a second input object. Input
properties may be rich object types which may have
their own properties. The Action properties can be
accessed from the web page via the taglibs. Struts422
also supports the ActionForm pattern, as well as
21
Struts 1 vs Struts 2
Struts 1 vs Struts 2
 Expression Language
 Struts 1 integrates with JSTL, so it uses the JSTL
EL. The EL has basic object graph traversal, but
relatively weak collection and indexed property
support.
 Struts 2 can use JSTL, but the framework also
supports a more powerful and flexible expression
language called "Object Graph Notation Language"
(OGNL).
43
 Binding values into views
 Struts 1 uses the standard JSP mechanism for
binding objects into the page context for access.
 Struts 2 uses a "ValueStack" technology so that the
taglibs can access values without coupling your view
to the object type it is rendering. The ValueStack
strategy allows reuse of views across a range of
types which may have the same property name but
different property types.
44
22
Struts 1 vs Struts 2
Struts 1 vs Struts 2
 Type Conversion
 Struts 1 ActionForm properties are usually all
Strings. Struts 1 uses Commons-Beanutils for type
conversion. Converters are per-class, and not
configurable per instance.
 Struts 2 uses OGNL for type conversion. The
framework includes converters for basic and
common object types and primitives.
45
 Validation
 Struts 1 supports manual validation via a validate
method on the ActionForm, or through an extension
to the Commons Validator. Classes can have
different validation contexts for the same class, but
cannot chain to validations on sub-objects.
 Struts 2 supports manual validation via the validate
method and the XWork Validation framework. The
Xwork Validation Framework supports chaining
validation into sub-properties using the validations
defined for the properties class type and the
validation context.
46
23
Struts 1 vs Struts 2
 Control Of Action Execution
 Struts 1 supports separate Request Processors
(lifecycles) for each module, but all the Actions in the
module must share the same lifecycle.
 Struts 2 supports creating different lifecycles on a
per Action basis via Interceptor Stacks. Custom
stacks can be created and used with different
Actions, as needed.
47
24

Documents pareils

Fiche Cours PDF - Ociensa Technologies

Fiche Cours PDF - Ociensa Technologies - Les différences de Struts 2 par rapport à Struts 1

Plus en détail

TD n 3 - struts 2 1 Struts 2 Travail demandé

TD n 3 - struts 2 1 Struts 2 Travail demandé 4. Ajouter un validator pour votre formulaire (méthode validate dans votre action) pour que le nom et prénom soient obligatoires et que le mot de passe fasse plus de 8 caractères. 5. Utiliser les f...

Plus en détail