JavaServer Pages
JSP o Java Server Pages, a cui talvolta si fa riferimento con Java Scripting Preprocessor è una tecnologia basata su Java che permette agli sviluppatori di generare dinamicamente XML, HTML o altri tipi di pagine web dinamiche. Questa tecnologia permette di integrare codice Java e alcune azioni predefinite in un contenuto statico.
La sintassi JSP aggiunge ulteriori tag XML, chiamati JSP action, che possono essere usati per invocare funzionalità predefinite. In aggiunta la tecnologia permette la creazione di librerie di tag JSP che fungono da estensioni dei tag standard. Le librerie di tag forniscono un metodo indipendente dalla piattaforma di estendere le capacità di un web server.
All'atto della prima invocazione, le pagine JSP vengono compilate in Servlet da un compilatore JSP. Un compilatore JSP può generare una servlet che poi sarà compilata dal compilatore Java o può direttamente generare il byte code.
JSP e Servlet
Dal punto di vista architetturale, una pagina JSP può essere vista come un'astrazione di alto livello di una servlet che è implementata come estensione delle API Servlet.
Sintassi JSP
Una pagina JSP può essere suddivisa nei seguenti sotto-componenti:
- Dati statici, per esempio HTML.
- Direttive JSP, come la direttiva include.
- Elementi di scripting JSP e variabili
- Actions JSP.
- tag custom.
Dati Statici
I dati statici, come dice il nome, sono dati che non vengono influenzati da parte delle interazioni con l'utente e vengono scritti nella risposta HTTP esattamente come appaiono nel file di input. Quindi una pagina JSP valida potrebbe essere anche una pagina HTML senza contenuti dinamici. Tuttavia in qusto caso, gli stessi dati sarebbero mandati in risposta ogni volta dal web server. Ovviamente lo scopo di JSP non è questo ma mandare dei contenuti dinamici che vengono integrati nel contenuto statico.
Direttive JSP
Le direttive JSP controllano il modo in cui il compilatore genera il codice della corrispondente servlet. Sono disponibili le seguenti direttive:
- include - questa direttiva informa il compilatore JSP di includere un altro file in quello corrente. È un'operazione equivalente a quella di copiare e incolare il contenuto del file in quello corrente. Questa funzionalità è simile a quella fornita dal preprocessore del C/C++.
<%@ include file="filedaincludere.ext" %>
- page - Esistono diverse opzioni alla direttiva page:
- import permette di definire l' import di una classe pre-esistente o di un package
- contentType specifica il contenuto che viene generato. Deve essere usato se non viene restituito codice HTML o se il set di codifica non è quello standard.
- errorPage specifica la pagina che deve essere visualizzata se viene sollevata un'eccezione durante il soddisfacimento della richiesta HTTP.
- isErrorPage se settata a true, indica che quella corrente è una pagina di errore.
- isThreadSafe indica se la servlet è thread safe.
<%@ page import="java.util.* %> //importa tutte le classi del package java.util <%@ page contentType="text/html" %> //imposta il contenuto a text/html <%@ page isErrorPage=false %> //specifica che non è una pagina di errore <%@ page isThreadSafe=true %> //dice che la pagina è thread safe
Nota: solo la dierettiva "import" può essere usata più volte nella stessa pagina JSP.
- taglib -- La direttiva taglb indica deve essere usata una libreria di tag. La direttiva impone di specificare un prefisso (molto simile ai namespace in C++) e l'URI della descrizione della tag library.
<%@ taglib prefix="myprefix" uri="taglib/miataglib.tld" %>
Elementi di scripting e variablili nelle pagine JSP
Variabili implicite
Le seguenti variabili sono sempre disponibili in una pagina JSP:
- out - Il JSPWriter usato per scrivere i dati nello stream di risposta.
- page - La servlet stessa.
- pageContext - un'istanza PageContext che contiene dati associati all'intera pagina. Una data pagina HTML può essere trasferita fra diverse pagine JSP.
- request - l'oggetto HTTP request.
- response - L'oggetto HTTP response.
- session - L'oggetto HTTP session che per può essere usato per memorizzare le informazioni da scambiare fra diverse pagine.
Elemementi di Scripting
Esistono tre tipi di elementi di scripting che consentono di inserire codice Java all'interno della servlet corrispondente alla pagina JSP.
- Un tag che permette che il codice sia inserito appena dentro la classe. Viene usato per definire proprietà della classe Java (allo stesso modo possono essere definiti membri statici).
<%! int serverInstanceVariable = 1; %>
- Un tag che permette di posizionare il codice Java all'interno del metodo _jspService() della corrispondente servlet come un blocco separato.
<% int localStackBasedVariable=1; %>
- Un tag che fa si che il codice venga espanso inline e scritto direttamente sulla HTTP response, In questo caso non è necessario l'uso del punto e virgola in quanto il codice viene valutato come espressione.
<%= "expanded inline data "+1 %>
Azioni JSP
Le JSP actions sono tag XML che invocano funzionalità integrate nel web server. Vengono fornite le seguenti azioni:
- jsp:include
- Simile ad una funzione, la servlet temporaneamente gestisce la richiesta e la risposta fuori dalla specifica pagina JSP. Il controllo ritornerà alla pagina corrente una volta che l'altra JSP ha finito. Con questa tecnica il codice può essere riutilizzato con maggiore semplicità.
- jsp:param
- Viene impiegato all'interno dei tag jsp:include, jsp:forward e jsp:params. Specifica un paramentro che verrà aggiunto a quelli correnti contenuti nella request.
- jsp:forward
- Viene usato per demandare ad un'altra pagina jsp la gestione della request e della response. In questo caso il controllo non ritornerà mai a quella corrente.
- jsp:plugin
- Le vecchie versioni di Internet Explorer e Netscape Navigator usavano tag differenti per integrare un applet. Questa action genera i tag necessari per il browser che legge la pagina per includere una applet.
- jsp:fallback
- contiene il messaggio da visualizzare se il browser non supporta le applet.
- jsp:getProperty
- ottiene il valore di una proprietà dal java bean specificato.
- jsp:setProperty
- imposta una proprietà nel java bean specificato.
- jsp:useBean
- Crea o riusa un java bean rendendolo disponibile nella pagina JSP.
Esempi di tag
jsp:include
<jsp:include page="mycommon.jsp" > <jsp:param name="extraparam" value="myvalue"/> </jsp:include>
Nell'esempio precedente, la generazione dell'output è gestito da un file comune, mycommon.jsp. Inoltre viene impostato un ulteriore parametro, extraparam con valore myvalue, nella richiesta prima di passare il controllo a mycommon.jsp. Una volta che mycommon ha scritto tutto il suop output sullo stream di uscita, il controllo ritorna alla pagina JSP corrente.
jsp:forward
<jsp:forward page="subpage.jsp" > <jsp:param name="forwardedFrom" value="this.jsp" /> </jsp:forward>
In questo esempio, il controllo è demandato completamente ad un'altra pagina JSP, chiamata supbpage.jsp. Come nell'esempio precedente, viene impostato un un parametro extra, forwardedFrom con valore this.jsp, nella richiesta prima dell'inoltro. Il controllo non ritornerà mai alla pagina corrente.
jsp:plugin
<jsp:plugin type=applet height="100%" width="100%" archive="myjarfile.jar,myotherjar.jar" codebase="/applets" code="com.foo.MyApplet" > <jsp:params> <jsp:param name="enableDebug" value="true" /> </jsp:params> <jsp:fallback> Your browser does not support applets. </jsp:fallback> </jsp:plugin>
L'esempio illustra come gestire in modo uniforme l'inserimento di una applet in una pagina web. Prima dell'avvento del tag <OBJECT>, non esisteva un metodo univoco per integrare le applet. Questo tag è abbastanza scarno e si spera che in futuro verrà integrato in modo da supportare attributi dinamici. Allo stato attuale, il tag non supporta chiamate dinamiche alla applet; per esempio, se si ha una applet che disegna un grafico che richiede che i punti siano passati come parametri, non si può usare il tag jsp:params a meno che i punti non siano costanti. Non è possibile quindi, iterare su un ResultSet per creare i tag jsp:param. Bisogna quindi gestire a mano ogni tag jsp:param; ognuno di questi tag comunque può avere un nome dinamico e un contenuto dinamico.
jsp:useBean
<jsp:useBean id="myBean" class="com.foo.MyBean" scope="request" /> <jsp:getProperty name="myBean" property="lastChanged" /> <jsp:setProperty name="myBean" property="lastChanged" value="<%= new Date()%>" />
Nell'esempio viene creato o reso accessibile un oggetto con nome myBean che appartiene alla classe MyBean del package com.foo e che sarà accessibile per tutta la durata della request. Questo significa che l'oggetto sarà accessibile e valido in tutte le pagine che vnegono richiamate tramite i tag <jsp:include> e <jsp:forward> dalla pagina che per prima ha ricevuto la richiesta. L'attributo scope può avere i seguenti valori:
- request - l'attributo sarà avlido in tutte per tutta la durata della request. Quando la request sarà stata processata da tutte le pagine JSP, l'oggetto sarà deverenziato.
- page - l'attributo sarà disponibile solo per la pagina corrente.
- session - l'attributo è disponibile per tutta la durata della sessione dell'utente.
- application - l'attributo è disponibile per ogni istanza e non viene mai deferenziato. È lo stesso di definire una variabile statica o globale.
Librerie di tag JSP
Oltre alle azioni predefinite, gli sviluppatori possono aggiungere action sviluppate da loro usando le API per l'estensioni dei tag JSP. Gli sviluppatori scrivo una classe JAva che implementa una delle interfacce Tag e forniscono una descrizione XML della libreria in cui si specificano i tag e le classi java che li implementano.
Consideriamo il seguente codice:
<%@ taglib uri="mytaglib.tld" prefix="myprefix" %> ... <myprefix:myaction> <%-- il tag di apertura %> ... </myprefix:myaction> <%-- il tag di chiusura %> ...
Il compilatore JSP caricherà il file mytaglib.tld e vedrà che il tag 'myaction' è implementato dalla classe 'MyActionTag'. La prioma volta che iltag viene usato nel file, verrà creata un'istanza di 'MyActionTag'. Quindi (e ogni volta che il tag viene usato), verrà invocato il metodo 'doStartTag()' quando viene incontrato il tag di apertura. Viene esamianto il risultato del tag di apertura e si determina come processare il contenuto del tag. Il contenutp è il testo compreso fra il tag di apertura e quello di chiusura. Il metodo doStrtTag() può restituire uno dei seguenti valori:
- SKIP_BODY - il contenuto del tag non verrà esaminato.
- EVAL_BODY_INCLUDE - processa il contenuto del tag.
- EVAL_BODY_TAG - processa il contenuto del TAG e invia ilrisultato nello stream di uscita.
NOTA: se il tag estende la classe BodyTagSupport verrà invocato quando il corpo èstato processato appena prima di invocare il metodo doEndTag. Questo metodo è implementato per implementatre costrutti di loop.
Quando viene incontrato il tag di chiusura, viene invocato il metodo doEndTag. Questo metodo può restituire uno dei seguenti valori.
- EVAL_PAGE - indica che il resto della pagina JSP deve essere processato.
- SKIP_PAGE - indica che non ci devono essere ulteriori elaborazioni. Il controllo lascia la pagina JSP. Viene impiegato per le azioni di forward.
Il tag MyAction su descritto potrebbe avere una implementazione simile a questa:
public class MyActionTag extends TagSupport { //Releases all instance variables. public void release() {...}
public MyActionTag() { ... }
//called for the start tag public int doStartTag() { ... }
//called at the end tag public int doEndTag() throws JspTagException { ... } }
Internazionalizzazione
L'internzionalizzazione delle pagine JSP viene ottenuata nello stesso modo utilizzato nelle normali applicazioni Java, ovvero usanod i resource bundles.
JSP 2.0
La nuova versione della specifca JSP include nuove funzionalità tese ad incrementare la produttività dello sviluppatore. In dettaglio
- Un Expression Language (EL) che permette agli sviluppatori di creare templates di stile (come quelli di Velocity (tra le altre cose).
- Un metodo più semplice e veloce di creare nuovi tag.
Paradigma MVC
Sun raccomanda di utilizzare il pattern Model View Controller con le pagine JSP in modo da dividere il livello di presentazione da quello dell'elaborazione della request e dalla memorizzazione dei dati. Le normali servlet o delle pagine JSP dedicate vengono utilizzate per processare i dati. Dopo che l'eleborazione è terminata, il controllo passa ad una pagina JSP che serve solo a visualizzare l'output. Quest'ultima pagina JSP dovrebbe contenere solo HTML, XML e action e tag JSP; la pagina dovrebbe far uso dei Java beans per ottenre i dati.