Laboratorio di reti II: Servlet

Transcript

Laboratorio di reti II: Servlet
Laboratorio di reti II: Servlet
Stefano Brocchi
[email protected]
16 marzo, 2009
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
1 / 34
Le Servlet
Le servlet
Una servlet è una classe Java eseguita lato server che genera il
contenuto della risposta da inviare ad un client che ha effettuato una
richiesta
Sebbene il suo utilizzo possa coprire molti altri contesti, una servlet
generalmente riceve delle richieste HTTP e risponde generando del
codice HTML rappresentante una pagina web
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
2 / 34
Le Servlet
Servlet HTTP
Sul server deve essere presente un server web supportante servlet.
Uno dei più noti è Tomcat (tomcat.apache.org/)
Quando una richiesta giungerà al server, questo cercherà la servlet ad
essa associata e questa genererà il codice HTML con cui rispondere
Per ogni connessione, il server avvia un thread che richiamerà
oppurtunamente i metodi della classe che si occupa della pagina
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
3 / 34
Le Servlet
Servlet, CGI o PHP ?
Servlet e CGI
L’approccio Java ai webserver tramite servlet offre diversi vantaggi
rispetto ai CGI
I CGI (Common Gateway Interface) sono programmi scritti in altri
linguaggi (es. in C) che vengono richiamati per generare pagine web in
risposta a richieste HTTP
La JVM resta sempre caricata ed una richiesta HTTP genera la
creazione di un nuovo thread e non di un nuovo processo
Questo permette un tempo di avvio ed una quantità di occupazione di
risorse molto minore
Essendo i vari client gestiti con diversi thread, è molto più facile
realizzare interazioni che tra processi distinti
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
4 / 34
Le Servlet
Servlet, CGI o PHP ?
Servlet e PHP
L’utilizzo di servlet ha dei vantaggi anche rispetto a PHP:
Le servlet hanno un comportamento attivo: possono essere avviati dei
thread che continuano a lavorare anche dopo che la connessione HTTP
si è chiusa
Grazie ai meccanismi di compilazione Java (strong-typing, gestione più
’rigorosa’ degli oggetti) è più facile creare codice robusto
A disposizione tutte le librerire della JDK, e qualsiasi modulo Java può
facilmente essere utilizzato dalle servlet
Come rispetto ai CGI, le servlet permettono più facile interazione tra i
vari client
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
5 / 34
Le Servlet
Servlet, CGI o PHP ?
Servlet e PHP
Rispetto a PHP l’uso di servlet ha anche degli svantaggi:
Minor supporto dei webserver: quasi tutti i servizi di hosting
interpretano il PHP, mentre è più raro trovarne che supportino le
Servlet
Maggiore complessità di linguaggio: per chi non conosce
approfonditamente i linguaggi di programmazione, probabilmente il
PHP risulta di più facile apprendimento
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
6 / 34
Le Servlet
Servlet, CGI o PHP ?
Servlet e PHP
Altri svantaggi delle servlet, che tuttavia vanno a scomparire per
applicazioni più complesse, sono i seguenti:
Più peso computazionale per le piccole applicazioni: una JVM deve
essere sempre attiva per il supporto di servlet occupando delle risorse
del server. Per applicazioni più grandi tuttavia una migliore gestione
delle risorse può compensare questo costo
Necessario più impegno da parte del programmatore per scrivere il
codice, a causa dello strong-typing. Questo viene compensato dalla
robustezza del codice (e quindi dai minori costi di manutenzione ed
estendibilità) per applicazioni più complesse
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
7 / 34
Le Servlet
Tomcat: configurazione
Applicazioni web di Tomcat
Vediamo in breve come va configurato Tomcat per far funzionare
correttamente una servlet
Similmente ad Apache, in Tomcat è presente una cartella dove di
default (webapps) vengono cercate le applicazioni web
Se l’URL richiesta non contiene un path, le richieste vengono ricercate
di default nella cartella ROOT
Ad esempio, se Tomcat è installato in C:\Tomcat per il sito
www.miosito.com, la richiesta della homepage restituirà il file
C:\Tomcat\webapps\ROOT\index.html
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
8 / 34
Le Servlet
Tomcat: configurazione
Configurazione di Tomcat: cartella WEB-INF
Per ogni cartella rappresentante un’applicazione web, Tomcat ricerca
informazioni su questa applicazione nella sottocartella WEB-INF
Per motivi di sicurezza, la cartella non viene pubblicata in rete
In questa cartella deve essere presente un file web.xml che descrive
l’applicazione nel formato XML
Per fare uso di servlet, la cartella deve inoltre contenere la
sottocartella classes contenente i file class che realizzano le servlet
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
9 / 34
Le Servlet
Tomcat: configurazione
Configurazione di Tomcat: cartella web.xml
Nel file di configurazione è necessario innanzitutto associare un nome
alla servlet, come nella seguente sintassi
<servlet>
<servlet-name>ServletName</servlet-name>
<servlet-class>ServletClass</servlet-class>
</servlet>
... e quindi associare il nome della servlet all’URL alla quale questa
deve essere associata
<servlet-mapping>
<servlet-name>ServletName</servlet-name>
<url-pattern>/servletPage.html</url-pattern>
</servlet-mapping>
In questo esempio, una richiesta al file servletPage.html verrà
servita dalla classe ServletClass.class
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
10 / 34
Le Servlet
Realizzare una servlet
La classe HttpServlet
Per realizzare una servlet HTTP, occorre estendere la classe
HttpServlet nel pacchetto javax.servlet.http
Questa classe, insieme ad altre che implementano funzionalità delle
servlet in javax.servlet.*, non sono presenti nelle JDK ma
vengono fornite solitamente con il server web
In Tomcat, si trovano sotto Tomcat home directory /lib: includere
questa cartella nel classpath
Occorrerà quindi riscrivere i metodi di HttpServlet che vengono
richiamati dal server davanti ai vari eventi
Standard output ed error delle servlet vengono rediretti da Tomcat su
opportuni file di log
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
11 / 34
Le Servlet
Realizzare una servlet
Gestione richieste HTTP
Per realizzare una servlet, implementare il metodo
doGet(HttpServletRequest request, HttpServletResponse
response)
che viene richiamato quando una richiesta GET viene fatta alla pagina
Analogamente, i metodi doPost, doPut, doTrace, doDelete e
doOptions gestiscono gli altri tipi di richiesta HTTP
L’oggetto HttpServletRequest passato rappresenta la richiesta
HTTP e può essere utilizzato per estrarne i vari campi
L’oggetto HttpServletResponse rappresenta la risposta che verrà
inviata al client ed i suoi metodi permettono di impostarne il
contenuto ed i vari header
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
12 / 34
Le Servlet
Realizzare una servlet
Metodi per la risposta HTTP
Tramite il metodo setContentType(String contentType) di
HttpServletResponse si imposta il tipo di dato che verrà restituito;
da utilizzare prima dell’invio del contenuto della pagina
Con il metodo getWriter() si ottiene il Writer sul quale si può
scrivere il contenuto della risposta HTTP
Alternativamente, si può usare il metodo getOutputStream() per
ottenere lo stream in uscita
Avere l’OutputStream è necessario quando si inviano al client dati non
testuali. Altrimenti l’utilizzo di un Writer è solitamente più comodo
Richiamare solo uno dei due metodi getWriter() e
getOutputStream(). getWriter() deve inoltre essere richiamato
dopo setContentType() per garantire una codifica corretta
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
13 / 34
Le Servlet
Realizzare una servlet
Esempio: Hello World
Vediamo quindi una semplice servlet di esempio:
public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response) {
try {
response.setContentType("text/html;" +
" charset=iso-8859-1");
PrintWriter out = response.getWriter();
out.println("<html><head><title>Hello world" +
"</title></head><body><center>");
out.println("<h1> Hello World ! </h1>");
out.println("</center></body></html>");
} catch (IOException e) { e.printStackTrace(); }
}
}
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
14 / 34
Le Servlet
Realizzare una servlet
Esempio: invio di un file
Vediamo invece un esempio dove non si ritorna codice HTML:
private String file = "file.pdf";
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException {
response.setContentType("application/pdf");
OutputStream out = response.getOutputStream();
InputStream in = new BufferedInputStream(
new FileInputStream(file));
int read = in.read();
while (read != -1) {
out.write(read);
read = in.read();
}
in.close(); }
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
15 / 34
Le Servlet
Realizzare una servlet
Invio e download di un file
Il precedente pùo essere utile in vari casi, come nei seguenti esempi
Per far puntare una stessa URL a diversi file da scaricare a seconda di
vari fattori (come l’ultima versione del documento)
Per inviare un file non pubblicato in rete ad un client autorizzato
Come in altri linguaggio, si può avviare un download lato client
specificando gli opportuni header nella risposta HTTP
response.setContentType("application/force-download");
response.setHeader("Content-disposition",
"filename= file.pdf");
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
16 / 34
Le Servlet
Realizzare una servlet
Impostare il codice di risposta
Si possono utilizzare i metodi di HttpServletResponse per
impostare il codice di risposta HTTP
I metodi che manipolano l’intestazione della risposta HTTP devono
essere richiamati prima dell’invio di qualsiasi contenuto
Il metodo setStatus(int sc) assegna un determinato valore al
codice di risposta
E’ possibile utilizzare le costanti pubbliche della classe per questi
codici, come in
response.setStatus(HttpServletResponse.SC OK);
Il metodo setError(int sc, String msg) permette di specificare
un codice ed un messaggio di errore
Infine il metodo sendRedirect(String location) richiede la
redirezione ad un’altra pagina
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
17 / 34
Le Servlet
Realizzare una servlet
Gestire l’intestazione della risposta
Per manipolare le intestazioni HTTP della richiesta, si possono usare i
metodi getHeader(String name) e getHeaderNames() di
HttpServletRequest
Analogamente, gli header della risposta possono essere impostati
tramite setHeader(String name, String value) e
addHeader(String name, String value) nella classe
HttpServletResponse
I due metodi differiscono per il caso dove un header con il nome
specificato esista già: nel caso di setHeader il vecchio valore viene
sostituito da quello nuovo mentre in addHeader i due valori vengono
concatenati
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
18 / 34
Le Servlet
Realizzare una servlet
Gestione intestazione: esempio
Un semplice esempio di manipolazione di header
String lang = request.getHeader("Accept-Language");
if (lang != null && lang.startsWith("it")) {
response.setHeader("Content-Language", "it");
out.println("Ciao Mondo !");
} else {
response.setHeader("Content-Language", "en");
out.println("Hello World !");
}
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
19 / 34
Le Servlet
Gestione parametri in ingresso
Gestione parametri in ingresso
I parametri inviati al server in GET o POST possono essere recuperati
tramite il metodo getParameter(String name) di
HttpServletRequest
Il metodo richiede in ingresso il nome del parametro desiderato e ne
restituisce il contenuto come una stringa
Nel caso il parametro con il nome richiesto non sia stato inviato, il
metodo restituisce null
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
20 / 34
Le Servlet
Sessioni HTTP
Sessioni HTTP
In Java una sessione HTTP viene rappresentata tramite un oggetto
HttpSession
Tramite le sessioni si realizza la persistenza degli oggetti tra una
richiesta HTTP e l’altra
Java tenta di gestire le sessioni tramite cookie. Se questo non è
possibile si può alternativamente passare l’ID di sessione tra i
parametri della pagina
Per questo scopo, il metodo encodeURL(String URL) di
HttpServletResponse aggiunge il parametro con l’id di sessione
all’URL passata nel caso in cui questo sia necessario
Tramite il metodo getSession() in HttpServletRequest viene
restituita la sessione corrente o ne viene creata una nuova se questa
non esiste
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
21 / 34
Le Servlet
Sessioni HTTP
Gestione valori di sessione
Vediamo i principali metodi disponibili negli oggetti HttpSession
setAttribute(String name, Object value)
Permette di inserire un oggetto nella sessione corrente, associandolo
ad un determinato nome
getAttribute(String name)
Estrae un oggetto associato ad una determinata chiave dalla sessione
getAttributeNames()
Ottiene tutte le chiavi relative alla sessione corrente
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
22 / 34
Le Servlet
Sessioni HTTP
Esempio: conteggio delle visite
Un semplice esempio che conteggia le visite di un utente alla pagina:
HttpSession ses = request.getSession();
Object o = ses.getAttribute("count");
if (o == null) {
o = new Integer(0);
}
int count = ((Integer)o).intValue() + 1;
out.println("Le tue visite: " + count + "<br><br>");
ses.setAttribute("count", new Integer(count));
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
23 / 34
Le Servlet
Sessioni HTTP
HttpSession: altri metodi
Altri metodi utili di HttpSession per la gestione della sessione
getMaxInactiveInterval(), setMaxInactiveInterval(int
time)
Per ottenere o impostare il tempo di inattività dopo il quale la
sessione scade
getId()
Restituisce l’identificativo di sessione
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
24 / 34
Le Servlet
Sessioni HTTP
HttpSession: rimozione associazioni e distruzione
Infine, i metodi per la rimozione di attributi della sessione o per la sua
distruzione
removeAttribute(String name)
Per rimuovere un attributo dalla sessione
invalidate()
Per distruggere la sessione corrente, scollegando tutti gli oggetti
associati ed invalidandola
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
25 / 34
Le Servlet
Coordinazione delle servlet
Oggetto ServletContext
Esiste inoltre in HttpSession un metodo getServletContext()
che restituisce un oggetto ServletContext rappresentante il
contesto della servlet
E’ possibile associare ed estrarre oggetti da una ServletContext
tramite i suoi metodi setAttribute(), getAttribute() e
getAttributeNames() in modo del tutto uguale a come avviene per
oggetti HttpSession
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
26 / 34
Le Servlet
Coordinazione delle servlet
Uso di ServletContext per interazione tra servlet
Un solo oggetto di tipo ServletContext viene istanziato per ogni
applicazione web. Questo oggetto può essere utilizzato quindi per
condividere facilmente dati tra più servlet
Questo non funzionerà quando un sito è servito da più server; in questo
caso è necessario utilizzare altre tecniche (es. un database)
Un semplice meccanismo di coordinazione come questo, reso possibile
dalla JVM che fa da supporto unico per tutte le servlet, è uno dei
vantaggi offerti dai server Java
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
27 / 34
Le Servlet
Coordinazione delle servlet
Esempio: conteggio delle visite globali
Un semplice esempio che conteggia le visite effettuate da tutti gli
utenti ad una determinata pagina:
HttpSession ses = request.getSession();
ServletContext sc = ses.getServletContext();
Object o = sc.getAttribute("count");
if (o == null) {
o = new Integer(0);
}
int count = ((Integer)o).intValue() + 1;
out.println("Visite globali: " + count + "<br><br>");
sc.setAttribute("count", new Integer(count));
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
28 / 34
Le Servlet
Coordinazione delle servlet
Gestione della concorrenza
Ricordarsi sempre che, anche se non esplicitamente visibile dal codice,
il server gestisce le richieste in modo concorrenziale
Nel modificare risorse condivise come una ServletContext quindi
tenere sempre in considerazione le problematiche di sincronizzazione
Particolare attenzione va utilizzata per i problemi di deadlock, in
quanto si rischia di bloccare l’accesso a delle pagine del sito
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
29 / 34
Le Servlet
Coordinazione delle servlet
Gestione della concorrenza: esempio
Nell’esempio del conteggio delle visite qualche errore di conteggio
potrebbe anche essere trascurabile, tuttavia un codice più preciso
potrebbe essere strutturato come il seguente:
ServletContext sc = ses.getServletContext();
synchronized (sc) {
Object o = sc.getAttribute("count");
...
sc.setAttribute("count", new Integer(count));
}
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
30 / 34
Le Servlet
Upload di file
Upload di file
Per quanto riguarda l’upload di file, nel pacchetto javax.servlet
non viene fornito uno strumento che gestisca automaticamente questa
operazione
Si può realizzare una servlet per l’upload ottenendo il file dallo stream
in ingresso che legge dal corpo della richiesta HTTP. L’oggetto
relativo si può ottenere tramite il metodo getInputStream()
In altri casi, questo stream è solitamente inutile perchè le richieste
HTTP generalmente non hanno corpo ma solo un’intestazione
Altrimenti, sono a disposizione in rete numerose librerie in Java che
permettono l’automatizzazione dell’upload di file
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
31 / 34
Le Servlet
Esercizio
Esercizio
Realizzare tramite servlet un sistema di personalizzazione delle pagine
web del forum
Nel box creato appositamente, permettere ad un utente di specificare
un contenuto a sua scelta formato da:
Semplice testo (utilizzabile ad esempio per dei promemoria)
Collegamenti a pagine web
Immagini esterne al sito
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
32 / 34
Le Servlet
Esercizio
Esercizio
Per realizzare queste funzionalità è necessario effettuare i seguenti
passi
Nel codice PHP, caricare diversi frammenti di HTML da inserire
all’interno del box a seconda dell’utente attuale (es. marco ->
userboxes/marco.html)
Realizzare una pagina di login al servizio di personalizzazione tramite
servlet
Dopo l’accesso, presentare all’utente un form che permetta di inserire
una serie di link, immagini o stringhe di testo
Al momento della sottomissione, creare l’apposito frammento di HTML
ed inserirlo nel percorso opportuno
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
33 / 34
Le Servlet
Esercizio
Esercizio
Come funzionalità aggiuntiva, dare la possibilità di immettere i vari
oggetti anche a più riprese e non tutti tramite un unico form
In questo caso, sarà necessario propagare i dati già inseriti dall’utente
tramite oggetti inseriti in una sessione
Inoltre sarebbe interessante che durante l’inserimento dei vari oggetti
da parte dell’utente venga visualizzata l’anteprima del box
personalizzato
Stefano Brocchi
Laboratorio di reti II: Servlet
16 marzo, 2009
34 / 34