Alla base degli elementi di scripting utilizzati nella pagine JSP, è noto che vi siano gli "scriptlet", i "declaration tags" e le "expressions". Rinfreschiamoci un attimo la memoria, proponendo 3 esempi in cui vengono utilizzati tali elementi:
Declaration
<%! int x = 4; %>
Scriptlet
<% while (i < 10) { out.write("i=" + i); } %>
Expression
<%= item.getCodeItem() %>
Nella versione 2.0 delle specifiche per le pagine JSP, sono state aggiunte delle istruzioni note come expression language statements (EL). Attraverso tali istruzioni è possibile arrivare, sovente, allo stesso risultato che si ottiene utilizzando gli elementi di scripting di base. La differenza è che la sintassi utilizzata dalle espressioni EL è più semplice.
Inoltre, è possibile utilizzare le EL anche nelle cosiddette scriptless pages (pagine prive di elementi di scripting). Queste ultime sono delle pagine JSP in cui non è consentito inserire nessuno degli scripting elements che abbiamo appena ripassato.
Ci si potrebbe chiedere quale possa essere la ragione per scrivere pagine JSP prive di scripting elements. Il motivo principale si basa sulla necessità (e la convenienza) di separare la parte di presentation (l'interfaccia utente, per intenderci) da quella contenente la logica di business. Nelle scriptless pages, quindi, il comportamento dinamico delle pagine JSP dovrà essere fornito dal altri elementi come i JavaBeans, le custom actions e le standard tag libraries. A tali elementi, si aggiungono, quindi, anche le espressioni EL.
Ci sono due modi per assicurarsi che una pagina non contenga elementi di scripting: attraverso una direttiva (page directive) oppure utilizzando un elemento del deployment descriptor. Naturalmente, è possibile estendere il "divieto" anche alle espressioni EL utilizzando le medesime tecniche. In generale, una direttiva che blocchi o consenta l'utilizzo di scripting elements ed espressioni EL ha il seguente formato:
<%@ page isScriptingEnabled="true|false" isELEnabled="true|false" %>
Il valore di default per l'attributo isScriptingEnabled
è true
. Normalmente, il container imposta il valore di isELEnabled
a true
a partire dalla versione 2.0 di JSP. Per la release 1.2 (o precedenti) tale valore è uguale a false
.
Se invece si vuole impostare l'utilizzo degli scripting elements e delle espressioni EL dal deployment descriptor sarà necessario utilizzare il seguente formato:
<web-app xmlns=http://java.sun.com/xml/ns/j2ee
xmlsn:xsi=http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation=http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd
version="2.4">
<welcome-file-list>
<welcome-file>TopicList.jsp</welcome-file>
</welcome-file-list>
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-enabled>true</el-enabled>
<scripting-enabled>true</scripting-enabled>
</jsp-property-group>
</jsp-config>
</web-app>
Si noti che nel caso si scelga di utilizzare il deployment descriptor per tali impostazioni, le direttive che abilitano o meno l'utilizzo degli scripting elements e delle espressioni EL varranno per tutte le pagine JSP dell'applicazione e non soltanto per una di esse (come nel caso della direttiva page che abbiamo visto).
Infine, è importante dire che l'utilizzo dell'elemento <jsp-config>
è utilizzabile soltanto in un deployment descriptor che abbia la versione di web-app impostata a 2.4 (che corrisponde alle specifiche 2.0 di JSP).
La Sintassi delle EL
La sintassi base per una espressione EL è la seguente:
${espressione}
Dove espressione
deve corrispondere ad una espressione valida, che includa, cioè, al suo interno uno o più dei seguenti elementi:: letterali (literals), operatori, variabili ed invocazioni a metodi.
I literals che possono essere utilizzati nelle espressioni EL accettano un numero limitato di valori. Essi sono:
- true, false (boolean literals)
- Qualunque stringa delimitata da apici singoli o doppi (String literals)
- Qualunque numero intero positivo o negativo (Integer literals)
- Qualunque numero decimale positivo o negativo (Float literals)
- Il valore null (Null literal)
Vediamo qualche esempio:
${true}
<%-- Restituisce: true --%>
${"I 'singoli apici' possono essere annidati direttamente dentro i doppi apici"}
<%-- Restituisce: I 'singoli apici' possono essere annidati direttamente dentro i doppi apici --%>
${2*12}
<%-- Restituisce 24 --%>
Gli operatori
La maggior parte degli operatori utilizzati in Java possono essere utilizzati all'interno delle espressioni EL. In particolare, per molti di essi, possono essere utilizzate due notazioni: quella simbolica e quella descrittiva (ad esempio, '/' e 'div' per l'operatore di divisione oppure '%' e 'mod' per l'operatore modulo) in modo da consentire alle pagine JSP di essere (quando necessario) XML compliant senza troppe difficoltà. Ad esempio per l'operatore '<' in XML, in mancanza della notazione descrittiva, si sarebbe dovuto utilizzare la notazione '<
' .
Nella tabella seguente sono riportati tutti gli operatori utilizzabili nelle espressioni EL:
Tipo | Notazione Simbolica | Notazione Descrittiva |
---|---|---|
Aritmetico | + | |
Aritmetico | - | |
Aritmetico | * | |
Aritmetico | / | div |
Aritmetico | % | mod |
Relazionale | = | eq |
Relazionale | != | ne |
Relazionale | < | lt |
Relazionale | > | gt |
Relazionale | <= | le |
Relazionale | >= | ge |
Logico | && | and |
Logico | || | or |
Logico | ! | not |
Altro | () | |
Altro | empty | |
Altro | [] | |
Altro | . |
Sugli operatori 'Aritmetici' e 'Relazionali' non c'e' molto da aggiungere rispetto all'utilizzo che se ne fa, normalmente, in Java. Si noti, ma anche questa non è una novità, che sulle espressioni EL le parentesi possono essere utilizzate per cambiare la precedenza degli operatori coinvolti. Ad esempio:
${ (3 * 5) + 4 } Restituisce 19
${ 3 * (5 + 4) } Restituisce 27
L'operatore empty
può essere utilizzato per testare vari tipi di condizioni. La sua sintassi è la seguente:
${empty name}
e restituisce true
se l'oggetto referenziato da name
vale null
oppure, nel caso di oggetti di tipo String
, contiene il valore di stringa vuota. La semantica è identica anche quando empty
viene utilizzato con oggetti di tipo List
, Vector
, Map
o array
: restituirà true
se tali oggetti non contengono elementi, altrimenti false
.
Per l'utilizzo di tale operatore è necessario che l'oggetto referenziato da name
sia relativo ad uno degli oggetti impliciti definiti per le pagine JSP (page
, request
, session
o application
). Ad esempio:
<% Vector vect = new Vector();
pageContext.setAttribute("miovector", vect); %>
${empty miovector} // Vale true perché il Vector non contiene elementi.
Gli operatori [] (parentesi quadre) e . (dot operator) sono utilizzati per accedere agli attributi di un oggetto della pagina. La parte alla sinistra di questi operatori corrisponde ad un oggetto della pagina mentre la parte a destra equivale ad una proprietà (o ad un indice).
Se, per esempio, è stato definito un bean in una pagina JSP (attraverso la standard action <jsp:useBean>
), sarà possibile accedere alle proprietà di tale bean utilizzando sia l'operatore [] che il dot operator. Ovvero, se nome e cognome sono due proprietà di un bean referenziato dalla variabile utente, sarà possibile scrivere, in modo perfettamente equivalente:
${user.nome}
${user[nome]}
${user.cognome}
${user[cognome]}
Gli oggetti impliciti per le espressioni EL
La maggior parte degli oggetti impliciti disponibili per le pagine JSP sono utilizzabili anche con le espressioni EL. Essi sono:
- pageContext: È l'oggetto di tipo
javax.servlet.jsp.PageContext
della pagina JSP e può essere utilizzato per accedere agli oggetti impliciti comerequest
,response
,session
,out
, etc. Ad esempio,${pageContext.response}
restituisce l'oggettoresponse
associato alla pagina. - pageScope: Rappresenta un oggetto di tipo
Map
che contiene gli attributi il cui contesto è quello relativo all'oggettopage
. In particolare, viene associato ad ogni nome di attributo il valore corrispondente. Ad esempio, se un certo JavaBean è utilizzato all'interno di una pagina JSP, con visibilità a livello di page, sarà possibile accedere a tale oggetto e alle sue proprietà nel seguente modo:
${pageScope.nomeOggetto}
${pageScope.nomeOggetto.nomeProprietà}
- requestScope: Un oggetto di tipo
Map
che contiene gli attributi il cui scope è l'oggettorequest
. La sintassi è identica a quella utilizzata per ilpageScope
. - sessionScope: Un oggetto di tipo
Map
che contiene gli attributi il cui scope è l'oggettosession
. Stessa sintassi anche in questo caso. - applicationScope: Un oggetto di tipo
Map
che contiene gli attributi il cui scope è l'oggettoapplication
. Stessa sintassi utilizzata dalpageScope
. - param: Un oggetto di tipo
Map
che "mappa" il nome di un parametro ricevuto attraverso la richiesta del client in un singolo valore di tipoString
. L'espressione${param.nomeParametro}
è equivalente all'invocazione del metodorequest.getParameter(nomeParametro)
. - paramValues: Simile al precedente ma in questo caso viene restituito un array di valori.
${paramValues.nomeParametro}
equivale, pertanto, all'invocazione del metodorequest.getParameterValues(nomeParametro)
. - header: Un oggetto di tipo Map che "mappa" il nome di un header ricevuto attraverso la richiesta del client in un valore di tipo String. L'espressione
${header.nomeHeader}
equivale arequest.getHeader(nomeHeader)
. - headerValues: Simile al precedente ma in questo caso viene restituito un array di valori.
${headerValues.nomeHeader}
equivale, pertanto, all'invocazione del metodorequest.getHeaderValues(nomeHeader)
. - cookie: Un oggetto di tipo
Map
che "mappa" i nomi dei cookie in un singolo oggetto di tipo Cookie. L'espressione${cookie.nomeCookie.value}
restituisce il valore del primo cookie avente il nome fornito. - initParam: Mappa il nome di un parametro di inizializzazione nel suo valore di tipo
String
. L'espressione${initParam.nomeParametro}
è equivalente ad invocareServletContext.getInitParameter(nomeParametro)
Errori ed Eccezioni
Le espressioni EL non scatenano le stesse eccezioni che ci si aspetta normalmente quando si verifica un errore a run-time in un costrutto Java. Ad esempio, consideriamo l'espressione:
${item.codice}
Che equivarrebbe, in Java, a:
item.getCodice();
Se non fosse istanziata la variabile item
, sappiamo bene che, in Java, verrebbe scatenata una eccezione di tipo NullPointerException
a run-time al tentativo di invocazione del metodo getCodice()
. Se, invece, la variabile stessa non fosse proprio definita, sarebbe il compilatore stesso a segnalare un problema durante la compilazione del codice.
Nelle espressioni EL, la maggior parte delle situazioni di errore possono essere accertate soltanto in fase di esecuzione dell'applicazione. Inoltre, al posto delle eccezioni vengono restituiti (laddove si verifichi una situazione che scatenerebbe, normalmente, un'eccezione) dei valori di default.
Ad esempio, nel caso precedente se non fosse stata istanziata la variabile item
, il valore restituito dall'espressione sarebbe null
. Esiste una lista di valori di default restituiti in caso di errore. Si consiglia, a tale scopo, di consultare le specifiche JSP 2.0.
Alla prossima.