In informatica JavaServer Pages, di solito indicato con la sigla JSP (letto anche talvolta come Java Scripting Preprocessor), è una tecnologia di programmazione web in Java per lo sviluppo della logica di presentazione (tipicamente secondo il pattern MVC) di applicazioni web, fornendo contenuti dinamici in formato HTML o XML. Si basa su un insieme di speciali tag, all'interno di una pagina HTML, con cui possono essere invocate funzioni predefinite sotto forma di codice Java (JSTL) e/o funzioni JavaScript. In aggiunta, permette di creare librerie di nuovi tag che estendono l'insieme dei tag standard (JSP Custom Tag Library). Le librerie di tag JSP si possono considerare estensioni indipendenti dalla piattaforma delle funzionalità di un server web.
Descrizione
Nel contesto della piattaforma Java, la tecnologia JSP è correlata con quella delle servlet: all'atto della prima invocazione, le pagine JSP vengono infatti tradotte automaticamente da un compilatore JSP in servlet. Una pagina JSP può quindi essere vista come una rappresentazione ad alto livello di un servlet. Per via di questa dipendenza concettuale, anche l'uso della tecnologia JSP richiede la presenza, sul server web, di un servlet container, oltre che di un server specifico JSP detto motore JSP (che include il compilatore JSP); in genere, servlet container e motore JSP sono integrati in un unico prodotto (per esempio, Tomcat svolge entrambe le funzioni).
JSP è una tecnologia alternativa rispetto a numerosi altri approcci alla generazione di pagine web dinamiche, per esempio PHP, o ASP o la più tradizionale CGI. Differisce da queste tecnologie non tanto per il tipo di contenuti dinamici che si possono produrre, quanto per l'architettura interna del software che costituisce l'applicazione web (e, di conseguenza, sui tempi di sviluppo, la portabilità, la modificabilità, le prestazioni, e altri aspetti di qualità del software).
Paradigma MVC Sun Microsystems 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 JavaBeans per ottenere i dati.
In altri termini nello sviluppo di un'applicazione web la convenzione vuole che nelle JSP ci sia meno codice Java possibile e quello presente vada a richiamare codice Java nativo (oggetti e metodi) implementato in classi separate apposite dette appunto JavaBeans. Questa separazione consente infatti un facile riuso di codice dei Java beans una volta richiamato in un qualsiasi punto richiesto dell'applicazione web.
Struttura di una pagina JSP Una JSP è un documento di testo, scritto con una sintassi specifica, che rappresenta una pagina web di contenuto parzialmente o totalmente dinamico. Elaborando la pagina JSP, il motore JSP produce dinamicamente la pagina HTML finale che verrà presentata al web browser dell'utente. La pagina JSP può contenere tre tipi di elementi, a cui corrispondono tre diversi modi di elaborazione: contenuti statici, direttive e script.
Contenuti statici I contenuti statici sono porzioni della pagina JSP che devono essere mantenute integralmente nella pagina web generata dinamicamente, senza alcuna elaborazione. Devono pertanto essere scritte nel linguaggio di tag di cui il client può usufruire direttamente, per esempio HTML (se il client è un browser), WML (se il client è un cellulare che accede alla pagina in WAP) o XML (vari tipi di client).
Direttive Le direttive JSP si possono interpretare come comandi rivolti al motore JSP. Questi comandi vengono eseguiti in una fase di preprocessing, prima che siano elaborate le porzioni della pagina contenenti script. Le due direttive principali sono include e page.
include: ordina al motore JSP di includere un altro file in quello corrente. È un'operazione equivalente a quella di copiare e incollare il contenuto del file indicato in quello corrente. (Una direttiva di questo tipo è simile a quella prevista dal preprocessore del C/C++). Questa direttiva può essere usata, per esempio, per realizzare contenuti ricorrenti in diverse pagine di un sito web.
<%@ include file="filedaincludere.ext" %>
page: esistono numerose varianti della direttiva page, con scopi piuttosto diversi fra loro: page import corrisponde all'import Java, e indica quali classi saranno utilizzate nel resto del documento; <%@ page import="java.util.*" %> //importa tutte le classi del package java.util page contentType indica in quale formato sia scritto il documento (per esempio HTML o XML) <%@ page contentType="text/html" %> page errorPage specifica la "pagina di errore" che deve essere visualizzata se l'elaborazione della pagina dinamica fallisse in seguito al verificarsi di qualche eccezione page isErrorPage indica se quella corrente è una pagina di errore <%@ page isErrorPage=false %> //specifica che non è una pagina di errore page isThreadSafe indica se il servlet generato dalla pagina JSP è thread safe page taglib indica che la pagina JSP fa uso di una libreria di tag. La libreria deve essere identificata tramite una URI (Uniform Resource Identifier) <%@ taglib prefix="myprefix" uri="taglib/miataglib.tld" %>
Scripting La terza categoria di elementi presenti in una pagina JSP sono frammenti di codice sorgente (Java). Questi frammenti di codice sono quindi eseguiti dalla Java Virtual Machine e producono in output un testo, che va a contribuire al sorgente della pagina web in via di generazione. L'invocazione di codice Java è la chiave della generazione di pagine dinamiche in JSP; per esempio, le pagine JSP di un sito di acquisti online potrebbero includere codice Java che verifica la disponibilità di un prodotto e genera in output una pagina che riporta questa informazione.
Dichiarazioni La pagina JSP può includere dichiarazioni di attributi e metodi, introdotte dalla sequenza <%!. Tali attributi e metodi andranno a far parte della classe "servlet" generata dal compilatore JSP (la loro posizione all'interno del testo della pagina JSP è irrilevante). Lo sviluppatore che ha familiarità con la tecnologia servlet può sfruttare questa possibilità, per esempio, per fare overriding dei "metodi di life-cycle" dei servlet, come jspInit. <%! int serverInstanceVariable = 1; %>
Espressioni Le espressioni sono introdotte dalla sequenza <%=, e contengono una qualsiasi espressione Java. Durante l'elaborazione della pagina JSP, l'espressione viene valutata dal motore JSP, il risultato viene convertito in stringa, e la stringa inserita nel codice HTML/XML nel punto corrispondente a quello dove compare l'espressione stessa. <body> Sei l'utente registrato nr. <%= registroUtenti.conta() %> <code></body></code>
Scriptlet Gli scriptlet sono frammenti di codice immersi in un qualunque punto del testo. Concettualmente, si può immaginare che durante la costruzione della pagina web dinamica, il motore JSP includa senza elaborazioni i contenuti statici, procedendo dall'alto verso il basso nel documento, ed esegua immediatamente eventuali scriptlet incontrati durante l'operazione. Tecnicamente, questi scriptlet vengono inclusi nei metodi del servlet generato dalla pagina JSP, all'interno dei metodi che producono la risposta a una richiesta HTTP.
Variabili implicite Gli elementi di codice in una pagina JSP possono fare riferimento a un insieme di variabili predefinite: out: rappresenta il flusso di output su cui viene prodotta la pagina web. Si tratta di un oggetto di classe JSPWriter. Il suo uso è spesso implicito (per esempio nelle espressioni), ma all'occorrenza si può fare riferimento a questa variabile page: rappresenta il servlet generato dalla pagina JSP pageContext: un oggetto di classe PageContext, che contiene dati associati all'intera pagina. L'oggetto può essere trasferito da una pagina JSP a un'altra request: l'oggetto di classe HttpServletRequest che rappresenta la richiesta HTTP che ha portato all'attivazione della pagina JSP/servlet response: l'oggetto di classe HttpServletResponse che rappresenta la risposta HTTP da inviare session: l'oggetto di classe HttpSession che rappresenta la sessione HTTP all'interno della quale è stata invocata la pagina JSP application: permette di accedere e di memorizzare gli oggetti per renderli accessibili da qualsiasi utente e modificabili da ogni pagina config: viene spesso lasciato inutilizzato, visto che le informazioni messe a disposizione da questo oggetto implicito sono generalmente settate e rilevate in automatico.
Azioni JSP Le azioni JSP sono tag XML che consentono di controllare alcuni aspetti del comportamento del server web. Alcuni esempi sono i seguenti: jsp:include: cede il controllo a un'altra pagina JSP, con ritorno del controllo a elaborazione terminata; simile a una chiamata di procedura jsp:forward: cede il controllo, definitivamente, a un'altra pagina JSP jsp:param: introduce un parametro aggiuntivo nel contesto di azioni come include e forward.
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 scrivono 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 prima volta che il tag 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 esaminato il risultato del tag di apertura e si determina come processare il contenuto del tag. Il contenuto è il testo compreso fra il tag di apertura e quello di chiusura. Il metodo doStartTag() 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 il risultato 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 viene usato per implementare 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'internazionalizzazione delle pagine JSP viene ottenuta mediante la stessa tecnica utilizzata nelle normali applicazioni Java, ovvero usando i resource bundles.
Esempi
Il seguente frammento suggerisce come si potrebbe creare un'intestazione a diverse pagine web, facendo in modo che la presentazione possa variare in qualche dettaglio (per esempio, rendendo non cliccabile il link alla pagina corrente):