Apache Struts è un progetto open source sponsorizzato dalla Apache Software Foundation ed è l'implementazione Java server-side del design pattern MVC (Model View Controller).
Il progetto Struts è nato con l'intenzione di implementare un framework open-source per la creazione di applicazioni web che permettesse la separazione del livello di presentazione e che fosse, allo stesso tempo, astratto dai vari livelli di dato e dalle transizioni.
Il design pattern MVC
Vediamo in fondo le 3 componenti basi che compongono il design pattern MVC:
- Model: Rappresenta gli oggetti dati. Il modello è ció che viene rappresentato e manipolato dall'utente.
- View: Serve come rappresentazione del modello. È l'oggetto che presenta lo stato corrente degli oggetti dato.
- Controller: Definisce il modo con cui l'interfaccia utente reagisce all'input dell'utente.
L'utilizzo del pattern MVC offre molteplici vantaggi tra i quali una separazione tra i livelli di presentazione e di transazione; ció permette di cambiare il look and feel di un'applicazione senza ricompilare il codice del Modello o del Controller.
In secondo luogo il tempo di sviluppo puó essere significativamente ridotto, perché i programmatori possono pensare alle transazioni, mentre i View programmers (HTML e JSP) si concentrano sull'interfaccia.
L'ultimo beneficio è la separazione della logica di presentazione da quella di business che rende più facile mantenere e modificare un'applicazione Web Struts-based.
I componenti di Struts
Struts, come ogni application framework, è un insieme di classi e interfacce che costituiscono lo scheletro per costruire le nostre Web application. I componenti base su cui si appoggia sono:
- ActionServlet: È la servlet di controllo che gestisce tutte le richieste dell'applicazione. Come tutte le servlet estende la classe
javax.servlet.http.HttppServlet
e che quindi implementa tutti i metodi di lifecycle, inclusoinit()
,doGet()
,doPost()
ed il destroy. - struts-config.xml: È il cuore di tutta l'applicazione. In tale file XML si vanno a settare ed a definire i vari elementi della nostra applicazione e le loro associazioni. Tale file viene letto in fase di start-up dell'applicazione dalla ActionServlet.
- Action: Le Action sono le classi alle quali le ActionServlet delegal'elaborazione della richiesta.
- ActionMapping: Contiene gli oggetti associati ad una Action nello struts-config come ad esempio gli ActionForward.
- ActionForm: Sono considerati dei veri contenitori di dati. Fanno riferimento ad uno specifico form e vengono popolati automaticamente dal framework con i dati contenuti nella request http.
- ActionForward: Contengono i path ai quali la servlet di Struts inoltra il flusso in base alla logica dell'applicazione.
Custom-tags: Sono tag particolari forniti dal framework Struts per assolvere a molti dei più comuni compiti delle pagine JSP.
In figura è rappresentato il flusso elaborativo nella logica di Struts:
Come si puó notare il Client invia una richiesta http (1), la quale viene ricevuta dalla servlet di Struts, che provvede a popolare l'ActionForm associato alla richiesta con i dati della request (2) e l'ActionMapping associata alla richiesta (4). Tutti i dati sono stati letti dallo struts-config.xml in fase di start up. L' ActionServlet delega l'elaborazione dati alla relativa Action (3) passandole in input request e response http e l'ActionForm e l'ActionMapping precedentemente valorizzati. La Action si interfaccia con lo strato di business object. Al termine dell'elaborazione restituisce alla ActionServlet un ActionForward (6) contenete il path della vista da fornire all'utente. La Action esegue il forward alla vista specifica nell'ActionForward (7).
Tale flusso di operazioni non è totalmente completo tuttavia fornisce un'indicazione di base su come viene gestito il flusso di richieste e di elaborazione dati in un applicazione Struts.
Il Deployment descriptor dell'applicazione
Il file web.xml descrive tutti i componenti dell'applicazione Web. Le informazioni che possono essere descritte nel seguente file sono:
- Parametri ed inizializzazione ServletContext
- Contenuto localizzato
- Configurazione della sessione
- Definizione Servlet/JSP
- Mapping Servlet/JSP
- Riferimenti a tag library
- Mappature a tipi MIME
- Lista di file di Welcome
- Pagine di errore
- Informazioni sulla sicurezza
Iniziare con Struts
Per prima cosa scarichiamo l'ultima versione di Struts ed eseguiamo i seguenti passi. Decomprimere lo Struts archive sul disco locale, creare una nuova applicazione Web, utilizzando la struttura di directory descritta precedentemente, copiare tutti i file JAR nella cartella lib.
Eseguiti i seguenti passi andiamo a crearci un file web.xml vuoto:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web app_2_3.dtd">
<web-app>
</web-app>
Creiamo un file struts-config.xml anch'esso vuoto:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!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>
</struts-config>
Creazione della prima applicazione Struts
Struts si basa sul costrutto MVC, è possibile seguire un processo di sviluppo standard per tutte le applicazioni Struts la cosiddetta regola del 6:
- Definire e creare tutte le viste che rappresentano l'interfaccia utente dell'applicazione
- Creare e distribuire tutti gli ActionFoms utilizzati dalle viste
- Creare i componenti del Controller dell'applicazione
- Definire le relazioni che esistono tra le Viste e i Controllers (struts-config.xml)
- Apportare le modifiche appropriate al file web.xml
- Eseguire l'applicazione
Iniziamo a costruire le viste. Nel nostro caso avremo due viste che compongono il livello di presentazione della nostra applicazione: index.jsp e risultato.jsp.
Listato 1. File index.jsp
<%@ page language="java" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<body>
<html:form action="ProvaAction" name="provaForm" type="forms.ProvaForm">
<table width="45%" border="0">
<tr>
<td>Symbol:</td>
<td><html:text property="symbol" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<html:submit />
</td>
</tr>
</table>
</html:form>
</body>
</html>
La pagina index.jsp utilizza il tag html:form. Questo tag, con i suoi tag di input subordinati, incapsula il processing di un form fatto da Struts.
Gli attributi del tag form utilizzati sono i seguenti:
- action: Rappresenta l'URL al quale questo form verrà inviato. Questo attributo viene anche utilizzato per trovare l'ActionMapping specifico nello struts-config.xml
- name: Identifica la chiave che viene utilizzata per identificare l'actionForm appropriato che rappresenterà i dati inviati dal form
- type: Rappresenta il form bean che si desidera utilizzare per questa richiesta
Per utilizzare i due tag HTML precedenti bisogna aggiungere un taglib entry nel file web.xml che referenzi l'URI/WEB-INF/struts-html.tld:
<taglib>
<taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
<aglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
È necessario poi copiare il file struts-html.tld nella directory WEB-INF dell'applicazione.
ActionForm
L'ActionForm utilizzato in questo esempio contiene un singolo data member che viene mappato direttamente al parametro di input symbol dalla Index View. L'ActionForm deve disporre per ogni data member un metodo set e get seguito dal nome del data member, con la prima lettera in maiuscolo.
Listato 2. ActionForm
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import javax.servlet.http.HttpServletRequest;
public class ProvaForm extends ActionForm {
private String symbol = null;
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public void reset(ActionMapping mapping, HttpServletRequest request) {
this.symbol = null;
}
}
L'ultima vista è la seguente jsp
Risultato : <%= request.getAttribute("OUTPUT") %>
Creazione dei componenti del Controller
In un applicazione Struts, due componenti rappresentano i controller. Le classi org.apache.struts.action.ActionServlet
e org.apache.struts.action.Action
.
Nel nostro esempio, abbiamo un solo processo da eseguire che è il valore del sub mitted quote symbol. Poniamo attenzione nel metodo execute()
.
Listato 3. classe che estende org.apache.struts.action.Action
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class ProvaAction extends Action {
protected String getSimbolo(String symbol) {
//un semplice controllo sulla stringa String out;
if (symbol.equalsIgnoreCase("Ciao")) {
out="OK!!!";
}else{
out="Sbagliato!!!";
}
return out;
}
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String output = null;
String target = "success";
//controlliamo che il form non sia nullo
if (form!=null) {
ProvaForm provaForm = (ProvaForm) form;
String symbol = provaForm.getSymbol();
output = getSimbolo(symbol);
}
//salviamo il risultato in request
request.setAttribute("OUTPUT", output);
return (mapping.findForward(target));
}
}
Notiamo che questa classe estende la classe org.apache.struts.action.Action
. Il metodo execute()
contiene la funzionalità principale di ProvaAction
.
Vediamo il significato dei parametri di ingresso:
- ActionMapping: Contiene tutte le informazioni di deployment per un parti colare oggetto Action.
- ActionForm: Rappresenta il form di input contenente i parametri della vista.
- HttpServletRequest: Rappresenta l'http request object.
- HttpServletResponse: Rappresenta l'http response object.
Ecco il risultato che si ottiene lanciando l'applicazione ed inserendo nel campo di testo la stringa "Ciao":
Per effettuare il deploy della Action alla nostra applicazione Struts, dobbiamo aggiungere al file struts-config.xml le seguenti sezioni:
<action-mappings>
<action path="/ProvaActiom" type="action.ProvaAction" name="ProvaForm" >
<forward name="success" path="/risultato.jsp" />
<forward name="failure" path="/index.jsp" />
</action>
</action-mappings>
Vantaggi nell'uso di Apache Struts
È facile implementare l'approccio MVC anche attraverso l'utilizzo di RequestDispatcher.forward
e jsp:getProperty
(ottenendo ovviamente una ridotta implementazione dell'ActionServlet) tuttavia l'utilizzo di Struts supporta vantaggi significativi in termini di progetto:
- Modularità e Riusabilità: I diversi ruoli dell'applicazione sono affidati a diversi componenti. Ció consente di sviluppare codice modulare e più facilmente riutilizzabile.
- Manutenibilità: L'applicazione è costituita da livelli logici ben distinti. Una modifica in uno dei livelli non comporta modifiche negli altri.
- Rapidità di sviluppo: È possibile sviluppare in parallelo le varie parti dell'applicazione, logica di business e di view.
- File di configurazione centralizzato: È possibile utilizzare una serie di file XML atti a codificare il comportamento della Web application ( vedi struts-config.xml, web.xml ...)
- FormBean: Un oggetto automaticamente popolato con i dati provenienti da un form HTML accessibile da Servlet e JSP
- Bean Tag: Struts mette a disposizione un'insieme di custom Tags per accedere alle componenti JavaBean
- Validazione dati di un form: È possibile effettura diversi tipi di controlli per dati provenienti da un form tramite due file XML il validation-rules.xml e il validator.xml