Le applicazioni web e Java

III parte: Le Java Server Pagesdi

Nel precedente articolo della serie abbiamo descritto le servlet, il componente della J2EE che costituisce la spina dorsale di tutte le web application. In questo articolo introduciamo le Java Server Pages, la tecnologia per la costruzione dell‘interfaccia utente nelle applicazioni web J2EE.

Introduzione

Nel precedente articolo abbiamo descritto i concetti di base riguardanti la Servlet API. Abbiamo visto come le servlet costituiscano la spina dorsale di ogni applicazione web J2EE consentendo di gestire in maniera molto semplice per lo sviluppatore il paradigma richiesta/risposta tipico di queste applicazioni. Come abbiamo già  accennato il ruolo principale di una servlet è quello di controller; una servlet gestisce le richieste dei client e delega l‘elaborazione a componenti opportuni in base alla logica applicativa. Nel primo esempio di servlet abbiamo anche visto come sia possibile inviare al client un flusso HTML di risposta inserendo direttamente nel codice di uno dei metodi di servizio, doGet() e doPost(), il codice della pagina HTML. Questa tecnica, interessante solo da un punto di vista didattico, non è quella usata nelle applicazioni reali per la costruzione dell‘interfaccia utente. Per il livello di presentation di una web application J2EE ci viene in aiuto un‘altra specifica fondamentale nella piattaforma J2EE, le Java Server Pages.

Le Java Server Pages

Il layer di presentation di una applicazione web, e di una applicazione in generale, è estremamente importante perchà© è quello che consente all‘utente di fruire delle funzionalità  dell‘applicazione stessa. Una interfaccia utente costruita correttamente sia dal punto di vista grafico sia funzionale è molto importante per il successo di una applicazione. Nel mondo delle applicazioni web l‘interfaccia utente è costituita da un internet browser, Internet Explorer Mozilla Firefox o altri, che è in grado di interpretare codice HTML. Abbiamo già  discusso nel primo articolo la differenza tra pagine statiche e dinamiche e abbiamo visto come siano le seconde a assumere particolare rilevanza nel mondo delle applicazioni web. La tecnologia che nell‘ambito della J2EE ci consente di costruire pagine web dinamiche è la Java Server Pages.

Dal punto di vista dello sviluppo una JSP a prima vista non sembra molto diversa da una comune pagina HTML. Il sorgente è un normale file di testo contenente tag HTML e una serie di direttive, dichiarazioni e tag particolari che vedremo.

Ma nonostante l‘aspetto del suo sorgente una JSP è qualcosa di molto diverso da una comune pagina web statica. La differenza risulta evidente quando si analizza cosa accade quando una pagina JSP viene invocata da un client e va in esecuzione.

Innanzitutto è bene sottolineare che, come si evince dal nome stesso, una JSP è un componente server-side, che va in esecuzione nel web container e, anche se viene scritta come fosse una pagina HTML, non va in esecuzione lato client.

La cosa però veramente importante da sottolineare è che una JSP è una classe Java ed in particolare è una servlet. Una JSP unisce quindi tutte le caratteristiche di una normale servlet alla possibilità  di creare una interfaccia web dinamica utilizzando le stesse tecniche usate nella scrittura di pagine web statiche.

Il sorgente di una pagina JSP è un file di testo con estensione .jsp che contiene al suo interno tag HTML più altri elementi caratteristici della specifica JSP.

Una pagina JSP viene deployata nel web container è può essere invocata da un internet browser analogamente a quanto accade per una semplice pagina HTML. A differenza però di quanto avviene per una semplice pagina HTML il processo di elaborazione di una JSP è molto più complesso.

Quando il web server riceve una richiesta per una pagina JSP non essendo in grado di soddisfarla delega l‘elaborazione al web container. La pagina JSP a questo punto viene tradotta dal web container in una classe Java, viene compilata, viene caricata in memoria ed inizializzata analogamente a quanto visto per una comune servlet. Dopo la prima richiesta la servlet generata dalla traduzione e dalla compilazione della pagina JSP sorgente resta in memoria nello stato di servizio per ricevere e gestire le richieste dei client.

Da questo momento in poi la JSP è in grado di servire tutte le richieste client ad essa dirette in modo assolutamente identico a quanto accade per una servlet. Dopo il processo di elaborazione costituito da traduzione, compilazione, caricamento in memoria e istanziamento la JSP non è altro che una servlet e segue lo stesso ciclo di vita.

Nella Figura 1 è rappresentato il processo descritto:

Figura 1 - L‘elaborazione di una pagina JSP

La codifica di una pagina JSP

Ã? interessante capire come quello che scriviamo in una pagina JSP venga poi tradotto nella classe generata dal container. Come primo esempio possiamo vedere una pagina JSP molto semplice che produce un output analogo a quello prodotto dalla servlet vista nel precedente articolo della serie. Il sorgente della nostra prima pagina hello.jsp è il seguente:

<%@ page contentType="text/html;charset=windows-1252"%>

    
        
        hello
    
    
        HELLO WORLD!
    

