STRUTS 2 Best Practices

La bibbia di struts 2 è su:
http://struts.apache.org/2.0.11.2/docs/guides.html

1) nei tag struts delle pagine jsp può essere invocata la action tramite elemento action=”” che può contenere: il name della <action name=”” >.. oppure contestuale esempio “#{action.Cerca}” che chiama il metodo Cerca della classe action (pojo class) associata

2) i nomi delle azioni sono mappati su metodi di classe da eseguire dal file struts.xml (o sottostanti inclusi in struts.xml)

i tag <action> sono nei file di configurazione struts.xml o inclusi

i tag action sono anche definibili con wildcard
esempio:

 <action name="*Crud" class="example.Crud" method="{1}">

dove “editCrud” chiamerà il metodo “edit” della classe di action; “deleteCrud” chiamerà il metodo “delete” e così via..

si può anche prevedere action di default (che raccolgono azioni non esistenti)

esempio 1 con tag dichiarativo default-action-ref in struts.xml:

 <package name="Hello" extends="action-default">
  <default-action-ref name="UnderConstruction">
  <action name="UnderConstruction">
   <result>/UnderConstruction.jsp</result>
  </action>
 </package>

esempio 2 che usa le wildcard:

 <action name="*" >
  <result>/{1}.jsp</result>
 </action>


3) concluso il metodo della classe pojo associata alla action mediante struts.xml questa deve ritornare una stringa di risultato

questa stringa serve per selezionare il sotto tag result della action in struts.xml

il result selezionato è responsabile di una certa uscita dipendente anche dall’esito dell’esecuzione del metodo associato

Ci sono dei risultati (stringa) predefiniti:

   * String SUCCESS = "success";
   * String NONE = "none";
   * String ERROR = "error";
   * String INPUT = "input";
   * String LOGIN = "login";

in più è possibile aggiungerne di nuovi e diversi …
 
a questo punto Struts 2 fa un match sui tag result nella action in questione

essendo che:

   * omissione di name in result -> “success”
   * omissione di type -> “dispatcher”
   * omissionne di <param> usa il testo nel nodo result
  
ho che le seguenti 4 dichiarazioni si equivalgono:

 1.
 <result>/ThankYou.jsp</result>

 2.
 <result>
  <param name="location">/ThankYou.jsp</param>
 </result>

 3.
 <result name="success">
  <param name="location">/ThankYou.jsp</param>
 </result>

 4.
 <result name="success" type="dispatcher">
  <param name="location">/ThankYou.jsp</param>
 </result>

a titolo di esempio ecco una azione dichiarata in struts.xml con azioni multiple:

 <action name="Hello">
  <result>/hello/Result.jsp</result>
  <result name="error">/hello/Error.jsp</result>
  <result name="input">/hello/Input.jsp</result>
 </action>

dove il primo by default corrisponde a name=”success”

IMPORTANTE: è anche possibile dichiarare dei result globali che possono essere invocati se nella action in questione non viene trovato un result corrispondente

sempre in struts.xml (o inclusi) e fuori dal tag <action> si dichiara:

 <global-results>
  <result name="error">/Error.jsp</result>
  <result name="invalid.token">/Error.jsp</result>
  <result name="login" type="redirect-action">Logon!input</result>
 </global-results>

RESULT TYPE:

il result type di default è dispatcher.
I result che vengono generati e restituiti all’utente da una azione possono essere anche di tipo diverso.
Ad esempio il result “success” può restituire una pagina JSP, mentre il result
“error” può inviare al browser un particolare header HTTP

ad esempio
<result name="success" type="dispatcher" ...
ha come conseguenza un render JSP

questi risultati quindi possono essere sia con un esito visuale che di mera interazione con l’ambiente

i result type predefiniti sono:

   * chain: used for action chaining
   * dispatcher: used for web resource integration, including jsp integration
   * freemarker: used for freemarker integration
   * httpheader: used to control special http behaviors
   * redirect: used to redirect to another url (web resource – per browser redirect)
   * redirect-action: used to redirect to another action mapping
   * stream: used to stream an inputstream back to the browser (usually for file downloads)
   * velocity: used for velocity integration
xsl: used for xml/xslt integration
   * plaintext: used to display the raw content of a particular page (i.e jsp, html)
   * tiles: used to provide tiles integration
  
nel nostro caso ne usiamo uno specifico (perchè sono estendibili) chè è quello di jsf per render jsf:

 <result name=”success” type=”jsf” />
 
per maggiori dettagli in merito leggere:
http://struts.apache.org/2.0.11.2/docs/jsf-plugin.html

INTERCEPTORS:

servono a valutare pre-azioni per una azione (es: controlli, validazioni. inizializzazioni, …) nell’ordine in cui questi vengono dichiarati nello stack xml della action

esempio:

 <package name="default" extends="struts-default">
  <interceptors>
   <interceptor name="timer" class=".."/>
   <interceptor name="logger" class=".."/>
  </interceptors>
  <action name="login" class="tutorial.Login">
   <interceptor-ref name="timer"/>
   <interceptor-ref name="logger"/>
   <result name="input">login.jsp</result>
   <result name="success" type="redirect-action">/secure/home</result>
  </action>
 </package>

1. prima viene invocato interceptor timer
2. poi viene invocato interceptor logger
3. poi eseguita l’azione login
4. poi si continua sul result dato dal metodo login della classe action

