scarica - Appunti Corso Java

Transcript

scarica - Appunti Corso Java
SERVLET & JSP
DISPENSE
PROGRAMMAZIONE LATO SERVER
Un server deve rispondere alle richieste del client e permettere di visualizzare le pagine
Web. Questo compito è svolto da un software ben definito, il Web server. Quando si invia
ad un Web server la richiesta di una pagina statica (ad esempio index.html) questo:
• Riconosce la richiesta.
• Cerca e, se presente, trova la pagina nel computer server.
• Invia la pagina al browser client che la visualizzerà.
Il Web server, quindi, non ha una logica di controllo; non è in grado di garantire alcuna
interattività con il visitatore tranne quella di fornire pagine web da visualizzare.
Ma se volessimo interagire con l’utente, rispondere dinamicamente, memorizzare dati
in database, eseguire quindi genericamente algoritmi un Web server propriamente detto
non è più sufficiente. Avremo bisogno di inserire della logica dietro alle semplici pagine
HTML, degli algoritmi che ci permettano, ad esempio, di effettuare dei calcoli o tenere a
memoria dei valori. Questo è permesso dagli Application server su cui possiamo creare
delle Web Application
Visualizzando semplicemente la pagina di un sito non è semplice distinguere apriori delle
pagine generate da un server “statico” da quelle generate da una Web application.
Questo perchè in entrambi casi ci troviamo difronte pagine html. La differenza sta
nell’origine di quelle pagine.
Nel primo caso le pagine sono file statici (file .html) che vengono semplicemente prelevati
dal server e visualizzati nel browser. Nel caso di Web application, invece, le pagine
vengono costruite dinamicamente al tempo della chiamata da un programma che gira sul
server e che può essere scritto in qualsiasi linguaggio.
Nel caso quindi di Web Application, quando si richiedere una pagina (è riduttivo ora
parlare di pagine), viene eseguito prima l'algoritmo che c'è dietro, poi visualizzato il
risultato.
In genere un'applicazione web si sviluppa su tre livelli:
1. Livello di presentazione: rappresenta l’interfaccia utente dell’applicazione e si
occupa di acquisire dati e visualizzare risultati.
2. Livello intermedio: si occupa delle elaborazioni dei dati; di eseguire la parte
algoritmica e generare i risultati poi visualizzati dal precedente livello.
3. Livello dati: memorizzazione e gestione dei dati, come per esempio un database.
Per l'esecuzione di questi programmi quindi non serve un semplice Web Server ma è
necessario il supporto di un Application Server. Questo, a differenza del Web server, non
si limita a rispondere alla richiesta dell’utente con la pagina HTML ma è capace di
eseguire degli algoritmi per fare calcoli, ricerche, memorizzare, ecc.
Grazie ad esso possiamo:
•
affiancare alle normali pagine HTML statiche delle pagine dinamiche che
cambieranno il loro aspetto ed il loro contenuto in base a dei parametri che saremo
noi a decidere.
•
inserire lato server dei veri e propri algoritmi che ricevano dalle pagine Web delle
informazioni, effettuino le opportune elaborazioni e restituiscano i risultati ad altre
pagine Web per la visualizzazione.
In base al linguaggio con cui si vuole programmare e creare i programmi lato server,
bisogna scegliere un opportuno Application Server che lo supporti.
Nel caso di Java l'Application Server più diffuso è Tomcat, che è open source ed è usato
per quasi il 70% dei server della rete mondiale .
Ci sono poi altri Application Server rivolti ad una nicchia di clienti di fascia alta, grosse
aziende o grandi organizzazioni:
•
JBoss, un altro AS open source
•
WebSphere, l’AS di casa IBM che vanta innumerevoli estensioni.
•
WebLogic, la proposta di BEA, una software house americana specializzata in
soluzioni enterprise.
•
Oracle, la piattaforma per la gestione di enormi quantitativi di dati che include
anche un ottimo Application server.
Ritornando a Tomcat, volendo esser pignoli, è un Servlet Container ed un JSP Engine.
Un motore quindi in grado di eseguire lato server applicazioni Web basate sulla tecnologia
J2EE e costituite da componenti Servlet e da pagine JSP.
In genere Tomcat è utilizzato insieme al Web server Apache: la sezione statica è gestire
con Apache, quella dinamica con Tomcat.
Nello sviluppo di applicazioni Web molto semplici è inutile utilizzare entrambi gli strumenti,
visto che Tomcat si comporta benissimo anche da Web server.
LE SERVLET
Una Servlet è emplicemente, un programma scritto in Java e residente su un server, in
grado di gestire le richieste generate da uno o più client, attraverso uno scambio di
messaggi tra il server ed i client stessi che hanno effettuato la richiesta.
Girano all'interno di un Application Server e possono essere considerate delle classi
(quindi dei programmi) che estendono le funzionalità del server.
Quindi le Servlet sono classi Java e possono avvalersi interamente di tutte le librerie Java
viste; bisogna però sottolineare il fatto che le Servlet, a differenza degli Applet, non hanno
delle GUI (interfacce grafiche) associate direttamente ad esse. Pertanto, le librerie AWT e
Swing non verranno mai utilizzate direttamente quando si desidera implementare una
Servlet.
Il flusso di una Servlet
Vediamo come lavora una Servlet:
1. Un client invia una richiesta (request) per una servlet ad un web application server.
2. Qualora si tratti della prima richiesta, il server istanzia e carica la servlet in
questione avviando un thread che gestisca la comunicazione con la servlet stessa.
Nel caso, invece, in cui la Servlet sia già stata caricata in precedenza (il che,
normalmente, presuppone che un altro client abbia effettuato una richiesta
antecedente quella attuale) allora verrà, più semplicemente, creato un ulteriore
thread che sarà associato al nuovo client, senza la necessità di ricaricare ancora la
Servlet.
3. Il server invia alla servlet la richiesta pervenutagli dal client
4. La servlet costruisce ed imposta la risposta (response) e la inoltra al server
5. Il server invia la risposta al client.
Il contenuto della risposta non è necessariamente calcolato da un unico algoritmo
contenuto tutto all’interno della Servlet invocata (questo può essere, semmai, il caso di
applicazioni molto elementari) ma, anzi, è spesso legato ad interazioni della Servlet stessa
con altre sorgenti di dati (data source) rappresentate, ad esempio, da Data Base, file di
risorsa e, non di rado, altre Servlet.
La Classe HttpServlet
Tutte le servlet devono implementare l'interfaccia Servlet, i cui metodi sono invocati
automaticamente dall'Application Server.
public interface Servlet {
public void init(ServletConfig config)
throws ServletException;
public ServletConfig getServletConfig();
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
public String getServletInfo();
public void destroy();
}
In particolare le Servlet che tratteremo dovranno estendere la classe astratta HttpServlet
(del package javax.servlet.http) che implementa appunto questa interfaccia.
Vediamo i metodi dell'interfaccia a cosa si riferiscono:
1. void init( ServletConfig config ): inizializza la servlet una volta sola durante il ciclo
di esecuzione della servlet;
2. ServletConfig getServletConfig( ): ritorna un oggetto che implementa l'interfaccia
ServletConfig e fornisce l'accesso alle informazioni sulla configurazione della
servlet, tra cui i parametri di inizializzazione e il ServletContext, ovvero il suo
ambiente (il servlet engine in cui vengono eseguite);
3. String getServletInfo( ): viene definito in modo da restituire una stringa con
informazioni quali autore e versione;
4. void service(ServletRequest request, ServletResponse response): viene
mandato in esecuzione in risposta alla richiesta mandata da un client alla servlet;
5. void destroy( ): invocato quando la servlet viene terminata; usato per rilasciare le
risorse (connessioni a basi di dati, file aperti, etc). Non ha nulla a che fare con il
browser.
I metodi su cui porremo attenzione sono init, service, destroy.
Il metodo init viene invocato solo quando la servlet viene caricata in memoria, di solito a
seguito della prima richiesta per quella servlet. Solo dopo che il metodo è stato eseguito, il
server può soddisfare la richiesta del client invocando il metodo service, che riceve la
richiesta, la elabora e prepara la risposta per il client.
Quindi il metodo service viene richiamato ogni volta che si riceve una richiesta.
Tipicamente, per ogni nuova richiesta il servlet engine crea una nuova thread di
esecuzione in cui viene mandato in esecuzione service. Solo quando il servlet engine
termina la servlet, viene invocato il metodo destroy per rilasciare le risorse della servlet.
Quindi di fatto, il codice del programma (o ovviamente il codice da cui partire che poi
chiama altre classi), va inserito in service in quanto è il metodo che viene chiamato ogni
volta che un client contatta il server (il metodo init viene chiamato solo quando la servlet
viene avviata la prima volta, ovvero quando è contattata dal primo client).
HttpServletRequest e HttpServletResponse
Il metodo più significativo in una servlet è quindi il metodo service, che prende in ingresso:
• un oggetto ServletRequest, corrispondente ad uno stream di ingresso, da cui
leggere la richiesta del client;
• un oggetto ServletResponse, corrispondente ad uno stream di uscita, su cui
scrivere la risposta.
Nella classe HttpServlet, il metodo service() viene sovrascritto ed i parametri che utilizza
sono del tipo specifico:
• HttpServletRequest request: che rende accessibili i dati relativi alla richiesta
inoltrata dal client;
• HttpServletResponse response: in cui inserire la risposta da passare al client.
Quindi sono i parametri tramite i quali posso gestire il flusso client-server di cui parlavamo
in precedenza: ho una richiesta (request, inviata dal client verso il server) ed una
coseguente risposta (response, inviata dal server verso il client).
In particolare sugli oggetti di questo tipo abbiamo a disposizione diversi metodi per
appunto leggere informazioni sulla richiesta del client e per scrivere informazioni da
ritornare come risposta.
Metodi dell'interfaccia HttpServletRequest:
• String getParameter(String name): torna il valore del parametro name passato
nella get/post;
• Enumeration getParameterNames( ): parametri nella post;
• String[] getParameterValues(String name): se name ha valori multipli
• Cookie[] getCookies( ): memorizzati dal server nel client;
• HttpSession getSession(boolean create): se l'oggetto non esiste e create = true,
allora lo crea.
•
Metodi dell'interfaccia HttpServletResponse:
• void addCookie( Cookie cookie ): nell'header della risposta passata al client; essa
viene memorizzata a seconda dell'età massima e dell'abilitazione o meno ai cookie
disposta nel client;
• ServletOutputStream getOutputStream( ): stream basato su byte per dati binari;
• PrintWriter getWriter( ): stream basato su caratteri per dati testuali;
• void setContentType(String type): specifica il formato MIME.
In particolare ci interesseranno i metodi getParameter(String name) per ricavare gli
eventuali parametri passati dal client nella sua richiesta e getWriter() per ottenere lo
stream su cui scrivere la risposta.
Servlet Context
Un’altra importante interfaccia messa a disposizione dal Servlet engine è la
javax.servlet.ServletContext. Attraverso di essa è possibile trovare un riferimento
al contesto (context) di un’applicazione, ovvero ad una serie di informazioni a livello
globale condivise tra i vari componenti che costituiscono l’applicazione stessa.
L'HttpServlet possiede il metodo getServletContext che ritorna appunto il riferimento al
contesto della Servlet.
Tra i vari metodi a disposizione sull'oggetto context ottenuto abbiamo per esempio
getRealPath( String virtualPath) a cui posso passare come parametro un path virtuale e
che ritorna la stringa contenente il Path reale corrispondente (utilizzabile per esempio per
creare file nel contesto dell'applicazione web).
Scrivere una Servlet
Creare una Servlet vuol dire, in termini pratici, definire una classe che estende la classe
HttpServlet e fare l'override dei metodi che ci interessano.
In precedenza abbiamo detto che principalmente ci interesserà principalmente il metodo
service ( ); in realtà Java può differenziare le richieste di tipo GET e quelle di tipo POST
ed eseguire di conseguenza il metodo appropiato tra i seguenti due (metodi propri della
classe HttpServlet):
•
void doGet(HttpServletRequest req, HttpServletResponse resp)
Gestisce le richieste HTTP di tipo GET. Viene invocato da service()
•
void doPost(HttpServletRequest req, HttpServletResponse resp)
Gestisce le richieste HTTP di tipo POST. Viene invocato da service()
In particolare, se non sovrascriviamo il metodo service( ) questo, in base al tipo di richiesta
che ha avuto dal client, chiamerà automaticamente doGet o doPost passandogli la
request e la response.
Quindi sono questi i metodi che veramente dobbiamo andare a sovrascrivere ed in cui
dobbiamo definire il codice dell'algoritmo (nulla ci vieta di fare l'override di service e
scrivere lì in codice se non ci interessa la differenzazione tra Get e Post).
All'interno del mio codice potrò prendere eventuali parametri inclusi nella richiesta tramite
il metodo getParameter sull'oggetto HttpServletRequest:
. . .
//prendo il valore del parametro nome
String name = request.getParameter("nome");
. . .
Oppure scrivere una risposta inserendola nell'oggetto HttpServletResponse:
. . .
//indico che il contenuto della mia risposta sarà del codice HTML
response.setContentType("text/html;charset=UTF­8");
//scrivo il codice
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>La Mia Prima Servlet</title>"); out.println("</head>");
out.println("<body>");
out.println("<h1>La mia servlet</h1>");
out.println("</body>");
out.println("</html>");
. . .
Tale classe va compilata ed il file class posizionato all'interno della cartella della Web
Application.
Se per esempio il nome della classe è MyServlet (e quindi avrò il file MyServlet.class)
nella Web Application, posso accedere alla servlet indicando nel browser l'indirizzo del suo
path: miosito.it/myapplication/MyServlet.
Il browser ci mostrerà il contenuto dell'HttpServletResponse che abbiamo tra l'altro
indicato essere codice HTML.
Primi Esempi
Semplice Stampa:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.*;
public class NewServlet1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF­8");
PrintWriter out = response.getWriter();
try {
out.println("<html>");
out.println("<head>");
out.println("<title>La Mia Prima Servlet</title>"); out.println("</head>");
out.println("<body>");
out.println("<h1>Questa è un Servlet</h1>");
out.println("</body>");
out.println("</html>");
} finally { out.close();
}
}
}
Prendere Parametri col Get / Post
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.*;
public class NewServlet1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("nome");
response.setContentType("text/html;charset=UTF­8");
PrintWriter out = response.getWriter();
try {
out.println("<html>");
out.println("<head>");
out.println("<title>La Mia Prima Servlet</title>"); out.println("</head>");
out.println("<body>");
out.println("<h1>Nome: " + name + "</h1>");
out.println("</body>");
out.println("</html>");
} finally { out.close();
}
}
}
Pagina HTML che richiama la Servlet (con il get):
<html>
<head>
<meta http­equiv="Content­Type" content="text/html; charset=UTF­8">
<title>La mia pagina</title>
</head>
<body>
<h1>Prova 1</h1>
<form action="NewServlet1" metod="get">
Inserisci il nome: <input type="text" name="nome"><br>
<input type="submit" value="Invia">
</form>
</body>
</html>
Analizziamo il codice:
•
Creiamo una classe "NewServlet1" che estende la classe HttpServlet che
implementa a sua volta l'interfaccia Servlet
•
Non sovrascriviamo il metodo service ( ) ma i due metodi doGet e doPost
•
In particolare, non esigendo un comportamento diverso per ognuno di essi,
mettiamo le operazioni in un metodo a parte processRequest che definiamo noi e
che facciamo chiamare sia a doGet che a doPost.
•
Nel nostro codice con il metodo setContentType stabiliamo il tipo MIME della
pagina di risposta. In questo caso e' HTML
•
Il metodo getWriter è un modo per restituire dati all'utente, in particolare getWriter
ritorna un writer, cioè un outputstream con il quale sarà possibile ritornare la pagina
di risposta al client. Chiamiamo questo metodo sul parametro
HttpServletResponse che rappresenta i dati che verranno restiuiti al client.
•
Nel caso in cui prevediamo la lettura di parametri in input, utilizzaiamo
HttpServletRequest. In particolare utilizziamo il metodo getParameter( .. ) in cui
indichiamo il nome del parametro che ci interessa e di restuisce il valore che gli è
stato associato dal client.
I vantaggi delle Servlet
Efficienza. Le servlet vengono istanziate e caricate una volta soltanto, alla prima
invocazione. Tutte le successive chiamate da parte di nuovi client vengono gestite creando
dei nuovi thread che si prendono carico del processo di comunicazione (un thread per ogni
client) fino al termine delle rispettive sessioni.
Portabilità: Grazie alla tecnologia Java, le servlet possono essere facilmente
programmate e “portate” da una piattaforma ad un’altra senza particolari problemi.
Persistenza: Dopo il caricamento, una servlet rimane in memoria mantenendo intatte
determinate informazioni (come la connessione ad un data base) anche alle successive
richieste.
Gestione delle sessioni: Il protocollo HTTP è un protocollo stateless (senza stati) e,
pertanto non in grado di ricordare i dettagli delle precedenti richieste provenienti da uno
stesso client. Le servlet sono in grado di superare questa limitazione.
JSP : JAVA SERVER PAGE
Nella visione di una Web Application in cui la parte di visualizzazzione dei dati è
separata da quella di elaborazione dei dati, le pagine JSP si occupano della
visualizzazzione offrendo però strumenti per renderla dinamica.
Di fatto una pagina JSP è una pagina di testo formata da:
• un template statico, espresso in un qualsiasi formato testuale (HTML, SVG, WML,
XML, ...)
• istruzioni Java
Quando un client richiede al server una pagina JSP, il server elabora le istruzioni Java
producendo l'opportuno output; quel che alla fine il client ottiene è una pagina statica
contenente solo codice HTML (o simili).
Come per le Servlet quindi è il server che esegue il codice Java, al client non arriverà
null'altro che una pagina HTML.
Architettura di una pagina JSP
Come già detto quindi una pagina JSP (quindi con estensione .jsp) è una pagina HTML
con codice Java immerso all'interno dei tags HTML con i quali convive ed interagisce; tale
codice vene eseguito dal server ed all'utente arriva quindi una pagina interamente HTML.
Volendo andare nello specifico, al momento dell'invocazione di una pagina ".jsp" si
succederanno le fasi seguenti:
1. Chiamata di una pagina ".jsp" tramite browser.
2. Raccolta della chiamata da parte del Web server.
3. Il Web server "vede" la pagina ".jsp", la riconosce e la consegna nelle mani
dell'Engine JSP, ad esempio Tomcat.
4. La pagina ".jsp" viene processata una prima volta.
5. Il file ".jsp" viene tradotto in una classe Java e compilato in una Servlet.
6. Vengono chiamati i metodi init e service in modo che la pagina ".jsp" non debba
subire nuovamente lo stesso processo di riconoscimento, traduzione e
compilazione ad ogni nuova chiamata.
7. La richiesta effettuata attraverso la chiamata viene soddisfatta sotto forma di un
output costituito da una pagina recante solo codice HTML prodotto però
dinamicamente.
Tutto questo processo sarà però nascosto al programmatore che invece si deve limitare a
scrivere una pagina HTML con all'interno codice Java (racchiuso in determinati
identificatori)
Un primo esempio
Prima di tutto bisogna dire che i file per essere riconosciuti dal server come pagine JSP
devono essere salvati con estensione .jsp.
Iniziamo con il classico messaggio “Ciao Mondo!” da stampare a video.
<html>
<body>
<% out.println("Ciao Mondo!"); %>
</body>
</html
Come avevamo detto è una normale pagine HTML con la differenza che c'è una porzione
di codice Java immersa al suo interno.
Come si evince dall'esempio il codice Java della pagina è stato isolato tra i delimitatori
<% e %>
Ricordando quanto detto prima, sappiamo che la prima volta che si effettua la richiesta del
file, quest’ultimo viene compilato, creando una servlet, che sarà archiviata in memoria (per
servire le richieste successive); solo dopo questi passaggi viene elaborata la pagina HTML
che viene mandata al browser.
Ad ogni richiesta successiva alla prima il server controlla se sulla pagina .jsp è stata
effettuata qualche modifica, in caso negativo richiama la servlet già compilata, altrimenti si
occupa di eseguire nuovamente la compilazione e memorizzare la nuova servlet.
L'architettura delle JSP risulta quindi abbastanza semplice; però oltre ai semplici
delimitatori appena visti, è possibile utilizzare varie componenti che necessitano di essere
analizzate.
In particolare vedremo:
1. Le Dichiarazioni
2. Le Espressioni
3. Le Scriptlet
4. Le Direttive
5. Le Actions o Standard Actions
Le Dichiarazioni
La sintassi per le dichiarazioni è la seguente:
<%! dichiarazione %>
In pratica si aggiunge il punto esclamativo dopo il primo delimitatore.
Viene utilizzata questa sintassi sia per la dichiarazioni di variabili, sia per la dichiarazione
di metodi.
Questi (variabili e metodi) diventano membri della classe ottenuta dalla traduzione della
JSP; quindi saranno in comune tra tutti i client che utilizzano la servlet ricavata dalla
traduzione.
Se un client accede ad una pagina jsp che prevede l'incremento di una variabile dichiarata
in questo modo, il client che accede successivamente troverà quella variabile
incrementata.
Inoltre i metodi e le variabili dichiarate nelle dichiarazioni JSP vengono inizializzate nel
momento in cui la JSP viene inizializzata e possono essere usate da tutti gli scriptlet e le
espressioni all'interno di quella JSP.
Le Espressioni
La sintassi per le espressioni è la seguente:
<%= espressione %>
In pratica si aggiunge l'uguale dopo il primo delimitatore.
Viene valutata l'espressione e stampato l'output (in pratica l'intero codice nella pagina
HTML finale verrà sostituito dalla stringa contenente il risultato dell'espressione).
Esempi:
Consideriamo di avere un metodo somma:
<%= somma (2,3)%>
Messa all'interno di una JSP produrrà la stringa “5” nella posizione in cui è scritta; all'interno dell'HTML
definitivo vedremo quindi la stringa “5”.
In genere sono utili per utilizzare a volo il risultato di metodi (magari di oggetti di sistema):
<%= request.getRemoteHost() %>
In questo caso sfrutta l'oggetto request per richiedere il nome di Host del server.
Le Scriplet
La sintassi è la seguente:
<% codice java %>
Le Scriptlet sono frammenti di codice java che dovranno essere eseguiti.
Vanno a riscrivere in pratica le cose all'interno del metodo service; possono anche essere
convertite in nulla che io vedo direttamente ma eseguire semplicemente righe di codice
dell'algoritmo. Posso metterci in esso qualsiasi istruzione Java.
Se poi voglio stampare qualcosa (che quindi andrà inserita nella pagina HTML prodotta),
utilizzo il metodo out.println( …. ).
Esempio:
<%
java.util.Date data_di_oggi = new java.util.Date();
out.println( String.valueOf( data_di_oggi ));
%>
Le Direttive
La sintassi è la seguente:
<%@ directive {attributo="value"}* %>
Le Direttive non producono output ma mettono a disposizione definizioni, notifiche e
informazioni valide e disponibili in tutto il documento ".jsp".
Abbiamo 3 tipologie di direttive:
Direttiva page:
Specifica le impostazioni della pagina.
Attributi possibili:
• language: specifica il linguaggio da utilizzare in fase di compilazione (es:
language="Java");
• import: specifica quali package dovranno venire inclusi nella pagina, (es:
import="java.util.*");
• isThreadSafe: indica se la pagina può servire più richieste
contemporaneamente; (es: istreadSafe = "true");
• info: contiene delle informazioni riguardanti la pagina, consultabili grazie al
metodo Servlet.getServletInfo (es: info="Prima prova");
• errorPage e isErrorPage: entrambi riguardanti la gestione delle pagine di
errore;
Vi possono essere diverse occorrenze di page, ma una sola occorrenza per
attributo, eccetto l'import
Direttiva include:
Include contenuti da altre risorse (possono per esempio essere file HTML
semplici file di testo); tali contenuti verranno poi tradotti come fossero
originariamente nelle JSP.
Unico attributo:
• file: indica il file con i contenuti da caricare
Direttiva taglib:
Permette di utilizzare una libreria di tag personalizzati (custom tag libraries).
Attributi:
• uri (del file descrittore della libreria);
• tagPrefix (esclusi: jsp, jspx, java, javax, servlet, sun, sunw);
Le Actions
Un altro importante componente delle JSP è dato dalle azioni standard.
Sintassi:
<jsp:action>.
Azioni possibili:
• <jsp:include>
permette di includere risorse aggiuntive di tipo sia statico che dinamico. Il risultato è
quindi quello di visualizzare la risorsa, oltre alle informazioni già inviate al client.
Sintassi:
<jsp:include page="URLRisorsa" flush="true | false" />
Parametri:
• page: URL della risorsa fa includere (parte della stessa applicazione Web);
• flush: indica se il buffer deve essere svuotato o meno (deve sempre essere
true in JSP 1.1);
• <jsp:forward>: inoltra la richiesta a un'altra JSP, servlet o pagina statica; fa
terminare l'esecuzione della JSP corrente.
Sintassi:
<jsp:forward page="URLRisorsa"/>
• <jsp:plugin>: permette di aggiungere ad una pagina un componente plug-in, sotto
forma di un elemento HTML object o embed specifico di quel browser. Nel caso si
tratti di un applet Java, l'azione provoca lo scaricamento del plug-in Java, se non è
già installato sul client.
• <jsp:param>: permette di dichiarare ed inizializzare dei parametri all'interno della
pagina, utilizzabili in include, forward e plugin.
Sintassi:
<jsp:params>
<jsp:param name="nomeParametro" value="valore">
</jsp:params>
Dove:
– name: nome del parametro dichiarato (se il nome esiste già, il valore viene
aggiornato);
– value: valore del parametro appena dichiarato.
Tutti i valori di ogni parametro vengono ottenuti applicando il metodo
getParameterValues sull'oggetto implicito request, e ottenendo come valore di
ritorno, un array di stringhe.
Gli Oggetti Impliciti
Sono oggetti automaticamente disponibili ed utilizzabili in una servlet. Vediamo quali sono:
Request:
E' lo stesso request visto per le Servlet: incapsula le informazioni sulla richiesta del client e
le rende disponibili attraverso alcuni suoi metodi. Il metodo più utilizzato è il
getParameter(“nomeParametro”), che restituisce una stringa con il valore del parametro
specificato.
Altri metodi a disposizione sono:
– getCookies() che restituisce un array di cookies;
– getAttributeNames()
restituisce una variabile di tipo Enumeration contenente i nomi di tutti gli attributi
coinvolti nella richiesta.
– getContentLength()
restituisce un intero che corrisponde alla lunghezza in byte dei dati richiesti.
– getContentType()
restituisce il tipo MINE della richiesta, cioè il tipo di codifica dei dati.
– getInputStream()
restituisce un flusso di byte che corrisponde ai dati binari della richiesta.
Particolarmente utile per funzioni di upload di file da client a server.
– getParameter(String)
restituisce una tringa con il valore del parametro richiesto.
– getParameterNames()
restituisce una variabile di tipo Enumeration contente i nomi dei parametri della
richiesta.
– getParameterValues(String)
restituisce un array contenente tutti i valori del parametro specificato (nel caso ci
siano più parametri con lo stesso nome).
– getProtocol()
corrisponde alla variabile CGI SERVER_PROTOCOL. Rappresenta il protocollo e la
versione della richiesta.
– getremoteHost()
corrisponde alla variabile CGI REMOTE_HOST.
– getServerName()
corrisponde alla variabile CGI SERVER_NAME e restituisce l’indirizzo IP del server
– getServerPort()
corrisponde alla variabile CGI SERVER_PORT, la porta alla quale in server è in
ascolto.
– getremoteAddr()
corrisponde alla variabile CGI REMOTE_ADDR. Restituisce in pratica l’indirizzo IP
del visitatore.
– getremoteUser()
come per REMOTE_USER restituisce lo username della macchina richiedente
– getMethod()
come per la variabile CGI REQUEST_METHOD e restituisce GET o POST.
– getPathInfo()
restituisce informazioni extra sul path, corrisponde alla varibile CGI PATH_INFO
– getQueryString()
restituisce una stringa contenete l’intera querySting (tutti i caratteri dopo il punto di
domanda), come per la variabile CGI QUERY_StrING.
– request.getServletPath()
restituisce il percorso relativo della pagina jsp
Esempio:
<% String n = getParameter(“nome”); %>
Response:
E' lo stesso response visto per le Servlet: fornisce tutti gli strumenti per inviare i risultati
dell’esecuzione della pagina jsp.
Metodi a disposizione:
– setBuffersize(int)
imposta la dimensione in byte del buffer per il corpo della risposta, escuse quindi le
intestazioni.
– setContentType(“tipo”)
imposta il tipo MINE per la risposta al client.
– flushBuffer()
forza l’invio dei dati contenuti nel buffer al client.
Out:
Questo oggetto ha principalmente funzionalità di stampa di contenuti. Con il metodo
print(oggetto/variabile) è possibile stampare qualsiasi tipo di dato.
Config:
Permette di gestire tramite i suoi metodi lo startup del servlet associato alla pagina JSP, di
accedere quindi a parametri di inizializzazione e di ottenere riferimenti e informazioni sul
contesto di esecuzione del servlet stesso.
Exception:
Questo oggetto è accessibile solo dalle pagine di errore (dove la direttiva isErrorPage è
impostata a true). Contiene le informazioni relative all’eccezione sollevata in una pagina in
cui il file è stato specificato come pagina di errore. Il metodo principale è getMessage()
che restituisce una stringa con la descrizione dell’errore.
I JAVA BEANS
I Java Beans sono 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 sarà pressochè invisibile la sezione di
codice puro, sostituito da richiami ai metodi delle classi incluse.
Posso quindi scrivere una classe, compilarla ed includerla nella Web Application.
All'interno delle pagine JSP posso poi utilizzare oggetti di questa classe tramite i suoi
metodi.
Per essere utilizzati essi devono essere semplicemente "integrati" nelle JSP, dopo di chè
sarà possibile sfruttarne tutti i metodi.
Ogni classe Java può essere un JavaBean, purché soddisfi alcuni requisiti in merito ai
nomi, alla costruzione e al comportamento dei metodi. Queste convenzioni rendono
possibile avere tool che possono usare, riusare, sostituire e connettere JavaBeans.
Le convenzioni richieste sono:
• La classe deve avere un costruttore senza argomenti
• I suoi attributi devono avere setter e getter (e vari metodi standard) che rispettano le
convezioni dei nomi;
• Non dovrebbe contenere alcun metodo richiesto per la gestione degli eventi.
Utilizzo dei Java Beans:
Esistono tre azioni standard per facilitare l'integrazione dei JavaBean nelle pagine JSP:
• <jsp:useBean>
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 possibilità di
associare la classe contenuta nel JavaBean ad un oggetto utilizzabile nel resto
della pagina richiamando i metodi definiti nella classe.
Sintassi:
<jsp:useBean id="nomeBean" scope="session" class="Classe" />
Id: identità dell'istanza dell'oggetto nell'ambito specificato (sarà la variabile
contentente l'oggetto).
Scope: ambito dell'oggetto, le opzioni sono:
◦ page: gli oggetti con questo ambito sono accessibili solo all'interno della pagina
in cui sono stati creati, in pratica possono venire paragonati alle variabili locali di
un qualsiasi linguaggio di programmazione, vengono distrutte alla chiusura della
pagina e i dati saranno persi;
◦ request: gli oggetti con questo ambito sono accessibili esclusivamente nelle
pagine che elaborano la stessa richiesta di quella in cui è stato creato l'oggetto,
quest'ultimo inoltre rimane nell'ambito anche se la richiesta viene inoltrata ad
un'altra risorsa;
◦ session: gli oggetti definiti in quest'ambito sono accessibili solo alle pagine che
elaborano richieste all'interno della stessa sessione di quella in cui l'oggetto è
stato creato per poi venire rilasciati alla chiusura della sessione a cui si
riferiscono, in pratica restano visibili in tutte le pagine aperte nella stessa istanza
(finestra) del Browser, fino alla sua chiusura. Solitamente i bean istanziati in
questo modo vengono utilizzati per mantere le informazioni di un utente di un
sito;
◦ application: gli oggetti definiti in quest'ambito sono accessibili alle pagine che
elaborano richieste relative alla stessa applicazione, in pratica sono validi dalla
prima richieta di una pagina al server fino al suo shotdown.
Class: nome della classe di cui voglio instanziare l'oggetto, deve ovviamente
coincidere con il nome del file .class (senza estensione).
•
<jsp:setProperty>
Permette di impostare il valore di una delle proprietà di un bean.
Attributi:
◦ name: nome dell'istanza di bean definita in un'azione <jsp:useBean>
◦ property: rappresenta la proprietà di cui impostare il valore
◦ param: nome del parametro di richiesta il cui valore si vuole impostare
◦ value: valore assegnato alla proprietà specificata
Richiama in pratica il setter sull'attributo indicato della classe.
Esempio:
<jsp:setProperty name="nome_bean" property="prop"
param="nome_parametro" />
Permette di assegnare il valore del parametro nome_parametro alla proprietà prop del bean di nome
nome_bean.
•
<jsp:getProperty>
Prende il valore di una proprietà di una data istanza di bean e lo inserisce
nell'oggetto out implicito (in pratica lo stampa a video).
Attributi:
◦ name: nome dell'istanza di bean da cui proviene la proprietà definita da
un'azione <jsp:useBean>
◦ property: rappresenta la proprietà del bean di cui si vuole ottenere il valore
Richiama in pratica il getter sull'attributo indicato della classe.
Un Esempio di Java Bean
Un semplice esempio di bean, realizzato per contenere le informazioni di un utente
durante la sua permanenza nel sito.
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;
}
}
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.
Vediamo come utilizzarlo.
Creazione un’istanza del bean InfoUtente con ambito session:
<html>
<head><title>Utilizzo del Bean</title></head>
<body>
<jsp:useBean id="utente" scope="session" class="InfoUtente"/>
Le proprietà del bean possono essere impostate con l’azione setProperty o agendo
direttamente con i metodi creati appositamente.
<jsp:setProperty name="utente" property="nome" value="Zina& tram"/>
<%
utente.setNome("Zina& tram");
utente.setEmail("[email protected]");
%>
Lo stesso vale per la lettura delle proprietà:
<jsp:getProperty name="utente" property="nome"/>
<% out.println(utente.getNome());
out.println(utente.riassunto()); %>
Per incrementare il numero di pagine viste è sufficiente richiamare il metodo aggiornaPV()
e per ottenere il valore getPagineViste():
<% utente.aggiornaPV();
out.println(utente.getPagineViste()); %>
ARCHITETTURA DI UNA WEB APPLICATION
Abbiamo visto che nel creare una web application significa creare un programma che
lavora su un server e può soddisfare le richieste di un client.
In particolare le componenti di una web application nel nostro caso sono:
– Servlet;
– Pagine JSP (con eventuali Java Beans).
In genere le Pagine JSP rappresenteranno la parte grafica dell'applicazione, ovvero quella
che prende l'input e mostra l'output. Ciò non toglie che comunque posso avere porzioni di
algoritmi direttamente nelle pagine (soprattutto se utilizzo Java Beans) che non si riducono
ad un semplice richiamo di parametri.
In linea di principio posso applicare il seguente ragionamento: se in una pagina JSP la
quantità di codice Java supera notevolmente la quantità del codice HTML allora è molto
probabile che necessito di una Servlet a cui devo delegare le operazioni di calcolo.
Le Servlet dunque sono classi (che possono a loro volta utilizzare classi di appoggio) che
vengono richiamate per svolgere operazioni e rimandano poi il risultato e la
visualizzazione di esso ad una pagina JSP.
Per poter far ciò è possibile utilizzare due metodi:
request.getRequestDispatcher( "paginaDest.jsp" ).forward(request,response);
oppure:
response.sendRedirect("paginaDest.jsp?param="+value);
Vediamo le differenze tra Servlet redirect e servlet forward:
•
Servlet redirect ricontatta il client indicandogli il nuovo indirizzo da contattare, il
client allora richiama la pagina indicata ricontattando di nuovo il server.
•
Servle forward invece inoltra direttamente la richiesta ad un'altra servlet o pagina
JSP comprendendo anche tutti i parametri e gli attributi salvati nella request (cosa
che non accade con la forward). Inoltre il browser non si rende proprio conto del
forward in quanto l'indirizzo nella barra degli indirizzi resta invariato.