Vous êtes sur la page 1sur 36

INSA - ASI TechnoWeb : Struts 1/36

Technologie Web
Un framework J2EE : Struts

Alexandre Pauchet
INSA Rouen - Département ASI
BO.B.RC.18, pauchet@insa-rouen.fr
INSA - ASI TechnoWeb : Struts 2/36

Plan

1 Introduction

2 Fonctionnement

3 Utilisation des javabeans

4 Validation d’un formulaire

5 Exemple : Journées thématiques

6 Conclusion
INSA - ASI TechnoWeb : Struts 3/36

Introduction (1/6)
Description

Framework développé par Apache (comme Tomcat)


Basé sur J2EE (JSP et servlets) :
surcouche J2EE,
toute application Struts est une application web J2EE
Ajoute de nouvelles classes
Ajoute de nouveaux tags pour JSP
Basé sur l’architecture MVC (Modèle-Vue-Contrôleur)
Un peu vieux, très utilisé
INSA - ASI TechnoWeb : Struts 4/36

Introduction (2/6)
Le MVC (rappel)

Le Modèle-Vue-Contrôleur (MVC) est une architecture et une méthode de


conception pour le développement d’applications logicielles. Le MVC
distingue :
Modèle (données) : le comportement de l’application.
Vue (présentation) : interface avec l’utilisateur.
Contrôleur (traitement) : gestion des évènements de synchronisation
entre la vue et le modèle.
En résumé, lorsqu’un client envoie une requête à l’application, celle-ci est
analysée par le contrôleur, qui demande au modèle approprié d’effectuer
les traitements, puis renvoie la vue adaptée au navigateur, si le modèle ne
l’a pas déjà fait.
INSA - ASI TechnoWeb : Struts 5/36

Introduction (3/6)
Le MVC sans Struts

Des JavaBeans (et autres classes) qui gèrent l’aspect métier (modèle)
Des JSP (éventuellement sans code Java) qui produisent l’affichage
(les vues)
Une ou plusieurs Servlets font le lien entre les JavaBeans et les JSP,
via les mécanismes de Délégation/Inlusion (contrôleur(s))
INSA - ASI TechnoWeb : Struts 6/36

Fonctionnement (4/6)
L’idée de Struts

Ajouter un fichier de configuration en XML jouant le rôle de


contrôleur (struts-config.xml)
Ce fichier est géré par une Servlet spécifique

⇒ Le code Java se limite désormais aux aspects métiers


⇒ Beaucoup plus de souplesse : pour changer le comportement de
l’application, il suffit de changer le code XML
⇒ Moins de compilation
INSA - ASI TechnoWeb : Struts 7/36

Introduction (5/6)
Installation

1 Récupérer une archive struts-blank.war (comprise dans les


exemples d’application) sur http://struts.apache.org/.
Versions : 1.2.7, 1.3.10 ou 2.1.8
2 La copier dans webapps : elle se décompresse toute seule, comme
tout fichier .war
3 On a alors une application Struts vide

V Pour créer une nouvelle application, on copie struts-blank.war, on le


renomme, et on effectue les modifications à l’intérieur.
INSA - ASI TechnoWeb : Struts 8/36

Introduction (6/6)
Contenu (partiel) de struts-blank

struts-blank.war
|_ META-INF
| |_ MANIFEST.MF
|_ pages
| |_ Welcome.jsp
|_ WEB_INF
| |_ classes
| |_ lib
| | |struts.jar, jakarta-oro.jar, ...
| |_ src
| |_ struts-config.xml, web.xml, ...
| |_ struts-html.tld, struts-beans.tld, ...
|_ index.jsp
INSA - ASI TechnoWeb : Struts 9/36

Fonctionnement (1/9)
Fonctionnement d’une application Struts

L’utilisateur remplit (par exemple) un formulaire issu d’une JSP ou


d’un document HTML statique
On appelle lors de la validation une URL de la forme
traitement.do, qui est traitée en fonction du contenu de
struts-config.xml
On appelle la méthode execute d’une instance de la classe Action
(ou d’une sous-classe)
Une JSP est appelée en fonction du résultat de la méthode et du
struts-config.xml
INSA - ASI TechnoWeb : Struts 10/36

Fonctionnement (2/9)
La méthode execute

Dans la classe qui étend la classe Action, la méthode execute est


redéfinie pour être appelé à l’envoi du formulaire :
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)

form est un JavaBean contenant les données issues du formulaire


