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