# # FAQ - Laboratorio di programmazione di rete # # Versione: 1.0 # Edited by: Ivo Marino # Last modified: Tue, 24 Jan 2006 10:01:51 PM +0100 # 0. Indice --------- 0. Indice 1. Differenze tra JSP e JavaScript 2. Un esercizio sulle servlet (codice) 3. Un esercizio sulle pagine javascript (codice) 4. Funzionamento delle servlet 5. Descrizione dei file da creare per l'utilizzo della servlet 6. Tipi di redirezione 7. Cookie 8. HTTP session 9. Java server pages + dichiarazioni + commenti + espressioni 10. JavaBean 11. Tag personalizzati 1. Differenze tra JSP e JavaScript ---------------------------------- La prima sostanziale differenza risulta negli end-point in cui il codice viene "eseguito". Nel primo caso il codice viene "elaborato" sul server mentre nel secondo direttamente sul client. Sia nel caso di codice JSP che JavaScript viene eseguito un parsing delle istruzioni presenti nel codice. Il codice JSP viene elaborato sul server da parte del webserver (Tomcat) mentre il codice JavaScript viene eseguito direttamente dal browser del client. Un codice JSP viene in ogni caso compilato almeno una volta sul webserver mentre un codice JavaScript viene interpretato ogni qualvolta il browser accede alle sue funzioni. Un codice JSP, viene elaborato server-side, e l'output dello stesso viene inviato al client -- Ovviamente si tratta solitamente di codice HTML che il client potra' opportunamente visualizzare. Cio' permette di fornire al client contenuti dinamici richiesti precedentemente. Dunque con delle istruzioni JSP possiamo elaborare richieste da parte del client in maniera dinamica lato del server, cio' permette, ad esempio, di accedere, da parte del server, a risorse visibili solamente al server, elaborare quest'ultime ed inviare le informazioni al client. Una servlet e' un programma applicativo che viene eseguito dal server web. Accoglie ed elabora richieste attraverso comandi POST e GET. Il servlet e' una classe Java che implementa l'interfaccia servlet. Un servlet e' ospitato all'interno di un servlet container il quale puo' ospitare anche piu' di una servlet con relativi alias. Quando una servlet viene invocata per la prima volta il servlet engine genera un thread Java che inizializza l'oggetto Servlet, questo oggetto persiste per tutta la durata del processo relativo al server container salvo esplicita de-allocazione. Ogni servlet e' dunque un thread all'interno del Servlet Container. Un servlet e' in grado di processare richieste multiple in modo concorrente (e.g. conferenze online). Un servlet puo' anche eseguire dei forward ad altre servlet in modo da bilanciare il carico di lavoro. La tecnologia Java Server Pages e' una soluzione multipiattaforma per realizzare pagine HTML dinamiche, dal lato server. Le pagine JSP sono un' evoluzione dei gia' collaudati servlet Java, create per separare i contenuti dalla loro presentazione: una pagina JSP si presenta, infatti, come un normale documento in linguaggio HTML, frammentato da sezioni di codice Java. Si potranno quindi modificare le parti sviluppate in Java lasciando inalterata la struttura HTML o viceversa. La tecnologia JSP e' stata creata con l'ulteriore intento di facilitare la creazione di pagine finalizzate al commercio elettronico (lo stato puo' essere facilmente mantenuto in una sessione HTML, permettendo la memorizzazione di eventuali acquisti, annullati solamente alla chiusura del browser), largamente utilizzato di questi tempi e sicuramente in via di ulteriore sviluppo. 2. Un esercizio sulle servlet (codice) -------------------------------------- /* * this.foo * * $Revision: 1.1 $ * $Date: 2006/01/26 13:30:19 $ * $Author: IvoMarino $ */ package this; import javax.servlet.*; /** * Gestione foo. * * @author Ivo Marino * @version $Revision: 1.1 $ */ public class foo extends HttpServlet { /** * Verifica bar. * * @author Ivo Marino * @version 0.1 * @return Ritorna la posizione d'indice di MyCookies[] in cui si trova * Il cookie "AttemptToAccess", -1 altrimenti. */ protected int bar(Cookie[] MyCookies) { int ReturnValue = -1; // Do something return ReturnValue; } /** * Metodo che sovrascrive doPost. * * @author Ivo Marino * @version 0.1 */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String MyReq = "null"; String MyLoginUsername = request.getParameter("nome_utente"); // Alloca MyHTMLOutput out.println(MyHTMLOutput); out.close(); } // Serial version private static final long serialVersionUID = 1L; // Open a DBMS connection private Connection MyDBMSConnection = MyHandleDBMS.OpenDBMSConnection(); } 3. Un esercizio sulle pagine javascript (codice) ------------------------------------------------ JavaScript consiste in: . Funzioni . Metodi (appartenenti ad un'oggetto) Esempio di codice JavaScript: 4. Funzionamento delle servlet ------------------------------ Il server web riceve dal browser del client una richiesta HTTP GET o POST. Questa richiesta viene poi rediretta dal web server al servlet engine (anche chiamato servlet container). Se la servlet non e' ancora in memoria viene caricata ed inizializzata da dal servlet engine. Il servlet engine incapsula la richiesta HTTP in una classe HttpServletRequest e la passa al metodo doPost o doGet derl servlet. Il servlet risponde scrivendo il codice HTML nella HttpServletResponse che viene rimandata al web server e poi riconsegnata al client via HTTP. Schema di funzionamento: +-------- Java Virtual Machine ------+ | | | <---------- HttpServletResponse <-. +--------+ +------------+ | | | CLIENT | <- HTTP -> | WEB SERVER | -> HttpServletRequest | | +--------+ +------------+ \ | | Browser | `----> Servlet ------' | | +------------------------------------+ Come anticipato prima il servlet container (o servlet enginge) e' il server che esegue una servlet. Le servlet possono essere usate sia con HTTP che FTP. Nella forma piu' generale una servlet e' un'estensione di una classe javax.servlet.GenericServlet che implementa l'interfaccia javax.servlet.Servlet. Le servlet usate nel web sono estensioni della classe javax.servlet.http.HttpServlet che implementa l'interfaccia javax.servlet.Servlet. Tutte le servlet devono implementare l'interfaccia javax.servlet.Servlet. Tutti metodi di quest'interfaccia vengono invocati dal servlet container secondo un prefissato ciclo di vita. Ciclo di vita di una servlet: 1) Caricamento della servlet in memoria. 2) Il container della servlet invoca il metodo init (una sola volta): . Solo ora la servlet e' in grado di rispondere alla prima richiesta. . Inizilizazzione delle variabili globali. 3) Il metodo service gestisce le richieste (invocato ad ogni richiesta): . Riceve la richiesta. . Elabora la richiesta. . Spedisce una risposta al client. 4) Il metodo destroy rilascia le risorse allocate dalla servlet quando il container la termina. Esistono due classi astratte che implementano l'interfaccia Servlet: . GenericServlet . HttpServlet Entrambi le classi forniscono l'implementazione di default di tutti i metodi dell'interfaccia Servlet. Il metodo chiave e' service che riceve come parametri gli oggetti HttpServletRequest e HttpServletResponse. La classe HttpServlet sovrascrive i metodo service che invoca i metodi doGet e doPost che ricevono come parametri gli oggetti HttpServletRequest e HttpServletResponse. 5. Descrizione dei file da creare per l'utilizzo della servlet -------------------------------------------------------------- E' necessario creare alcuni file in modo da poter far uso di un servlet disponibile all'interno del web container: . WEB-INF/web.xml Mappa il servlet ad un dato URL di richiesta. . WEB-INF/classes/ Cartella che conterra' le classi compilate 6. Tipi di redirezione ---------------------- Esistono sostanzialmente 2 modi per eseguire un redirect. 1. SendRedirect(String Location) -------------------------------- Redirect Servlet -> JSP: Si fa uso del metodo SendRedirect(String Location) della classe HttpServletResponse. Questa tecnica di redirect puo' essere usata solamente con richieste di tipo GET (doGet) ed i parametri del redirect saranno visibili al client come variabili GET. 2. getRequestDispatcher() ------------------------- Si invoca il metodo getRequestDispatcher() di ServletContext fornendo la relativa URL di redirect. Questa tecnica puo' essere usata si per richieste di tipo GET che POST. Non coinvolge il client come fa response.SendRedirect() ed e' dunque la scelta preferita. forward ------- Si invoca il metodo forward della classe RequestDispatcher per trasferire il controllo completo alla pagina di destinazione, in tal caso non avviene nessuna comunicazione con il client come avviene con response.SendRedirect(). include (opzionale) ------------------- Si invoca il metodo include per inserire l'output della pagina di destinazione e continuare l'elaborazione. 7. Cookie --------- Attorno ai cookies e' cresciuta col passare del tempo una sorta di cattiva reputazione, dovuta all'uso improprio che ne viene fatto da alcuni progettisti di pagine Web. I cookies non sono altro che quell'insieme di informazioni associate ad un particolare dominio che vengono memorizzate sul client sotto forma di file di solo testo, in modo da poter riconoscere un particolare utente dell'applicazione. Con lo sviluppo di applicazioni sempre piu' complesse ed efficienti, l'utilizzo dei cookies e' diventato indispensabile, come anche far capire agli utenti del sito che, se usati nel modo giusto, non fanno altro che migliorare la loro navigazione. Fatte queste premesse, vediamo quali sono le istruzioni che ci servono. Naturalmente la prima fase e' quella di scrivere un cookie, compito del metodo addCookie() dell'oggetto response: response.addCookie(cookie) Dove il parametro di ingresso cookie non e' altro che una classe che ha alcuni metodi che ci permettono di impostare le proprieta' del cookie. Ecco come: Cookie mioCookie = new Cookie ("nome", "valore"); response.addCookie(mioCookie); A questo punto mioCookie e' scritto sul client. Per leggerlo l'operazione e' leggermente piu' complicata. L'oggetto request dispone infatti di un metodo getCookies() che restituisce un array di oggetti cookie trovati nel client. Una volta ottenuto l'array, e' quindi necessario passare in rassegna tutti i suoi elementi fino a trovare quello che ci interessa. 8. HTTP session --------------- Una delle funzionalita' pia' richieste per un'applicazione Web e' mantenere le informazioni di un utente lungo tutto il tempo della sua visita al sito. Questo problema e' risolto dall'oggetto implicito Session che gestisce appunto le informazioni a livello di sessione, relative ad un singolo utente a partire dal suo ingresso alla sua uscita con la chiusura della finestra del browser. E' possibile quindi creare applicazioni che riconoscono l'utente nelle varie pagine del sito, che tengono traccia delle sue scelte e dei suoi dati. E' importante sapere che le sessioni vengono memorizzate sul server e non con dei cookies che devono pero' essere abilitati per poter memorizzare il cosi detti SessionID che consente di riconoscere il browser e quindi l'utente nelle fasi successive. I dati di sessione sono quindi riferiti e riservati ad un utente a cui viene creata un'istanza dell'oggetto Session e non possono essere utilizzati da sessioni di altri utenti. Per memorizzare i dati all'interno dell'oggetto session e' sufficiente utilizzare il metodo setAttribute specificando il nome dell'oggetto da memorizzare e una sua istanza. Per esempio, per memorizzare il nome dell'utente al suo ingresso alla pagina ed averlo a disposizione i seguito e sufficiente fare session.setAttribute("nomeUtente", nome) a patto che nome sia un oggetto di tipo stringa che contenga il nome dell'utente. 9. Java server pages + dichiarazioni + commenti + espressioni ------------------------------------------------------------- Come gia' detto i servlet sono uno degli elementi fondamentali da cui deriva e a cui si appoggia la teconogia JSP. Qui di seguito verra' fatto un accenno alla natura di tali elementi affinche' risultino poi piu' chiari alcuni richiami teorici riguardanti le pagine JSP. Un servlet non e' altro che un'applicazione Java in esecuzione su una JVM (Java Virtual Machine) residente su un server. Questa applicazione tipicamente esegue una serie di operazioni che producono in output un codice HTML che verra' poi inviato direttamente al client per venire interpretato da un qualsiasi Browser che non necessita di funzionalita' aggiuntive. A differenza di uno script CGI i servlet vengono caricati solo una volta, al momento della prima richiesta, e rimangono residenti in memoria pronti per servire le richieste fino a quando non vengono chiusi, con ovvi vantaggi in fatto di prestazioni (risultano infatti un po' più lenti in caricamento, ma una volta "aperti" le successive richieste vengono evase molto velocemente). Come si sara' già dedotto, affinche' le Java Server Pages siano competitive nel campo dello sviluppo web, e' necessario che offrano degli allettanti vantaggi: cosa dovrebbe spingere, dunque, uno sviluppatore a scegliere questa tecnologia? In primo luogo (a differenza di soluzioni come ASP e PHP) le JSP sono in chiave Java a e quindi eredi di tutti gli indiscussi vantaggi che hanno reso questo linguaggio di programmazione precompilato uno dei piu' sfruttati nel mondo della programmazione ad oggetti; prima fra tutti la quasi totale portabilita' (intesa come capacita' di un software di funzionare correttamente su stazioni che utilizzano un qualsiasi tipo di piattaforma). Le Java Server Pages sono a dir poco ottime per l'implementazione di programmi applicativi attivi dal lato server, essendo infatti svincolate dal tipo di sistema operativo non necessitano di nessuna modifica nemmeno dal passaggio tra server gestiti in maniera diversa (possono per esempio venire supporate sia da un server Windows che da un server Unix). Ovviamente l'aspetto della portabilita' non dev'essere visto esclusivamente sotto l'aspetto server: anche dal lato client questa neonata tecnologia offre un completo svincolamento sia dal tipo di SO che dal tipo di browser (il linguaggio Java viene infatti interpretato dal server sollevando il browser da questo compito, limitando la sua funzione a interprete di pagine HTML). Una Java Server Page possono essere invocate (richiamate) utilizzando due diversi metodi: . La richiesta puo' venire effettuata direttamente ad una pagina JSP, che grazie alle risorse messe a disposizione sul lato server, e' in grado di elaborare i dati di ingresso per ottenere e restituire l'output voluto . La richiesta puo' essere fatta in un primo tempo ad un servlet che, dopo l'elaborazione dei dati, incapsula adeguatamente i risultati e richiama la pagina JSP. Sara' poi quest'ultima che, in grado di prelevare i dati immagazzinati, produrrà l'output voluto. 10. JavaBean ------------ L'oggetto persistena Bean puo' essere usato da una pagina JSP per passare dati durante un redirect: jsp:useBean scope="page|session|application|request". Pregio importante, ma non unico quello dell'indipendenza dalla piattaforma, le JSP inoltre permettono una molto vantaggiosa possibilita' di riutilizzare il codice: si puo' infatti di includere nelle pagine sezioni di codice (java bean) che rendono molto piu' abbordabile l'implementazione di applicazioni anche complesse anche senza approfondite conoscenze di Java, rendendo inoltre molto piu' semplice la modifica e la manutenzione delle pagine stesse. Come gia' accennato le JSP sono estensioni dei servlet Java, di conseguenza consentono di ottenere tutti i risultati di questi ultimi. Lo svantaggio dei Servlet e' pero' rappresentato, come per tutti gli script CGI, dalla difficolta' di manutenzione del codice HTML delle applicazioni eccessivamente complesse, in quanto il piu' delle volte contengono una quantita' di codice scriptler eccessiva per un programmatore non esperto in Java. Soluzione a questo problema e' rappresentata dai Java Beans, componenti software contenenti una classe Java, che possono venire inclusi in una pagina JSP, permettendo quindi un ottimo incapsulamento del codice, peraltro riutilizzabile. Al programmatore quindi sara' pressoche' invisibile la sezione di codice puro sostituito da richiami ai metodi delle classi incluse. I Bean sono costituiti esclusivamente da codice Java e possono venire realizzati con un semplice editor di testo, salvati con estensione .java e compilati generando un file di estensione .class. Sara' il file .class che dovra' venire incluso nella pagina JSP. Esistono tre azioni standard per facilitare l'integrazione dei JavaBean nelle pagine JSP: Permette di associare un'istanza di un JavaBean (associata ad un determinato ID) ad una variabile script dichiarata con lo stesso ID. In pratica offre la possibilita' di associare la classe contenuta nel JavaBean ad un oggetto visibile all'interno della pagina, in modo da poter richiamare i suoi metodi senza dover ogni volta far riferimento al file di origine. class: nome della classe che definisce l'implementazione dell' oggetto beanName: contiene il nome del bean che, come gia' accennato deve coincidere con il nome del file .class (senza estensione) Esempio: Crea un'istanza della classe classe con ambito session richiamabile attraverso l'id NomeBean: da questo momento sara' possibile accedere a metodi e variabili (pubbliche) attraverso la sintassi nomeBean.nomeMetodo e nomeBean.nomeVariabile, rispettivamente per metodi e variabili. Vediamo subito un semplice esempio di bean, realizzato per contenere le informazioni di un utente durante la sua permanenza nel sito. InfoUtente.java --------------- public class InfoUtente { private String nome = null; private String email = null; private int pagineViste; public InfoUtente() { pagineViste=0; } public aggiornaPV(){ pagineViste++; } public int getPagineViste(){ return pagineViste; } public void setNome(String value) { nome = value; } public String getNome() { return nome; } public void setEmail(String value) { email = value; } public String getEmail() { return email; } public String riassunto() { String riassunto = null; riassunto = "Il nome dell'utente è"+nome+","; riassunto+= "il suo indirizzo e-mail è: "+email; riassunto+=" e ha visitato "+pagineViste+" del sito"; return riassunto; } } Come e' facile capire, questo bean contiene il nome dell'utente ed i metodi per modificarlo e restituirlo, il suo indirizzo e-mail con i relativi metodi, il numero di pagine viste dall'utente e un metodo che restituisce un riassunto schematico dei dati dell'utente. Ecco come utilizzarli: Utilizzo del Bean <% utente.setNome("Zina&Tram"); utente.setEmail("ciao@dom.it"); %> <% out.println(utente.getNome()); out.println(utente.riassunto()); %> <% utente.aggiornaPV(); out.println(utente.getPagineViste()); %> 11. Tag personalizzati ---------------------- In moltissimi casi l'azione puo' realizzare gli stessi obbiettivi di un tag personalizzato ma i Bean _non_ possono manipolare il contenuto JSP ed inoltre operazioni molto complesse possono essere espresse in una forma molto piu' semplice utilizzando tag personalizzati. Per definire un tag personalizzato e' necessario definire una classe handler del tag che ne implementi le funzionalita'. Inoltre e' necessario definire un descrittore della libreria di tag (TLD) e scrivere le pagine JSP che fanno uso della libreria dei tag personalizzati. Un descrittore della libreria di tag (TLD) e' un documento XML che definisce una libreria di tag e i tag in essa contenuti: WelcomeTagHandler.java ---------------------- package miei_tag; import java.io.*; public class WelcomeTagHandler extends TagSupport { public int doStartTag() throws JspException { try { JspWriter out = pageContext.getOut(); out.println("Messaggio del tag"); } return SKIP_BODY; } } mialib.tld ---------- 1.0 1.1 Libreria personale Una semplice libreria di tag welcome miei_tag.WelcomeTagHandler emptyStampa welcome index.jsp --------- Test <%@ taglib uri="/WEB-INF/tlds/mialib.tld" prefix="util" %> Richiama tag: Le funzionalita' dei tag personalizzati sono definite all'interno di classi java che implementano l'interfaccia tag e in genere estendono le classi TagSupport oppure BodyTagSupport che implementano l'interfaccia Tag. . TagSupport Si usa quando si vuole implementare tag che non elaborano il contentuto del proprio body. . BodyTagSupport Si usa quando si vuole implementare tag che elaborano il contentuto del proprio body. L'interfaccia Tag fornisce i metodi che vengono invocati dal container durante l'elaborazione del tag. Quando viene elaborato un tag il container richiama i seguenti tre metodi del package javax.servlet.jsp.tagext nel seguente ordine: . int doStartTag() . int doEndTag() . void release() I tag handler devono essere definit all'interno di package. Si definisce l'implementazione dei metodi dell'interfaccia Tag che si ritengono utili all' eleborarzione dei tag personalizzati. E' possibile passare argomenti ad un tag.