On exécute alors le code métier correspondant
À la fin, appel de la méthode mapping.findForward pour trouver la
JSP à exécuter en fonction du résultat (succès, échec, etc.)
INSA - ASI TechnoWeb : Struts 11/36

Fonctionnement (3/9)
Le fichier web.xml de Struts (extrait)

<web-app>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>
org.apache.struts.action.ActionServlet
</servlet-class>
</servlet>
...
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
INSA - ASI TechnoWeb : Struts 12/36

Fonctionnement (4/9)
Exemple : login

On veut mettre en place un système de login pour un site web :


On se loggue via la page login.html
On va modifier le struts-config.xml
On va créer une sous-classe de Action
On va créer les JSP correspondantes
INSA - ASI TechnoWeb : Struts 13/36

Fonctionnement (5/9)
Exemple : le fichier login.html

index.html
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-
strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
<head>
< title >Page de login pour Struts 1</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
</head>
<body>
<form action="login.do" method="POST">
<input type="text" name="login"/>
<input type="password" name="password"/>
<input type="submit"/>
</form>
</body>
</html>
INSA - ASI TechnoWeb : Struts 14/36

Fonctionnement (6/9)
Exemple : struts-config.xml

struts-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
<struts-config>
<action-mappings>
<action path="/login" type="monAppli.LoginAction">
<forward name="succes" path="/pages/ok.jsp"/>
<forward name="echec" path="/pages/echec.jsp"/>
</action>
</action-mappings>
<controller processorClass="org.apache.struts.tiles.TilesRequestProcessor"/>
<message-resources parameter="MessageResources" />
<plug-in className="org.apache.struts.tiles.TilesPlugin" >
<set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" />
<set-property property="moduleAware" value="true" />
</plug-in>
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>
</struts-config>
INSA - ASI TechnoWeb : Struts 15/36

Fonctionnement (7/9)
Exemple : LoginAction.java

LoginAction.java
package monAppli;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class LoginAction extends Action {
public ActionForward execute (ActionMapping mapping, ActionForm actionForm, HttpServletRequest request,
HttpServletResponse response) throws Exception {
String login = request.getParameter ("login");
String password = request.getParameter ("password");
if (login.equals(password))
return mapping.findForward("succes");
else
return mapping.findForward("echec");
}
}
INSA - ASI TechnoWeb : Struts 16/36

Fonctionnement (8/9)
Exemple : ok.jsp

ok.jsp
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<html:html locale="true">
<head>
< title >Hello !</title>
<html:base/>
</head>
<body bgcolor="white">
<h1>Hello !!! Login/mdp bien trouvés...</h1>
</body>
</html:html>
INSA - ASI TechnoWeb : Struts 17/36

Fonctionnement (9/9)
Exemple : echec.jsp

echec.jsp
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<html:html locale="true">
<head>
< title >Echec à la connexion !</title>
<html:base/>
</head>
<body bgcolor="white">
<h1>Echec à la connexion : mauvais login/mdp...</h1>
</body>
</html:html>
INSA - ASI TechnoWeb : Struts 18/36

Utilisation des javabeans (1/5)


Amélioration : utilisation de javabeans

Lors de l’appel de la méthode execute, on a un objet de type


ActionForm
Cet objet est un javabean contenant les données saisies
Il faut développer la classe correspondante et la déclarer dans le
struts-config.xml :

struts-config.xml
<form-beans>
<form-bean name="logBean" type="monAppli.LogBean"/>
</form-beans>
<action-mappings>
<action path="/login" type="monAppli.LoginAction" name="logBean" scope="session">
<forward name="succes" path="/pages/ok.jsp"/>
<forward name="echec" path="/pages/echec.jsp"/>
</action>
</action-mappings>
INSA - ASI TechnoWeb : Struts 19/36

Utilisation des javabeans (2/5)


La classe LogBean

LogBean.java
package monAppli;
import org.apache.struts.action.*;
public class LogBean extends ActionForm {
private String login;
private String password;
public String getLogin(){
return this.login;
}
public void setLogin(String login){
this .login = login;
}
public String getPassword(){
return this.password;
}
public void setPassword(String password){
this .password = password;
}
}
INSA - ASI TechnoWeb : Struts 20/36

Utilisation des javabeans (3/5)


La classe UserBean

UserBean.java
package monAppli;
import java.io.*;
import org.apache.struts.action.*;
public class UserBean implements Serializable {
private String login;
private String name;
public String getLogin(){
return this.login;
}
public void setLogin(String login){
this .login = login;
}
public String getName(){
return this.name;
}
public void setName(String name){
this .name = name;
}
public static UserBean getUser(String login){
UserBean ub = new UserBean();
ub.setLogin(login);
ub.setName("Bob Leponge");
return ub;
}
}
INSA - ASI TechnoWeb : Struts 21/36

