Java Servlet Davide Taibi [email protected] 2010 Sommario Servlet Sessioni Cookies 2 Davide Taibi Servlet Moduli scritti in Java che estendono le funzionalità dei web server. Usati al posto di script CGI e risiedono sul server Cosa fanno? Consentono di generare pagine web dinamiche facili da scrivere e veloci da visualizzare Si può interagire con un DB remoto attraverso il protocollo HTTP con i soliti metodi POST e GET Vantaggio Essendo scritti in Java possono essere inseriti nella maggior parte dei web server (java è indipendente dalla piattaforma) …alcuni commenti generali… Il problema della sicurezza è superato grazie a un Securiy Manager simile quello degli applet Si presentano come un’applicazione java in esecuzione su una JVM residente su un sever di solito essa esegue delle operazioni che producono un codice HTML inviato al client Servlet Supportano richieste multiple (es. conferenze online) Aggiornano, eliminano o consultano dati contenuti in un DB tramite protocollo TCP/IP Applicazioni di E-Commerce Fare dei forward ad altri server per bilanciare i carichi di lavoro Vantaggi delle servlet Efficienza. Le servlet vengono istanziate e caricate una volta soltanto. Tutte le successive chiamate da parte di nuovi client vengono gestite creando dei nuovi thread che si prendono carico del processo di comunicazione. Portabilità: Grazie alla tecnologia Java, le servlet "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: Come è noto 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. Per utilizzare i servlet bisogna… E’ la libreria opzionale (javax sta per Standard Extension) di Java (J2EE) che permette di realizzare classi Java, caricate dinamicamente, per espandere le funzionalità di un Web server Installare le classi servlet del package javax Architettuura del package javax.servlet Servlet interface: dichiara I metodi della servlet (init, service, etc.) GenericServlet implements Servlet HttpServlet (subclass) aggiunge funzionalita’ specifiche HTTP Ciclo di vita di una servlet 1. A server loads and initializes the servlet New thread created for each client. 2. The servlet handles zero or more client requests 3. The server terminates the servlet Ciclo di vita di una servlet • Il server in risposta ad una richiesta per una servlet ne effettua il caricamento in memoria • void init (ServletConfig config) • è avviato automaticamente da server prima che la servlet possa gestire la richiesta • void service (ServletRequest request, ServletResponse response) • • • • gestisce tutte le richieste rceve le richieste le elabora e invia le risposte al client è chiamato dal server per rispondere ad una richiesta eseguito in un nuovo thread per ogni richiesta • void destroy( ) • chiamato al termine dell’esecuzione della servelt per rilasciare le risorse usate dalla servlet Classe HttpServlet • Generalmente le Servlet web-based • estendono la classe HttpServlet • usano il metodo service per distinguere tra le richieste ricevute da un client (web browser) • Le richieste (metodi) HTTP sono di tipo: • get per richiedere informazioni dal server, generalmente documenti HTML o immagini • post per inviare dati al server generalmente informazioni relative ad autenticazione o data inseriti in un form • Usa i metodi • doGet e doPost rispettivamente per rispondere alle richieste corrispondenti HttpServletRequest Interface Le chiamate a doPost e doGet per una HttpServlet ricevono un oggetto che implementa l’interfaccia HttpServletRequest. Il Web server che esegue la servlet crea un oggetto HttpServletRequest e lo passa al metodo service. HttpServletResponse Interface Il web server che esegue la servlet crea un oggetto HttpServletResponse che passa al metodo service della servlet che a sua volta lo passa a doGet o doPost Sviluppare una servlet Affinchè una servlet possa essere eseguita è necessario che il server sia attivo Web Server che supportano le servlet • • • • Apache Tomcat JBoss Jetty … Esempio n.1: costruzione di una servlet La servlet genera un documento XHTML in risposta ad una richesta di tipo get, che consente di recuperare il contenuto di una specifica URL • Generalmente il contenuto è di tipo HTML o XHTML Il documento conterrà la sola stringa • Welcome to Servlet! 1: 2: 3: 4: 5: import javax.servlet.*; import javax.servlet.http.*; import java.io; public class WelcomeServlet extends HttpServlet { 6: // gestisce le richieste "get" dai client 7: protected void doGet(HttpServletRequest request, 8: HttpServletResponse response) 9: throws ServletException, IOException 10: { 11: response.setContentType("text/html"); 12: PrintWriter out=response.getWriter(); Descrizione del contenuto della servlet Le linee 1,2,3 consentono di includere I packages javax.servlet a javax.servelet.http che contenogno le classi per gestire la richiesta get e il package java.io La classe WelcomeServlet deve estendere HttpServlet ServletException consente di gestire le eccezioni Overloading del metodo doGet Il metodo doGet riceve come parametri gli oggetti request e response rispettivamente delle classi • HttpServletRequest • HttpServletResponse setContentType: metodo di HttpServletRequest usato per specificare il tipo dei dati da inviare in risposta al client Out: oggetto della classe PrintWriter • Ottenuto mediante il metodo getWriter dell’oggetto response • Utilizzato per inviare la risposta al client 13: // invia la pagina xhtml al client 14: // avvia il documento xhtml 15: out.println("<?xml version = \"1.0\"?>"); 16: out.println("<!DOCTYPE html PUBLIC \”//W3C//DTD " + 17: "XHTML 1.0 Strict//EN\" \"http://www.w3.org"+ 18: "/TR/xhtml1/DTD/xhtml1-strict.dtd\">"); 19: 20: out.println("<html xmlns =\"http://www.w3.org/1999/xhtml\">"); Istruzioni per la creazione del documento XHTML 21: // intestazione del documento 22: out.println("<head>"); 23: out.println("<title> Prima servlet</title>"); 24: out.println("</head>"); 25: 26: // corpo del documento xhtml 27: out.println("<body>"); 28: out.println("<h1> Welcome to Servlet! </h1>"); 29: out.println("</body>"); 30: 31: // fine del documento 32: out.println("</html>"); 33: out.close(); // chiude lo stream 34: } 35: } Documento XHTML il documento contiene un form per richiamare la servlet. form action specifica la URL che richiama la servlet welcome1 form method indica che il browser invia una richiesta get al server la richiesta richiama il metodo doGet della servlet Documento XHTML <?xml version = 1.0?> <!DOCTYPE html PUBLIC "-//w3c//dtd xhtml 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <!-- Prima Servlet --> <html xmlns = "http://www.w3.org/1999/xhtml"> <head> <title> Gestione di una richesta HTTP di tipo Get </title> </head> <body> <form action = "/welcome1" method = "get"> <p><label> Click the button to invoke the servlet <input type = "submit" value = " Get HTML Document"/> </label></p> </form> </body> </html> Metodo doPost Una richiesta post è usata per inviare dati da un form HTML ad un gestore di form server side che possa elaborare i dati import import import public javax.servlet.*; javax.servlet.http.*; java.io; class WelcomeServlet extends HttpServlet { // gestisce le richieste "post" dai client protected void doPost(HtpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String firstName = request.getParameter("firstname"); response.setContentType("text/html"); PrintWriter out=response.getWriter(); // invia la pagina xhtml al client // avvia il documento xhtml out.println("<?xml version = \"1.0\"?>"); out.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD " + "XHTML 1.0 Strict//EN\" \"http://www.w3.org"+ "/TR/xhtml1/DTD/xhtml1strict.dtd\">"); out.println("<html xmlns = \"http://www.w3.org/1999/xhtml\">"); // intestazione del documento out.println("<head>"); out.println("<title> Gestione di una richesta post con invio di dati</title>"); out.println("</head>"); // corpo del documento xhtml out.println("<body>"); out.println("<h1> Hello!" + firstname + ",<br />"); out.println("Welcome to Servlet! </h1>"); out.println("</body>"); // fine del documento out.println("</html>"); out.close(); // chiude lo stream } } Documento XHTML <?xml version = 1.0?> <!doctype HTML public "-//w3c//dtd xhtml 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <!-- Terza Servlet --> <html xmlns = "http://www.w3.org/1999/xhtml"> <head> <title> Gestione di una richesta Post con invio di dati </title> </head> <body> <form action = "/welcome3" method = "post"> <p><label> Type your name and press the Submit button <br> <input type = "text" name = "firstname"/> <input type = "submit" value = "Submit"/> </label></p> </form> </body> </html> Session Tracking Servlets in Duke’s Bookstore BookStoreServlet: Forward to main page CatalogServlet: Show all books and allow selection BookDetailServlet: Show details of a book and allow selection ShowCartServlet: Show shopping cart CashierServlet: Check out Session Tracking Motivation In a Bookstore, suppose a client has selected several books. (Do this and check the page produced by CatalogServlet.) Problem 1: The client requests ShowCartServlet to show the books in his/her shopping cart. Question: How does ShowCartServlet know the selected books? How communications between servlets are facilitated? Problem 2: The client decides to leave the bookstore and visit some other pages. Question: When the client comes back and makes further requests, how do the servlets know the books that have been selected previously? How come servlets can remember things? Session Tracking Session tracking is a mechanism that servlets use to maintain state about a series of requests From the same user (that is, requests originating from the same browser) Across some period of time Solution to Problem 2: Servlets use sessions as “notebook” and hence can remember Sessions are shared among the servlets accessed by the same client. Solution to Problem 1. Servlets communicate via sessions. Session Tracking Session is associated with a request. To use session, Get session from HttpServletRequest request: HttpSession getSession(boolean create) HttpSession mySession = request.getSession(boolean create); Case 1: create==true Return the associated session if exists Otherwise, create a new session, associate it with the request, and return the session Case 2: create==false Return the associated session if exists Otherwise, return null. Note: get session before accessing response streams. Session Tracking Store/retrieve information to/from HttpSession object. public void setAttribute(String name, Object obj) public Object getAttribute(String name). Invalidate the session (optional). Manually: Session.invalidate() Automatically when no request after certain time. void setMaxInactiveInterval(int interval) o Specifies the time, in seconds, between client requests before the servlet container will invalidate this session. A negative time indicates the session should never timeout. public class HelloAgainServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) ServletException, IOException { resp.setContentType("text/html"); throws HttpSession session = req.getSession(true); // get session if exists, does not create PrintWriter out = resp.getWriter(); out.println("<HTML><BODY><h1>Count me!</h1><HR>"); name = req.getParameter("name"); if (session == null) { out.println("Welcome," + name + ", I don't believe we've met!"); session = req.getSession(true); // create session session.setAttribute("Count", new Integer(1)); } else { int n=((Integer)session.getAttribute("Count")).intValue(); out.println("You again? " + name); out.println("That makes " + (n + 1) + " visits!"); session.setAttribute("Count", new Integer(n + 1)); } out.println("</BODY></HTML>"); out.close(); } private String name = ""; } Session Tracking The program presented on the previous slide has a bug. The fix is to change HttpSession session = req.getSession(true); to HttpSession session = req.getSession(false); Some interesting observations: After you test the correct version, go back and test the original version. It works! Why? Session Tracking - Exercise Design the following servlets CatalogServlet.java ShowCartServlet.java Cookies Cookies: objects containing a little bit information Made at server Sent to client for storage Retrieved by server when client connects again (Part of HTTP, supported by Java) Cookies can be used for Session tracking. HttpSession implemented using cookies. Persistent state. E.g. name, address, email address. When user access some servlets again, no need to provide such information one more time. Cookies Details: Each cookie is a name=value pair. Servlets create cookies and send them to clients by adding fields to HTTP response headers. Client browser is expected to support 20 cookies for each Web server, 300 cookies total, and may limit cookie size to 4 KB each. Clients automatically return cookies by adding fields to HTTP request headers. cookies can be retrieved from the request headers NOTE: Cookies shared among servlets on the server accessed by the same client. Cookies Cookies are objects of class javax.servlet.http.Cookie To send a cookie, 1. Create a Cookie object 2. 3. Cookie c = new Cookie(name, value); Set attributes if necessary c.setMaxAge(30); // expire after 30 seconds Send the cookie response.addCookie(c); To get information from a cookie, 1. 2. Retrieve all the cookies from the user's request Cookie[] cookies = request.getCookies(); Find the cookie that you are interested in and get its value for (int i = 0; i < cookies.length; i++) { String name = cookies[i].getName(); String value = cookies[i].getValue(); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("Cookies received from client:<br>"); Cookie[] cookies = request.getCookies(); if(cookies !=null){ for (int i = 0; i < cookies.length; i++) { Cookie c = cookies[i]; String name = c.getName(); String value = c.getValue(); out.println(name + " = " + value + "<br>"); } } out.println("<br>Cookies sent to client:><br>"); String name = request.getParameter("cookieName"); String value = request.getParameter("cookieValue"); if (!name.isEmpty() && !value.isEmpty()) { Cookie c = new Cookie(name, value); c.setMaxAge(180); response.addCookie(c); out.println(name + " = " + value + "<br>"); }} // CookieServlet.java Cookies Cookies not shared between different clients accessing the same server. Try to Access the following from two different browsers http://localhost:8080/servlet/CookieServlet?cookieName=cookie1&cook ieValue=a1 Cookies are not shared between different servers accessed by the same client Try: http://localhost:8080/servlet/CookieServlet?cookieName=monkey&c ookieValue=a http://localhost:8080/servlet/CookieServlet?cookieName=scpu8&coo kieValue=a