500 likes | 729 Views
Un framework per il pattern MVC. Simone Pulcini. Oggi parleremo di:. Framework Design Pattern e MVC Contoller in Struts e Servlet Model in Struts e Form Bean View in Struts e Java Server Pages (JSP). Framework: definizione. Insieme di librerie di codice
E N D
Un framework per il pattern MVC Simone Pulcini
Oggi parleremo di: • Framework • Design Pattern e MVC • Contoller in Struts e Servlet • Model in Struts e Form Bean • View in Struts e Java Server Pages (JSP)
Framework: definizione • Insieme di librerie di codice • Implementano funzionalità per sviluppare una propria applicazione software • Favorisce riusabilità del codice e permette di concentrarsi sullo sviluppo di funzionalità proprie. • Sviluppo come integrazione • Funzionalità del framework documentate attraverso le API. • Sovrainsieme delle librerie run-time proprie del linguaggio. • Offre funzionalità specifiche
Design Pattern • Soluzione riutilizzabile ad un problema comune nello sviluppo di software • Soluzione proposta non è implementazione diretta. • Descritta attraverso un template, per astrarre dal linguaggio di sviluppo e dal caso specifico
Design Pattern MVC • Separa logica operativa da interfaccia utente. • Interfaccia utente detta VIEW • Sorgenti di dati identificate dal MODEL • Interazione gestita dal CONTROLLER; notifica il MODEL di richieste di cambiamenti risultanti dalle interazioni. • MODEL notifica VIEW dei cambiamenti nei dati
MVC: Diagramma Controller View Model
Problemi MVC su Web • Connessioni senza stato fra client e server • Come notificare modifiche nel model? • Browser deve reinterrogare il server per scoprire modifiche nello stato dell’applicazione • Differenze nella tecnologia di implementazione fra client e server
Struts e MVC • Struts: framework che implementa il pattern MVC per lo sviluppo di web applications • Struts integra ed estende alcuni componenti di Java Enterprise Edition • Arricchisce le API Java per la gestione delle Servlet e offre tag aggiuntivi per le Java Server Pages (JSP)
Diagramma di una applicazione Struts Web Browser Application Server View Model JSP ActionForm beans Controller Struts-config.xml e Actions
Ruoli • Client browser • Produce eventi di richiesta e attende una risposta. • Controller • Riceve la richiesta e decide a chi mandarla. Riflette il pattern Command ed è implementato come servlet. Configurato in struts-config.xm • Business logic • Aggiorna lo stato del modello e aiuta a controllare il flusso dell’applicazione. Realizzato mediante una Action class. • Model state • Rappresenta lo stato dell’applicazione. Rappresentato da bean ActionForm a livello di sessione o richiesta, non a livello di persistenza. Informazione dalla ActionForm letta mediante tag JSP. • View • Componente JSP senza logica di flusso o di business o informazione di modello, solo tag.
Componenti chiave • "request" handler fornito dall’applicazione, associato a uno URI standard. • "response" handler trasferisce il controllo a un’altra risorsa che completa la risposta. • Biblioteca di tag per creare applicazioni interattive, basate su form, con pagine lato server.
Controller in Struts • Controller di Struts basato su 4 componenti: • ActionServlet • Action • Plugins • RequestProcessor • Flusso di web application: da richiesta dal client a risposta offerta da application server
Servlet: definizione • Componente di web application Java EE • Programma Java che gira lato server (differentemente da una applet che gira lato client) • Classe java che estende funzionalità offerte da un server (HTTP, FTP, SMTP ecc.) • HttpServlet (da javax.servlet.http)
Separation of concerns per Web applications • Per-action logic • Accesso agli oggetti necessari per eseguire la logica dell’azione e accedere alle risorse • Traduzione, associazione e conversione da valore stringa in HTML a tipi e primitive e da oggetti vista a oggetti business • Cross-cutting concerns per fornire funzionalità a gruppi di azioni o a tutte le azioni nell’applicazione.
Servlet: ciclo di vita • Richiesta da client ad application server • Application server verifica in web.xml a quale servlet mappare la richiesta • Classe Servlet indicata nel descrittore viene caricata, istanziata, e inizializzata dal Servlet Container • La classe genera la risposta alla richiesta ricevuta dal client [doGet(); oppure doPost();] • Se non vi sono altre richieste da soddisfare con tale servlet, Servlet Container chiama il metodo destroy()
ActionServlet: la servlet di Struts • Controller si innesta estendendo ActionServlet • Questa servlet raccoglierà tutte le richieste conformi ad un certo pattern, opportunamente dichiarato nel file web.xml • Ma se c’è una sola servlet che raccoglie tutte le richieste, come differenzio le risposte? • ActionServlet prende come parametro un file di configurazione (struts-config.xml) nel quale lo sviluppatore può dichiarare i mapping fra una risorsa richiesta (path), la logica di risposta (Action) e la pagina JSP che produce il risultato (View) • Struts genera opportunamente il codice di risposta dei metodi doGet o doPost in base a quanto dichiarato nel file di configurazione struts-config.xml
Esempio: WEB.XML • E’ il file di descrittore di ciascuna WEB APPLICATION. Viene letto dall’application Server. NON E’ UN FILE DI CONFIGURAZIONE DI STRUTS • In esso però scriveremo una dichiarazione ad hoc per far si che ogni richiesta venga elaborata da una particolare servlet che estende la ActionServlet delle API di Struts
WEB.XML <servlet> <servlet-name>action</servlet-name><servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> …. </servlet> <servlet-mapping> <servlet-name>action</servlet-name><url-pattern>*.do</url-pattern> </servlet-mapping>
Struts-config.xml; tag <action> • Indica mapping fra risorse View, Controller, Model • Tag <action> • All’interno si dichiara in quale classe è implementata la logica di controllo che deve gestire la richiesta di una risorsa effettuata dal client, quale è la view e quale è il model con il quale si devono rappresentare i dati • Esaminiamo, per concludere il discorso sul Controller, i tipi di classi Action messi a disposizione da Struts e vediamo eventualmente come definire una nostra Action che implementa una logica non identificabile tra le Action già implementate in Struts
Actions in Struts • Ogni classe di tipo Action deve estendere la classe org.apache.struts.action.Action • Ogni Action deve ridefinire il metodo execute() che ha la seguente segnature: public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception • Non è compito dello sviluppatore istanziare la classe ACTION!!! • Sarà la ActionServlet, in base a quanto dichiarato nel file di configurazione struts-config.xml, ad istanziare la corretta Action e a chiamare il metodo execute in essa ridefinito.
Esempio di Action package org.prova;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.struts.action.Action;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;public class TestAction extends Action {public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception{// Logica di controllo (codice Java) … … //al termine devo restituire una istanza di ActionForward per soddisfare //la segnatura del metodo execute() return mapping.findForward("testAction"); }}
Struts-config.xml: tag <action> <action-mappings> <action path="/TestAction" type=“org.prova.TestAction"> <forward name="testAction" path="/pages/TestAction.jsp"/> </action> </action-mappings>
Actions Built-in di Struts • Vi sono alcune Action già implementate che offrono funzionalità comuni. Possibile usarle direttamente. • org.apache.struts.actions.DispatchAction • Riceve valore che può funzionare come discriminante in un parametro della URL. Invece di execute, un metodo per ogni valore di tale parametro. A seconda del valore presente nel parametro, Struts chiamerà il metodo corrispondente • org.apache.struts.actions.ForwardAction • Chiama pagina jsp. Non richiede nessuna implementazione di codice ma solo dichiarazione opportuna in tag <action>
Esempio di Dispatch Action package org.prova;import java.io.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.ServletException;import org.apache.struts.actions.DispatchAction;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping; public class Dispatch_Action extends DispatchAction {public ActionForward add( ActionMapping mapping, ActionForm form, HttpServletRequest request HttpServletResponse response) throws Exception { System.out.println("You are in add function.");return mapping.findForward("add"); }
Dispatch action (contd.) public ActionForward edit( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { System.out.println("You are in edit function.");return mapping.findForward("edit"); } }
Dispatch Action: struts-config.xml <action path="/DispatchAction"type=“org.prova.Dispatch_Action"parameter=“discrimina"input="/pages/DispatchAction.jsp"name="DispatchActionForm"> <forward name="add" path="/pages/DispatchActionAdd.jsp" /><forward name="edit" path="/pages/DispatchActionEdit.jsp" /><forward name="search“ path="/pages/DispatchActionSearch.jsp"/> </action>
ForwardAction: struts-config.xml • Forward Action richiede sola configurazione; non è necessario scrivere codice Java <actionpath="/success"type="org.apache.struts.actions.ForwardAction"parameter="/pages/Success.jsp"input="/pages/ForwardAction.jsp“> </action>
Model in Struts • Struts non dettaglia scelte specifiche sulle componenti che riguardano il Modello. • Fondamentalmente il Modello deve occuparsi del reperimento di dati e informazioni ignorando comunque come esse verranno presentate nella View • Per il modello vi sono molte API che permettono ad esempio l’interfacciamento con un database (JDBC, Hibernate…)
ActionForm: il punto di raccordo tra Model e View • Struts prevede struttura di supporto per raccordare i dati ottenuti dal modello e renderli più facilmente manipolabili da una View. • ActionForm: Java Bean estende org.apache.struts.action.ActionForm, le cui variabili membro contengono i valori di un form html dichiarato nella view (oltre eventuali parametri passati nella URL e tag di tipo “hidden”) • ActionForm popolato automaticamente da Struts • Ogni pagina jsp “dovrebbe” contenere la dichiarazione di un form html. Attraverso opportuni tag dichiaritivi contenuti nella pagina JSP, Struts sarà in grado di popolare il bean associato a tale form
ActionForm: esempio package org.prova; import org.apache.struts.action.ActionForm; public class DispatchActionForm extends ActionForm { private String discriminante =" "; public String getDiscriminante( ) { return discriminante; } public void setDiscriminante(String discriminante) { this.discriminante = discriminante }
Action Form: struts-config.xml <form-bean name="DispatchActionForm" type=“org.prova.DispatchActionForm"/>
View in Struts • Struts estende Java Server Pages (JSP) aggiungendo ulteriori tag a quelli già presenti • Prima di vedere alcuni esempi però è necessario richiamare alcuni concetti di base riguardanti le pagine JSP
JSP: definizione e ciclo di vita • Java Server Pages è una tecnologia per la realizzazione di pagine web con contenuti dinamici • Una pagina JSP può contenere: • Tag HTML • Tag XML definiti in apposite librerie esterne (Tag Libraries) • Codice Java inserito in apposite sezioni denominate “Scriptlet” • Una pagina JSP viene caricata dall’application Server e tradotta in nell’output finale, HTML, subendo però un processo di generazione intermedio. Il container che si occupa di tradurre le JSP genera infatti una Servlet (JSP Page Implementation Class) • Il codice Java della Servlet si occupa di creare dinamicamente sullo stream di Output il sorgente HTML che viene offerto quale risposta alla richiesta effettuata dal client
JSP: Tag Libraries 1/2 • Le specifiche JSP prevedono tag di base identificabili dal prefisso “jsp” • In generale un tag ha un prefisso relativo alla tag library di appartenenza seguito dal nome della funzionalità che si intende utilizzare: <nome_prefisso:nome_funzione>…</nome_prefisso:nome_funzione>
JSP: Tag Libraries 2/2 • Tag library è composta da un jar e da un file “.tld” che descrive il contenuto del jar. Ha una sintassi specifica. • Il jar e il tld permettono all’opportuno componente dell’application server di tradurre i tag in frammenti di codice java. L’application server sa dell’esistenza di nuove tag libraries perché file web.xml avrà ricevuto le opportune modifiche per le nuove dichiarazioni di tag libraries aggiuntive • Processo di traduzione da JSP in Servlet e produzione del codice HTML di output interamente server-side
JSP: scriptlet • Codice Java incluso direttamente, racchiuso tra opportuni marcatori; se necessario si possono anche scrivere tag html. • Problema manutenzione di JSP contenente scriptlet, HTML e tag appartenenti a librerie • Esistono oggi molte tag libraries, comprese quelle aggiunte da Struts e le note JSTL, che permettono tramite tag di rendere una pagina JSP facilmente “scriptless”
Tag Libraries di Struts • Bean: contiene tag per la manipolazione e l’accesso di Java Bean • Html: contiene tag per creare form HTML gestibili attraverso Struts e ulteriori tag per generare altri elementi html (ovvero permettono di non usare direttamente tag HTML dentro la pagina JSP) • Logic: contiene tag per riprodurre logica decisionale, cicli iterativi e valutazioni di valori
Esempio finale • Faremo vedere i componenti di una mini web application struts che visualizza una pagina con un form nel quale è possibile inserire un numero • Se questo numero è uguale ad 1 verrà visualizzato una pagina con un messaggio di successo. • In ogni altro caso verrà visualizzata una pagina di insuccesso.
Form bean • Ci serve un bean in cui memorizzare il numero che verrà inserito nel form visualizzato dall’utente. package org.prova;import org.apache.struts.action.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class LogicForm extends ActionForm { private long number; public long getNumber() {return number; }public void setNumber(long number) {this.number=number; } }
Pensiamo ora alla Action • Non ha bisogno di logica operativa particolare; dovrà soltanto restituire il mapping alla pagina successiva (ovvero la pagina dove esaminerò il valore introdotto dall’utente e stamperò un msg di successo/insuccesso)
Action package org.prova;import java.io.*;import java.util.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.ServletException;import org.apache.struts.action.*;public class LogicAction extends Action {public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException { //Il mapping identificato dalla stringa “success” si trova in struts-config.xml return mapping.findForward("success"); }}
Configuriamo lo struts-config.xml per il bean e per la action <form-bean name="LogicForm" type=“org.prova.LogicForm" /> <action path="/LogicAction"type=“org.prova.LogicAction"name="LogicForm"input="/pages/InputLogic.jsp"> <forward name="success" path="/pages/output.jsp"/> </action>
InputLogic.jsp <%@ taglib uri="/tags/struts-html" prefix="html" %><%@ taglib uri="/tags/struts-logic" prefix="logic" %><html:html><head><title>Esempio tag Logic</title></head><body><html:form action="/LogicAction" method ="post"><h2>Enter a number:</h2><html:text property="number"/><br>
InputLogic.jsp (contd.) <br><h3>Nella pagina di output logic:equal funzionerà se il valore inserito sarà 1</h3><h3>altrimenti verrà eseguito logic:notEqual</h3><br><html:submit value="Submit"/><html:cancel/></html:form></body></html:html>
Output.jsp <%@ taglib uri="/tags/struts-bean" prefix="bean" %><%@ taglib uri="/tags/struts-logic" prefix="logic" %><html><head><title>Verifichiamo il dato...</title></head><body><h3>Il momento della verifica!!!!!</h3><h4>Il numero inserito è:</h4>
Output.jsp <bean:write name="LogicForm" property="number"/></h4><logic:equal name="LogicForm" property="number" value="1"><h4>Hai immesso il numero 1 e sono entrato nel tag equal</h4> </logic:equal><logic:notEqual name="LogicForm" property="number" value="1"><h4>Hai immesso un numero diverso da 1 e sono entrato nel tag notEqual</h4> </logic:notEqual></body></html>
Fonti: • Chuck Cavaness, Programming Jakarta Struts, 2nd Edition, O’Reilly, 2004 • http://struts.apache.org/ • http://www.infoq.com/minibooks/starting-struts2 • http://www.roseindia.net/struts/