Utilisation des javabeans (4/5)


Mise à jour de LoginAction.java

Utilisation d’un javabean comme représentation du formulaire


Utilisation d’un javabean comme représentation de l’utilisateur

LoginAction.java
package monAppli;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class LoginAction extends Action {
public ActionForward execute (ActionMapping mapping, ActionForm actionForm, HttpServletRequest request,
HttpServletResponse response) throws Exception {
LogBean bean = (LogBean)actionForm;
String login = bean.getLogin ();
String password = bean.getPassword ();
if (login.equals(password)) {
UserBean userBean = UserBean.getUser(login);
request.setAttribute("userBean", userBean);
return mapping.findForward("succes");
}
else
return mapping.findForward("echec");
}
}
INSA - ASI TechnoWeb : Struts 22/36

Utilisation des javabeans (5/5)


Amélioration de ok.jsp

Utilisation de la taglib proposée pour la gestion des Beans (un peu plus
pratique que celle par défaut)

ok.jsp
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<html:html locale="true">
<head>
< title >Hello !</title>
<html:base/>
</head>
<body bgcolor="white">
<h1>Salut <bean:write name="userBean" property="name"/> !</h1>
</body>
</html:html>
INSA - ASI TechnoWeb : Struts 23/36

Validation d’un formulaire (1/4)


Validation du ActionForm

On veut que le login soit non vide lors de la saisie :


On ajoute à la classe LogBean une méthode :
ActionErrors validate (ActionMapping mapping,
HttpServletRequest request);

On modifie struts-config.xml :
<action path="..." type="..." validate="true" input="/
erreurs.jsp">...</action>

On crée une page erreur.jsp


En cas d’erreur, c’est erreur.jsp qui est appelée : la LoginAction
n’est pas appelée du tout
INSA - ASI TechnoWeb : Struts 24/36

Validation d’un formulaire (2/4)


La page erreur.jsp

erreur.jsp
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<html:html locale="true">
<head><title>Erreurs dans les champs du formulaire</title><html:base/></head>
<body bgcolor="white">
<h1>Erreurs dans les champs du formulaire</h1>
<html:errors/>
</body>
</html:html>

Le html:errors affiche la liste des erreurs renvoyées par la méthode


validate, en se basant sur un fichier nommé
MessageResources.properties (ou
ApplicationResources.properties, selon les versions de Struts) pour
la traduction en HTML
INSA - ASI TechnoWeb : Struts 25/36

Validation d’un formulaire (3/4)


La méthode validate

LogBean.java
package monAppli;
import org.apache.struts.action.*;
import javax.servlet.http.*;
public class LogBean extends ActionForm {
private String login;
private String password;
public String getLogin(){
return this.login;
}
public void setLogin(String login){
this .login = login;
}
public String getPassword(){
return this.password;
}
public void setPassword(String password){
this .password = password;
}
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if (this.getLogin().equals(""))
errors.add("login", new ActionError("errors.login"));
return errors;
}
}
INSA - ASI TechnoWeb : Struts 26/36

Validation d’un formulaire (4/4)


MessageResources.properties

MessageResources.properties
# -- standard errors --
errors.header=<font color="#FF0000"><ul>
errors.prefix=<LI>
errors.suffix=</LI>
errors.footer=</ul></font>
# -- validator --
errors.login=Il faut mettre un Login !
errors.invalid={0} is invalid.
errors.maxlength={0} can not be greater than {1} characters.
errors.minlength={0} can not be less than {1} characters.
errors.range={0} is not in the range {1} through {2}.

...
INSA - ASI TechnoWeb : Struts 27/36

Exemple : Journées thématiques (1/8)


Déploiement

Exemple
journees.war
|_ WEB_INF
| |_ src
| | |_ journees
| | | |_ LookupForm.java, LookupAction.java
| |_ classes
| | |_ journees
| | | |_ LookupForm.class, LookupAction.class
| | |_ MessageRessources.properties
| |_ lib
| | |_struts.jar, ...
| |_ struts-config.xml, web.xml, ...
| |_ struts-html.tld, struts-logic.tld, ...
|_ index.jsp, lieu.jsp, erreur.jsp
INSA - ASI TechnoWeb : Struts 28/36

Exemple : Journées thématiques (2/8)


LookupForm.java