E‘ facile notare come il codice della pagina hello.jsp sia quasi del tutto del puro e semplice codice HTML a meno della prima riga che vedremo essere una direttiva JSP.

La pagina in questione però non viene servita direttamente al client dal web server ma subisce il processo di elaborazione descritto al paragrafo precedente. A seguito della traduzione che il web container esegue quando un client invoca per la prima volta la pagina JSP si ottiene la seguente classe Java:

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
            implements org.apache.jasper.runtime.JspSourceDependent {

    private static java.util.List _jspx_dependants;    

    public Object getDependants() {
        return _jspx_dependants;
    }

    public void _jspService(HttpServletRequest request, HttpServletResponse response)
            throws java.io.IOException, ServletException {

    JspFactory _jspxFactory = null;
    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;

        try {
            _jspxFactory = JspFactory.getDefaultFactory();
            response.setContentType("text/html;charset=windows-1252");
            pageContext 
            = _jspxFactory.getPageContext(this, request, response,
                            null, true, 8192, true);
            _jspx_page_context = pageContext;
            application = pageContext.getServletContext();
            config = pageContext.getServletConfig();
            session = pageContext.getSession();
            out = pageContext.getOut();
            _jspx_out = out;
            out.write("
");
            out.write("
");
            out.write("
");
            out.write("
");
            out.write("hello
");
            out.write("
");
            out.write("
");
            out.write("HELLO WORLD!
");
            out.write("
");
            out.write("");
        } catch (Throwable t) {
            if (!(t instanceof SkipPageException)){
                out = _jspx_out;
                if (out != null && out.getBufferSize() != 0)
                    out.clearBuffer();
                if (_jspx_page_context 

                   != null) _jspx_page_context.handlePageException(t);
            }
        } finally {
            if (_jspxFactory 
                != null) _jspxFactory.releasePageContext(_jspx_page_context);
        }
    }
}

La classe hello_jsp.java è stata generata eseguendo la JSP su Jakarta Tomcat 5.5 uno dei più diffusi web container, ma il risultato sarebbe stato analogo in un qualsiasi altro web container J2EE compliant.

Già  da questo semplice esempio è facile osservare dove vada a finire il codice scritto nel sorgente della pagina e cosa aggiunga di suo il traduttore JSP.

Il codice HTML statico viene generato mediante delle out.write() analogamente a quanto facevamo nel primo esempio di servlet proprio allo scopo di fare vedere che questa è la tecnica usata nelle servlet generate dalle pagine JSP. Il codice che genera il flusso HTML fa parte del metodo _jspService() che è l‘analogo dei metodi doGet() e doPost() di una normale servlet. All‘inizio del metodo _jspService() il traduttore inserisce la definizione di una serie di oggetti standard quali ad esempio il ServletConfig ed il ServletContext. Questi oggetti detti "impliciti" perchà© vengono definiti automaticamente in fase di traduzione sono a disposizione in tutte le pagine JSP e consentono quindi di svolgere tutte le operazioni comunemente effettuate all‘interno dei metodi di una servlet.

L‘esempio banale presentato ha lo scopo quindi di far comprendere che una pagina JSP non è altro che una Java Servlet, che all‘interno di essa è possibile inserire codice Java cosଠcome si fa con una normale classe e che una pagina JSP ha la visibilità  di tutti gli oggetti a disposizione delle servlet di una applicazione.

Gli elementi fondamentali delle pagine JSP

La prima JSP che abbiamo visto è estremamente semplice e differisce da poco da una normale pagina HTML. In realtà  in una pagina JSP sono molti gli elementi di differenza rispetto ad una pagina statica.

Gli elementi fondamentali che costituiscono una pagina JSP sono

  • direttive
  • scriptlet
  • espressioni
  • dichiarazioni

Le direttive sono delle istruzioni che si possono dare al container in modo da influenzare la fase di traduzione della pagina JSP in classe Java. Ad esempio con una direttiva si può importare un package nel sorgente della classe java generata dalla pagina JSP. Una direttiva è inserita tra i simboli <%@ %> come nell‘esempio che segue:

<%@ page import="miopackage.*"  %>

Le direttive sono tre, page include e taglib,e per una loro descrizione approfondita rimandiamo al tutorial J2EE [2]. La cosa importante a questo livello da sottolineare è che una direttiva agisce in fase di traduzione di una pagina JSP non in fase di compilazione nà© di esecuzione.

Altro elemento fondamentale sono gli scriptlet. Gli scriptlet sono normali istruzioni Java inserite nel sorgente di una pagina JSP tra i simboli <% %> che il traduttore inserisce nel corpo del metodo _jspService() in fase di traduzione. Utilizzando gli scriptlet è quindi possibile scrivere qualsiasi cosa in Java in una pagina JSP anche se questa pratica è estremamente sconsigliata perchà© porta alla realizzazione di pagine JSP incomprensibili e difficili da mantenere. Alcuni consigli sulle best practises per la realizzazione di pagine JSP scriptless sono riportate in [3].

Ulteriore elemento fondamentale sono le espressioni. Una espressione è racchiusa tra i simboli

<%=  %> 

e consente di inviare nell‘output della pagina qualsiasi cosa che sia il risultato dell‘istruzione inserita tra i due tag visti. In pratica il container prende qualsiasi cosa si inserisca tra i tag <%= %> e lo mette come argomento di una istruzione che stampa sullo stream di risposta.

Ad esempio scrivere in una pagina JSP:

<%= miooggetto.getValore() %>

viene tradotto nel metodo _jspService() in una istruzione del tipo

out.write(miooggetto.getValore())

In pratica l‘output del metodo getValore() dell‘oggetto miooggetto viene stampato sulla pagina.

Altro elemento di base sono le dichiarazioni. Una dichiarazione consente di definire variabili o metodi nella classe Java generata dalla traduzione della pagina JSP. Anche con uno scriptlet è possibile definire una variabile ma a differenza di queste le variabili definite con una dichiarazione non sono locali al metodo _jspService() ma esterne, ovvero sono variabili di istanza. Le dichiarazioni sono inserite tra i tag <%! %>.

Quind scrivere <% int numero = 0; %> si traduce nel definire una variabile numero di tipo int inizializzata al valore 0 all‘interno del metodo _jspService(). Scrivere invece <%! int numero = 0; %> si traduce nel definire un attributo di nome numero di tipo int inizializzato a 0 nella classe generata dalla traduzione della pagina JSP.

Cosଠcome si definiscono variabili con le dichiarazioni è possibile definire metodi anche se questa è una pratica poco diffusa in quanto la best practice ripetiamo è quella di scrivere pagine scriptless [3].

Il ruolo delle JSP

Abbiamo introdotto nei paragrafi precedenti alcuni elementi di base della tecnologia JSP per far comprendere prima di tutto cosa sia una JSP e come venga elaborata dal web container. La carrellata degli elementi di base che costituiscono una pagina JSP non è ovviamente esaustiva perchà© sono molti gli aspetti che meriterebbero attenzione e che non possono essere oggetto di questo primo articolo introduttivo.

Una cosa da sottolineare subito è però il ruolo che hanno le pagine JSP in una applicazione web ben strutturata. Cosଠcome avevamo visto che il ruolo delle servlet è quello di controller possiamo affermare che il ruolo delle JSP è quello di presentation. Una JSP deve realizzare il livello di presentazione all‘utente dei dati dell‘applicazione e deve rispondere agli input dell‘utente notificandoli allo strato di controllo dell‘applicazione. Quello che non deve essere assolutamente inserito in una pagina JSP sono istruzioni relative alla business-logic dell‘applicazione. Il fatto che in una pagina JSP sia possibile inserire codice Java analogamente a quanto si fa in una regolare classe è una forte tentazione soprattutto per lo sviluppatore inesperto. Questa pratica conduce ad applicazioni non gestibili, difficili da comprendere e manutenere, nelle quali non c‘è una separazione logica tra i vari livelli che la costituiscono. Inoltre cosଠfacendo si vanificano tutte le potenzialità  che un linguaggio object-priented come Java ci può offrire. In conclusione come regola di buon senso si può dire che una pagina JSP dovrebbe somigliare più ad una pagina HTML che ad una classe Java.

Ovviamente per ottenere questo risultato si devono utilizzare alcuni strumenti non visti in questo capitolo come l‘espression language e i custom tag già  trattati in parte negli articoli della serie sulle JSTL [3].

Conclusioni

In questo articolo è stata introdotta la tecnologia delle Java Server Pages lo strumento della J2EE per la costruzione della view di una applicazione web. Come già  fatto nel caso delle servlet l‘intento era di fornire un‘introduzione di natura più concettuale che pratica per far capire soprattutto a chi per la prima volta si avvicina allo sviluppo di applicazioni web in Java quali siano gli strumenti che la J2EE mette a disposizione. Nei prossimi articoli affronteremo aspetti più di dettaglio che ci faranno capire come poi si possano utilizzare tutti questi strumenti per la realizzazione di applicazioni reali.

Riferimenti

[1] Bryan Basham - Kathy Sierra - Bert Bates, "Head First - Servlet & Jsp", O‘Reilly, 2004

[2] Autori Vari, "The J2EE 1.4 Tutorial ", Sun Microsystems, 2003

[3] Alfredo Larotonda, "La Java Server Pages Standard Tag Library. I parte: Scrivere JSP scriptless" MokaByte 91, dicembre 2004

Condividi

Pubblicato nel numero
112 novembre 2006
Alfredo Larotonda, laureato in Ingegneria Elettronica, lavora da diversi anni nel settore IT. Dal 1999 si occupa di Java ed in particolare dello sviluppo di applicazioni web J2EE. Dopo diverse esperienze di disegno e sviluppo di applicazioni web per il mercato finanziario e industriale, si occupa ora in particolare di…
Articoli nella stessa serie
Ti potrebbe interessare anche