Tecnologie Web: Parte 6m [Martedì, 6 Giugno 2006] |
---|
Home / Teaching |
Abbiamo visto come sia possibile leggere ed utilizzare in una pagina JSP un file XML esterno (ad esempio un file di configurazione). L'approccio può sicuramente essere efficace e più conveniente di un database tradizionale allorquando i dati a cui accedere siano in quantità limitata.
E se invece volessimo scrivere un file XML? Le librerie di TAG non ci vengono incontro. Né è possibile farlo tramite tag JSP. Dobbiamo utilizzare una servlet o almeno una scriplet e utilizzare direttamente Java.
Vediamolo con un esempio. Per farlo funzionare è necessario completare l'installazione del parser XML Xalan, copiando dal file di installazione [che potete trovare all'indirizzo http://www.apache.org/dist/xml/xalan-j/, ad esempio scaricate xalan-j_2_7_0-bin.zip] il file serializer.jar che va nella cartella lib della vostra applicazione.
Sempre nella cartella lib dovete anche copiare il file commons-jxpath-x.x.jar che scaricate dal sito http://jakarta.apache.org/site/downloads/downloads_commons-jxpath.cgi
Nell'esempio seguente, esempioScritturaXml.jsp, leggeremo un file XML esterno che salveremo nuovamente dopo averlo modificato. È un utile esercizio di ripasso di quanto visto durante il corso. Utili indicazioni ulteriori su come manipolare file XML da Java le trovate in forma succinta in questo tutorial on-line: http://totheriver.com/learn/xml/xmltutorial.html.
<%@ page import="org.w3c.dom.*" %> <%@ page import="org.apache.commons.jxpath.*" %> <%@ page import="java.io.*" %> <%@ page import="javax.xml.transform.*" %> <%@ page import="javax.xml.transform.dom.*" %> <%@ page import="javax.xml.transform.stream.*" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %> <c:set var="nomeFileIn" value="gestioneAsilo.xml" /> <c:set var="nomeFileOut" value="gestioneAsiloModificato.xml" /> <c:import var="MioFile" url="${nomeFileIn}" /> <x:parse varDom="domMioFile" doc="${MioFile}" /> <html> <head> <title>Esempio di manipolazione di file XML in JSP</title> </head> <body> In questo esempio vedremo come modificare un file XML. L'operazione non viene effettuata tramite TAG standard, ma direttamente in Java. Lavoreremo sul file XML <b>${nomeFileIn}</b> che contiene il seguente documento: <pre> <c:out value="${MioFile}" /> </pre> Il terzo bambino non ha configurato il valore dell'identificativo: <x:out select="$domMioFile/asilo/bambino[3]/@id"/> <br /><br /> <% // Document --> org.w3c.dom.Document // JXPathContext --> org.apache.commons.jxpath.JXPathContext // Pointer --> org.apache.commons.jxpath.Pointer // Element --> org.w3c.dom.Element // Text --> org.w3c.dom.Text Document documentoXml = (Document) pageContext.getAttribute("domMioFile"); JXPathContext contextMioFile = JXPathContext.newContext(documentoXml); Pointer puntatoreElemento = contextMioFile.getPointer("asilo/bambino[3]"); Element elementoDaModificare = (Element) puntatoreElemento.getNode(); elementoDaModificare.setAttribute("id", "palla"); // Crea un elemento figlio "Nome" e gli associa il valore testuale "Mario" Element sottoElementoNome = documentoXml.createElement("nome"); Text valoreSottoElementoNome = documentoXml.createTextNode("Mario"); sottoElementoNome.appendChild(valoreSottoElementoNome); //Crea un elemento figlio "Cognome" e gli associa il valore testuale "Rossi" Element sottoElementoCognome = documentoXml.createElement("cognome"); Text valoreSottoElementoCognome = documentoXml.createTextNode("Rossi"); sottoElementoCognome.appendChild(valoreSottoElementoCognome); //Associa i sotto elementi all'elemento da modificare selezionato in precedenza elementoDaModificare.appendChild(sottoElementoNome); elementoDaModificare.appendChild(sottoElementoCognome); %> Il documento XML in memoria è stato opportunamente modificato. Per il terzo bambino ora abbiamo: <br /> <b>Identificativo</b>: <x:out select="$domMioFile/asilo/bambino[3]/@id"/> <br /> <b>Nome</b>: <x:out select="$domMioFile/asilo/bambino[3]/nome"/> <br /> <b>Cognome</b>: <x:out select="$domMioFile/asilo/bambino[3]/cognome"/> <br /><br /> <% File fileOutput = new File(application.getRealPath((String) pageContext.getAttribute("nomeFileOut"))); // DOMSource --> javax.xml.transform.dom.DOMSource // StreamResult --> javax.xml.transform.stream.StreamResult DOMSource source = new DOMSource(documentoXml); StreamResult result = new StreamResult(fileOutput); // [22/12/2006] Utilizzando Windows può essere necessario: // StreamResult result = new StreamResult(fileOutput.toURI().getPath()); // Per scrivere il file usiamo un Transformer identità // (non compie alcuna operazione sul file) // TransformerFactory --> javax.xml.transform.TransformerFactory // Transformer --> javax.xml.transform.Transformer TransformerFactory tFactory = TransformerFactory.newInstance(); Transformer transformer = tFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.transform(source, result); %> Il file ${nomeFileOut} modificato è stato scritto in <%=application.getRealPath("/")%> </body> </html>
Il file XML di input era: gestioneAsilo.xml. mentre il file prodotto è il seguente: gestioneAsiloModificato.xml.
Durante il corso abbiamo appreso due importanti tecnologie, le servlet Java e le pagine JSP. Ma come utilizzarle in pratica? Nel gergo Sun esistono due architetture: "Model 1" e "Model 2". Vediamolo in due figure, tratte da un ottimo articolo http://www.javaworld.com/javaworld/jw-12-1999/jw-12-ssj-jspmvc.html (anche se oramai datato)
L'architettura "Model 2" è di fatto l'implementazione in questo contesto una architettura a più ampia diffusione, l'architettura MVC, dove M="Model", V="View" e C="Controller".
Alternativamente, si può presentare una visione a "stack" dell'architettura. Un ottimo articolo è http://www.onjava.com/pub/a/onjava/2003/10/15/php_scalability.html, da cui sono tratte le figure seguenti.
Tipicamente, il blocco controller viene implementato tramite il framework "Apache Struts" (http://struts.apache.org/). Struts offre una servlet di controllo standard: tutte le richieste che terminano in .do vengono opportunamente mappate ad endpoints, che ad esempio possono essere semplicemente file jsp che hanno lo stesso nome (es: pagina.do --> pagina.jsp).
Mappare semplicemente le pagine può essere utile per permettere una facile rilocazione delle risorse ma serve poco. La cosa importante è che dobbiamo dire alla nostra servlet di controllo come operare sui dati (il modello) prima di passare il controllo alla pagina JSP. In breve, dobbiamo opportunamente estendere la classe org.apache.struts.action.Action e prevedere i mapping opportuni tra le classi che abbiamo preparato e lo stato delle risposte alle richieste ricevute
<action-mappings> ... <action path="/addnews" type="com.jspbook.AddNewsAction"> <forward name="success" path="/addnews_thanks.jsp"/> <forward name="failure" path="/addnews.jsp"/> </action> ... </action-mappings>
Resta ancora da chiarire come operare l'astrazione relativa all'accesso a dati di database esterni. Una delle tecnologie (non l'unica) oggi in voga è Hibernate (http://www.hibernate.org). Semplificando la situazione, l'idea è quella di provvedere un mapping opportuno tra un oggetto Java Bean e la tabella di un database e poi lasciare ad Hibernate il resto del lavoro.
<hibernate-mapping> <class name="org.sassi.Item" table="item" > <id name="id" column="id" type="java.lang.Long" unsaved-value="0"> <generator class="identity"/> </id> <property name="name" column="name" type="java.lang.String" /> <property name="description" column="description" type="java.lang.String" /> </class> </hibernate-mapping>
Un breve tutorial, se siete interessati lo trovate a questo indirizzo: http://www.laliluna.de/first-hibernate-example-tutorial.html