LookupForm.java
package journees;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.*;
public class LookupForm extends ActionForm {
private String theme = null;
static final long serialVersionUID=1L;
public String getTheme() {
return this.theme;
}
public void setTheme(String theme) {
this .theme = theme;
}
public void reset(ActionMapping mapping, HttpServletRequest request) {
this .theme = null;
}
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors erreurs = new ActionErrors();
if (this.getTheme().equals("")){
erreurs.add("lookup", new ActionError("errors.theme"));
}
return erreurs;
}
}
INSA - ASI TechnoWeb : Struts 29/36

Exemple : Journées thématiques (3/8)


LookupAction.java

LookupAction.java
package journees;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class LookupAction extends Action {
protected String getLieu(String theme) {
if ( theme.equalsIgnoreCase("TechnoWeb") )
return new String("Saint-Etienne du Rouvray");
else return null;
}
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
String lieu = null, cible = new String("succes");
if ( form != null )
lieu = getLieu(((LookupForm)form).getTheme());
if ( lieu == null ) {
cible = new String("echec");
} else request.setAttribute("LIEU", lieu);
return (mapping.findForward(cible));
}
}
INSA - ASI TechnoWeb : Struts 30/36

Exemple : Journées thématiques (4/8)


index.jsp

index.jsp
<%@ page language="java" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<head>
< title >Journees thematiques</title>
</head>
<body>
<html:form action="Lookup.do" method="POST">
<p>Journees thematiques : <html:text property="theme" /></p>
<html:errors/>
<html:submit/>
</html:form>
</body>
</html>
INSA - ASI TechnoWeb : Struts 31/36

Exemple : Journées thématiques (5/8)


lieu.jsp et erreur.jsp

lieu.jsp
<html>
<head>
< title >Struts Application</title>
</head>
<body>
<h2>lieu : <%= request.getAttribute("LIEU") %></h2>
</body>
</html>

erreur.jsp
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<head>
< title >Erreur de saisie</title>
</head>
<body>
<h1>Erreur de saisie</h1>
<html:link href="/struts-journees/index.jsp">retour a la page de saisie</html:link>
</body>
</html>
INSA - ASI TechnoWeb : Struts 32/36

Exemple : Journées thématiques (6/8)


struts-config.xml

struts-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "
http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<form-beans>
<form-bean name="lookupForm" type="journees.LookupForm"/>
</form-beans>
<action-mappings>
<action path="/Lookup" type="journees.LookupAction" name="lookupForm" scope="session" validate="true"
input="/index.jsp">
<forward name="succes" path="/lieu.jsp"/>
<forward name="echec" path="/erreur.jsp"/>
</action>
</action-mappings>

...
INSA - ASI TechnoWeb : Struts 33/36

Exemple : Journées thématiques (8/8)


MessageResources.properties

MessageResources.properties
# -- standard errors --
errors.header=<font color="#FF0000"><ul>
errors.prefix=<LI>
errors.suffix=</LI>
errors.footer=</ul></font>
# -- validator --
errors.theme=Veuillez entrer un theme a rechercher
INSA - ASI TechnoWeb : Struts 34/36

Conclusion (1/3)
Struts ? Et le reste ?

Struts n’est pas le seul outil de haut niveau disponible pour les
applications web J2EE :
Java Server Faces (JSF),
Tapestry,
Hibernate,
Spring (Spring MVC),
...

Ces outils ne sont pas mutuellement exclusifs :


Struts est plutôt spécialisé "contrôleur"
JSF propose des composants graphiques : "vue"
Hibernate, les EJB et autres s’intéressent à la sérialisation des
objets : "modèle"
INSA - ASI TechnoWeb : Struts 35/36

Conclusion (2/3)
Faut-il utiliser Struts ?

Oui si l’application est conséquente ;


Non s’il s’agit d’une application simple (exemple limite, le blog) :
même le site de Struts déconseille d’utiliser le Framework dans ces
cas-là
On peut utiliser des JSP seules, du PHP ou un framework dit agile
(Ruby on Rails, Django, ...) dans les cas plus simples
INSA - ASI TechnoWeb : Struts 36/36

Conclusion (3/3)
Sources

http://struts.apache.org/
http://www-lih.univ-lehavre.fr/~coletta/dess0607/struts/une_appli.html
http://www-lih.univ-lehavre.fr/~coletta/dess0607/struts/erreurs.html
http://www.labo-sun.com/resource-fr-essentiels-859-5-java-j2ee-struts-un-framework-mvc-pour-vos-
applications-j2ee.htm\#h1n3
http://www.jmdoudoux.fr/java/dej/chap052.htm