Basic Internet Programming 2004 Servlets, Cookies and Sessions Björn Eiderbäck [email protected] Cristian Bogdan [email protected] Introduktion Pragmatisk exempelorienterad beskrivning Länkar på nätet Basic Internet Programming Servlets Varför bygga sidor dynamiskt? Websidorna baseras på data från användarna Websidorna konstrueras från data som ändras ofta Websidorna använder information från databaser, andra program på nätet eller via andra serverresurser 1 Basic Internet Programming Servlets Vad är servlets? Servlets är program körs på serversidan Motsvarar ungefär CGI-bin, dvs program som kör på servern skrivna i diverse olika språk En servlet Läser data från klienter Genererar svar Skickar data tillbaks till klienter Kommunicerar med filer, databaser och andra program Basic Internet Programming Servlets Hur kör jag servlets? En servlet körs i en Container av typ Tomcat En servlet anropas från en webläsare eller från en form i en html/xhtml-sida 2 Basic Internet Programming Servlets Fördelar med servlets jämfört med cgi-bin Effektivt Trådar istället för OS-processer Bekvämt Massor med högnivåfaciliteter Kraftfullt Dela data, poolning, persistens Portabelt Kan köras på massor av plattformar och servrar Säkert Körs i ”sandlåda”, ingen overflow Ej dyrt Basic Internet Programming Servlets En servlets struktur import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class ServletTemplate extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Use "request" to read incoming HTTP headers // (e.g., cookies) and query data from HTML forms. // Use "response" to specify the HTTP response status // code and headers (e.g. the content type, cookies). PrintWriter out = response.getWriter(); // Use "out" to send content to browser } } 3 Basic Internet Programming Servlets En enkel servlet som genererar text import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloWorld extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* servlet container takes care of writing initial http header lines. Still, we can change headers: */ response.setContentType("text/plain"); /* now the content: */ PrintWriter out = response.getWriter(); out.println("Hello World"); } } Basic Internet Programming Servlets Kompilera Lägg in följande i CLASSPATH %CATALINA_HOME%\common\lib\servlet.jar z Servletklasserna ligger i servlet.jar, så dom måste med Kompilera med javac javac MinServlet.java Alternativt om inte CLASSPATH är satt kan man göra något i stil med javac –classpath ".;%CATALINA_HOME%\common\lib\servlet.jar" MinServlet.java Sök i aktuell katalog Använd klasser i servlet.jar placerad i Tomcats lib 4 Basic Internet Programming Servlets Managing tomcat via ant Sets the classpath and other tomcat environment for you Works on all Windows and Unix/Mac OS X platforms ~> mkdir test; cd test ~/test> (set the path to ant) ~/test> cp -r /info/intnet03/localTomcat/ . ~/test> cd localTomcat/ localTomcat> ant install localTomcat> ant compile localTomcat> ant tomcat localTomcat> ant stopTomcat Basic Internet Programming Servlets Standard Web Application (webapp) Directories Under webapps/ everything is tomcat-independent! webapps/ ROOT/ examples/ WEB-INF/… (servlet contexts) http://host:port/ http://host:port/examples (not visible by http) http://host:port/labbar http://host:port/labbar/test.html (not visible by http) labbar/ test.html, test.jsp foo/bar.html WEB-INF/ web.xml someJSPTagLibrary.tld classes/ HelloWoldServlet.java HelloWorldServlet.class somepackage/AClassInThePackage lib/ someLibrary.jar 5 Basic Internet Programming Servlets En servlet som genererar HTML import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloWWW extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); String docType = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " + "Transitional//EN\">\n"; out.println(docType + "<HTML>\n" + "<HEAD><TITLE>Hello WWW</TITLE></HEAD>\n" + "<BODY>\n" + "<H1>Hello WWW</H1>\n" + "</BODY></HTML>");}} Basic Internet Programming Servlets En användbar klass för att skapa HTML-header public class ServletUtilities { public static final String DOCTYPE = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " + "Transitional//EN\">"; public static String headWithTitle(String title) { return(DOCTYPE + "\n" + "<HTML>\n" + "<HEAD><TITLE>" + title + "</TITLE></HEAD>\n"); } //Resten av klassen behövs inte nu, så den utelämnar vi 6 Basic Internet Programming Servlets En klass som använder föregående klass import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class SimplerHelloWWW extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println(ServletUtilities.headWithTitle("Hello WWW") + "<BODY>\n" + "<H1>Hello WWW</H1>\n" + "</BODY></HTML>"); } } Basic Internet Programming Servlets Lifscykel Lifscykel init anropas då servleten skapas public void init() throws ServletException { //Initiera servleten, tex genom att läsa in data från databas } service Varje gång en server får en fråga skapas en ny tråd och anropar service doGet, doPost och doXxx Dessa metoder är dom man normalt själv skriver för att beskriva vad servleten ska göra vid respektive anrop Vi tittar i Suns tutorial som beskriver detta http://java.sun.com/docs/books/tutorial/servlets/index.html 7 Basic Internet Programming Servlets Initieringsparametrar, Initieringsparametrar, servlet servlet public class ShowMessage extends HttpServlet { private String message; private String defaultMessage = "No message."; private int repeats = 1; public void init() throws ServletException { ServletConfig config = getServletConfig(); message = config.getInitParameter("message"); if (message == null) { message = defaultMessage; } Basic Internet Programming Servlets ... try { String repeatString = config.getInitParameter("repeats"); repeats = Integer.parseInt(repeatString); } catch(NumberFormatException nfe) { /* NumberFormatException handles case where repeatString is null *and* case where it is in an illegal format. */ } } 8 Basic Internet Programming Servlets ... public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); String title = "The ShowMessage Servlet"; out.println(ServletUtilities.headWithTitle(title) + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1 ALIGN=\"CENTER\">" + title + "</H1>"); for(int i=0; i<repeats; i++) { out.println("<B>" + message + "</B><BR>"); } out.println("</BODY></HTML>"); } } Basic Internet Programming Servlets ... Initieringsparametrar, web.xml <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd"> <web-app> <servlet> <servlet-name>ShowMsg</servlet-name> <servlet-class>ShowMessage</servlet-class> <init-param> <param-name>message</param-name> <param-value>Shibboleth</param-value> </init-param> 9 Basic Internet Programming Servlets ... <init-param> <param-name>repeats</param-name> <param-value>5</param-value> </init-param> </servlet> </web-app> Basic Internet Programming Servlets Anropa servlet med parametrar, htmldel <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <!-Front end to ThreeParams servlet. Taken from Core Web Programming Java 2 Edition from Prentice Hall and Sun Microsystems Press, http://www.corewebprogramming.com/. May be freely used or adapted. --> <HTML> <HEAD> <TITLE>Collecting Three Parameters</TITLE> </HEAD> <BODY BGCOLOR="#FDF5E6"> <H1 ALIGN="CENTER">Collecting Three Parameters</H1> 10 Basic Internet Programming Servlets ... <FORM ACTION="/servlet/ThreeParams"> First Parameter: <INPUT TYPE="TEXT" NAME="param1"><BR> Second Parameter: <INPUT TYPE="TEXT” NAME="param2"><BR> Third Parameter: <INPUT TYPE="TEXT" NAME="param3"><BR> <CENTER><INPUT TYPE="SUBMIT"></CENTER> </FORM> </BODY> </HTML> Basic Internet Programming Servlets Anropa Anropa servlet servlet med med parametrar, parametrar, servletdel servletdel import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class ThreeParams extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); String title = "Reading Three Request Parameters"; 11 Basic Internet Programming Servlets ... out.println(ServletUtilities.headWithTitle(title) + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1 ALIGN=\"CENTER\">" + title + "</H1>\n" + "<UL>\n" + " <LI><B>param1</B>: " + request.getParameter("param1") + "\n" + " <LI><B>param2</B>: " + request.getParameter("param2") + "\n" + " <LI><B>param3</B>: " + request.getParameter("param3") + "\n" + "</UL>\n" + "</BODY></HTML>"); } } Basic Internet Programming Servlets Request Request headers headers Med servleten kommer massa information via HTTP-protokollet. Vi kan läsa av hur servleten anropades (GET eller POST), vilken URI som angavs, vilka browser klienten har, vilken dator som klienten befinner sig på och en del annat 12 Basic Internet Programming Servlets ... exempel public class ShowRequestHeaders extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); String title = "Servlet Example: Showing Request Headers"; Basic Internet Programming Servlets ... out.println(ServletUtilities.headWithTitle(title) + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1 ALIGN=\"CENTER\">" + title + "</H1>\n" + "<B>Request Method: </B>" + request.getMethod() + "<BR>\n" + "<B>Request URI: </B>" + request.getRequestURI() + "<BR>\n" + "<B>Request Protocol: </B>" + request.getProtocol() + "<BR><BR>\n" + "<TABLE BORDER=1 ALIGN=\"CENTER\">\n" + "<TR BGCOLOR=\"#FFAD00\">\n" + "<TH>Header Name<TH>Header Value"); 13 Basic Internet Programming Servlets ... Enumeration headerNames = request.getHeaderNames(); while(headerNames.hasMoreElements()) { String headerName = (String)headerNames.nextElement(); out.println("<TR><TD>" + headerName); out.println(" <TD>" + request.getHeader(headerName)); } out.println("</TABLE>\n</BODY></HTML>"); } /** Vi låter doPost använda doGet. */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } Basic Internet Programming Servlets Cookies Cookies Cookies kan användas för att koppla data till viss användare Namn/lösen (försiktighet krävs dock!), var man varit på siten, varukorg eller liknande En cookie lagras på klientens dator Vi nästa ansluten till servern kan man läsa av cookien hos servern 14 Basic Internet Programming Servlets ... Exempel, setCookies public class SetCookies extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { for(int i=0; i<3; i++) { // Default maxAge is -1, indicating cookie // applies only to current browsing session. Cookie cookie = new Cookie("Session-Cookie-" + i, "Cookie-Value-S" + i); response.addCookie(cookie); cookie = new Cookie("Persistent-Cookie-" + i, "Cookie-Value-P" + i); // Cookie is valid for an hour, regardless of whether // user quits browser, reboots computer, or whatever. cookie.setMaxAge(3600); response.addCookie(cookie); } Basic Internet Programming Servlets ... response.setContentType("text/html"); PrintWriter out = response.getWriter(); String title = "Setting Cookies"; out.println(ServletUtilities.headWithTitle(title) + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1 ALIGN=\"CENTER\">" + title + "</H1>\n" + "There are six cookies associated with this page.\n" + "To see them, visit the\n" + "<A HREF=\"/servlet/ShowCookies\">\n" + "<CODE>ShowCookies</CODE> servlet</A>.\n" + "<P>\n" + "Three of the cookies are associated only with the\n" + "current session, while three are persistent.\n" + "Quit the browser, restart, and return to the\n" + "<CODE>ShowCookies</CODE> servlet to verify that\n" + "the three long-lived ones persist across sessions.\n" + "</BODY></HTML>"); }} 15 Basic Internet Programming Servlets ... Exempel, showCookies public class ShowCookies extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); String title = "Active Cookies"; out.println(ServletUtilities.headWithTitle(title) + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1 ALIGN=\"CENTER\">" + title + "</H1>\n" + "<TABLE BORDER=1 ALIGN=\"CENTER\">\n" + "<TR BGCOLOR=\"#FFAD00\">\n" + " <TH>Cookie Name\n" + " <TH>Cookie Value"); Basic Internet Programming Servlets ... Cookie[] cookies = request.getCookies(); if (cookies != null) { Cookie cookie; for(int i=0; i<cookies.length; i++) { cookie = cookies[i]; out.println("<TR>\n" + " <TD>" + cookie.getName() + "\n" + " <TD>" + cookie.getValue()); } } out.println("</TABLE></BODY></HTML>"); } } 16 Basic Internet Programming Servlets Sessionstracking Sessionstracking För att hantera en användares sessioner med en server och kanske flytta data mellan olika delar kan vi använda Cookies z URL-rewriting z Kan vara avstängda hos klienten Lite klumpigt att hantera Hidden forms z Också lite knöligt Java servlets erbjuder speciella sessionmekanismer som döljer den faktiska metod som används Basic Internet Programming Servlets exempel import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import java.net.*; import java.util.*; public class ShowSession extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); String title = "Session Tracking Example"; HttpSession session = request.getSession(true); String heading; Integer accessCount = (Integer)session.getAttribute("accessCount"); 17 Basic Internet Programming Servlets ... if (accessCount == null) { accessCount = new Integer(0); heading = "Welcome, Newcomer"; } else { heading = "Welcome Back"; accessCount = new Integer(accessCount.intValue() + 1); } // Use setAttribute instead of putValue in version 2.2. session.setAttribute("accessCount", accessCount); Basic Internet Programming Servlets ... out.println(ServletUtilities.headWithTitle(title) + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1 ALIGN=\"CENTER\">" + heading + "</H1>\n" + "<H2>Information on Your Session:</H2>\n" + "<TABLE BORDER=1 ALIGN=\"CENTER\">\n" + "<TR BGCOLOR=\"#FFAD00\">\n" + " <TH>Info Type<TH>Value\n" + "<TR>\n" + " <TD>ID\n" + " <TD>" + session.getId() + "\n" + "<TR>\n" + " <TD>Creation Time\n" + " <TD>" + new Date(session.getCreationTime()) + "\n" + "<TR>\n" + " <TD>Time of Last Access\n" + " <TD>" + 18 Basic Internet Programming Servlets ... new Date(session.getLastAccessedTime()) + "\n" + "<TR>\n" + " <TD>Number of Previous Accesses\n" + " <TD>" + accessCount + "\n" + "</TABLE>\n" + "</BODY></HTML>"); } /** Handle GET and POST requests identically. */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } Basic Internet Programming Servlets Request and Session Attributes Servlet can access attributes stored within the request or within the session Attributes are like variables: One servlet can set an attribute in the request or session, another (included or forwarded to) servlet can retrieve the attribute value, change it, etc If the attribute is in the session, future accesses from the same browser can read its value (this is how login is done) javax.servlet.ServletRequest.setAttribute(String name, Object value), getAttribute(String name) javax.servlet.HttpSession.setAttribute(String name, Object value), getAttribute(String name) 19 Basic Internet Programming Servlets Hands-on with Tomcat Various ways of mapping a servlet in web.xml z z z z /servlet/HelloWorldServlet /servlet/hello /world /anything.abc A form response Some HTTP request headers Some HTTP response headers Redirections, forwards, includes Sessions Basic Internet Programming Servlets Länkar Tutorial från SUN http://java.sun.com/docs/books/tutorial/servlets/index.html Tutorial av Marty Hall http://www.apl.jhu.edu/~hall/java/Servlet-Tutorial/ Diverse resurser http://www.corewebprogramming.com/ 20