se lo stesso stack di interceptors viene referenziato identicamente + volte è possibile dichiarare lo stack e referenziarlo in struts.xml o inclusi

esempio equivalente al precedente (ma più compatto in sede di action):

 <package name="default" extends="struts-default">
  <interceptors>
   <interceptor name="timer" class=".."/>
   <interceptor name="logger" class=".."/>
   <interceptor-stack name="myStack">
    <interceptor-ref name="timer"/>
    <interceptor-ref name="logger"/>
   </interceptor-stack>
  </interceptors>
  <action name="login" class="tutuorial.Login">
   <interceptor-ref name="myStack"/>
   <result name="input">login.jsp</result>
   <result name="success"
   type="redirect-action">/secure/home</result>
  </action>
 </package>

esempio di classe interceptor:

 import com.opensymphony.xwork2.ActionInvocation;
 import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
 public class SimpleInterceptor extends AbstractInterceptor {
  public String intercept(ActionInvocation invocation) throws
  Exception {
   MyAction action = (MyAction)invocation.getAction();
   action.setDate(new Date());
   return invocation.invoke();
  }
 }

interceptors provvisti dal framework di Struts 2 e configurati in struts-default.xml

   * params (setta i parametri passati in request sulla action)
   * scope (utile per intervenire a salvare lo stato dell’azione in sessione o applicazione)
   * validation (validazione mediante validatori definiti in action-validation.xml)
   * altri …
  
per tutti gli interceptors forniti dal framework leggere:
“Starting Struts 2.pdf” a pagina 64
  
4. VALIDATORS

forniti:

 <validators>
  <validator name="required" class=".."/>
  <validator name="requiredstring" class=".."/>
  <validator name="int" class=".."/>
  <validator name="double" class=".."/>
  <validator name="date" class=".."/>
  <validator name="expression" class=".."/>
  <validator name="fieldexpression" class=".."/>
  <validator name="email" class=".."/>
  <validator name="url" class=".."/>
  <validator name="visitor" class=".."/>
  <validator name="conversion" class="../>
  <validator name="stringlength" class=".."/>
  <validator name="regex" class=".."/>
 </validators>

si dichiarano in file associati alle azioni:

 <ActionName>-validation.xml
 
o altri modi: vedi pag. 74 di “Struts 2 Basics (slides).pdf”
 
esempio su SimpleAction-validation.xml

 <validators>
  <field name="bar">
   <field-validator type="required">
    <message>You must enter a value for bar.</message>
   </field-validator>
   <field-validator type="int">
    <param name="min">6</param>
    <param name="max">10</param>
    <message>bar must be between ${min} and ${max}, current value is ${bar}.</message>
   </field-validator>
  </field>
  <field name="bar2">
   <field-validator type="regex">
    <param name="regex">[0-9],[0-9]</param>
    <message>The value of bar2 must be in the format "x, y", where x and y are between 0 and 9</message>
   </field-validator>
  </field>
  <field name="date">
   <field-validator type="date">
    <param name="min">12/22/2002</param>
    <param name="max">12/25/2002</param>
    <message>The date must be between 12-22-2002 and 12-25-2002.</message>
   </field-validator>
  </field>
  <field name="foo">
   <field-validator type="int">
    <param name="min">0</param>
    <param name="max">100</param>
    <message key="foo.range">Could not find foo.range!</message>
   </field-validator>
  </field>
  <validator type="expression">
   <param name="expression">foo lt bar </param>
   <message>Foo must be greater than Bar. Foo = ${foo}, Bar =
   ${bar}.</message>
  </validator>
 </validators>

il codice di validazione JavaScript è generato dal  framework
per far si che venga generato usare l’attributo validate impostato a true
esempio:

 <s:form action="Login" validate="true">
  <s:textfield key="username"/>
  <s:password key="password" />
  <s:submit/>
 </s:form>

questo esempio per la validazione userà le regole dichiarate in

 Login-validation.xml
 
 
5. struts-default.xml

Definisce tutti i risultati di default in bundle e interceptors (o stack di interceptors)
che possono essere utili come base per l’applicazione specifica.
Viene automaticamente incluso in struts.xml
Incluso nel file struts2.jar
Al fine di fornire la propria versione, è possibile cambiare l’impostazione della proprietà: struts.configuration.files
nel file: struts.properties file.

6. struts.xml

è il file che contiene action o package di action (per raggruppare in comparti stagni)
viene posizionato in genere su classpath della webapp
ovvero: /WEB-INF/classes

può a sua volta includere altri file struts-*.xml per meglio dividere le logiche di action mapping

esempio di struts con inclusioni:

 <?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>
     <include file="struts-global.xml" />
     <include file="struts-1-Login.xml" />
     <include file="struts-2-Gestione.xml" /> 
 </struts>

esempio di file sottostante:

 <?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>
  <package name="welcome" extends="jsf-package" namespace="/jsp">
   <default-interceptor-ref name="jsf-stack" />
   <action name="welcome" class="it.doqui.pocacta.pocacta.presentation.action.WelcomeAction">
    <result name="success" type="jsf" />
    <result name="login" type="redirectAction">
     <param name="namespace">/jsp/login</param>
     <param name="actionName">login</param>
     <param name="codiceFiscale">${codiceFiscale}</param>
    </result>
   </action>
  </package>
  <package name="login" extends="jsf-package" namespace="/jsp/login">
   <default-interceptor-ref name="jsfStackNoLoginInterceptor" />
   ...
  </package>
  ...
 </struts>

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s