720 likes | 927 Views
Studying Servlet Programming. Introduction. Java servlets enable you to create responsive, reliable, and scalable server-side Web applications. They run inside a servlet container that communicates with the user’s Web browser by exchanging HTTP request and response objects.
E N D
Introduction • Java servlets enable you to create responsive, reliable, and scalable server-side Web applications. • They run inside a servlet container that communicates with the user’s Web browser by exchanging HTTP request and response objects. • The servlet container processes each servlet’s request in a separate thread, maintains user sessions, creates response objects and sends them back to the client. • Servlets are easily portable to any application server or servlet engine
Creating a Magazine PublisherApplication Using Servlets • When you use an online store or bank or when you search for some information on the Internet, your request is usually processed on the server side. • Only a limited number of operations, such as simple calculations and input validation, are performed on the client’s machine using Java applets and JavaScript. • Java applets have security restrictions and depend on the version of the Web browser’s JVM.
Creating a Magazine PublisherApplication Using Servlets • Web browser has to download large Java programs, the site’s response time will substantially increase. • That’s why the better choice is to keep only lightweight HTML pages (a thin client) on the client’s machine, while major processing should be done by the programs running on the server. • The server computers could be more powerful than the client computers, have the proper version of JVM, and might be clustered, load-balanced, fail-overed, and so on.
The server side • The server needs to run a servlet engine or servlet container. • If a user requests some information that should be retrieved programmatically from a database or any other resource. • we’ll use Java servlets that will accommodate the request, build an output HTML page dynamically, and pass that page over to the user with the help of the Web server. • Even though HTML is just a markup language, it has some basic elements and GUI components, such as buttons, text fields, check boxes, and dropdown lists, that allow users to enter data, make some selections, and submit requests to a remote server.
The server side • For example, the HTML <FORM>tag enables users to enter and submit data from a Web page. • A <FORM> tag has important attributes such as action and method. • The action attribute contains the uniform resource locator (URL) of the server program to which the browser should send the user’s input. • The method attribute tells the browser how to send the data; this attribute is usually either Get or Post. • Ex: <form action= “http://www.mymagpublisher.com/servlet/LoginServlet” method=Get> • <input type=Text name=”id” > The name of the text field will be passed by the browser to the servlet as a parameter name.
The client side • Magazine Publisher wants to maximize the number of customers by minimizing requirements for the client’s computer. • The publisher wants to ensure that even the clients with older computers and slow Internet connections will not wait long. • User should be able to work with any system, from an old PC to a Unix-based dumb terminal to an Apple computer - as long as the system has a Web browser installed. • There is no need of install any software on the client machine, the maintenance of the system becomes easy because all software and hardware upgrades will be done in one central location - the publisher’s company.
Creating an HTML login screen <html> <head> <title>Magazine Publisher Login</title> </head> <body> <P> <form action=”http://www.mymagpublisher.com/servlet/LoginServlet” method=Post> Enter Login ID: <input type=Text name=”id” > <P> Enter Password: <input type=Password name=”pwd”> <P> <input type=”Submit” value=”Login”> <input type=”Reset” > </form> </body> </html>
Writing the servlet import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class LoginServlet extends javax.servlet.http.HttpServlet { public void doPost(HttpServletRequestreq, HttpServletResponseres) throws ServletException, IOException { res.setContentType(“text/html”); PrintWriter out = res.getWriter();
String id = req.getParameter(“id”); String password = req.getParameter(“pwd”); out.println(“<HTML><BODY>”); if(“jsmith”.equalsIgnoreCase(id)&&“spring12”.equalsIgnoreCase(password)){ out.println(“Hello “+ id + “. Welcome to our magazines! “); } else { out.println(“Id/Password combination is not valid”); } out.println(“</BODY></HTML>”); } }
The following is a list of the steps involved in the browser/servlet interaction, using LoginServlet as an example: • The user enters his or her ID and password and presses the Submit button on the Login Web page. • The Web browser tries to connect to http://www.mymagpublisher.com/servlet/LoginServletand sends the entered data using Post. • A servlet engine checks to see if the LoginServlet is already running. • If LoginServlet is not running the servlet container starts it and invokes its method init(). • The servlet container calls the service() method of the servlet’s superclass, passing HttpServletRequest and HTTPServletResponse to it as arguments.
The ancestor’s method service() calls the doPost() method of the LoginServlet. • The code in LoginServlet.doPost() extracts the data entered by the user from HttpServletRequest. • After applying some application business logic contained in the doPost() method, the results are sent to the user’s browser when the code invokes the method println() on the object PrintWriter. The method getWriter() gets the reference to this object from the HTTPServletResponse. • The user’s Web browser displays the received HTML page.
HTTP Get and Post requests • If the HTML <FORM>tag has the attribute method=Get, the servlet has to override the method doGet(). • In this case the Web browser will append the values entered by the user to the end of the URL string, using the question mark (?) as a delimiter. • For example, if pub_login has the method=GET as its form attribute, the Web browser will create the following URL string: • http://www.mymagpublisher.com/servlet/LoginServlet?id= ”jsmith”&pwd=”Spring12”
The HTML method Get has the following disadvantages: • The length of the URL string is limited. • Different browsers have different restrictions on the URL length. • The URL string can be used only for text/data exchange. The binary data are not passed as a part of the URL. • The data is not protected - the password is visible as it’s a part of the URL. • If the HTML <FORM> tag uses the method=Post attribute, the servlet has to override the doPost() method. • The doPost() method does not append the user’s input to the URL string and can be used for sending and receiving various data types described in the Multipurpose Internet Mail Extensions (MIME).
If you’d like a servlet to handle both Get and Post requests, override both the doGet() and doPost() methods. • If you place the application’s code in the method doGet(), the method doPost() should look like this: public void doPost(HttpServletRequestreq, HttpServletResponseres) throws ServletException, IOException { doGet(req, res); // execute the code from doGet() }
Using the Servlet Context • The servlet context is a place inside the container where the servlet(s) live. • More than one Web application can be deployed in the servlet container, and each of them will have its own servlet context. • The ServletContext class can be used by the servlet whenever it needs to use the services of the container. • Java does not have global variables, but in a stand-alone Java application you can use the System.setProperty() and getProperty() methods to create variables visible by all the application’s classes.
You can also do this by using the following methods of the ServletContext class: • setAttribute() • getAttribute() • getAttributeNames() • removeAttribute() • For example, a servlet can set the database name in the init() method, as follows: • getServletContext().setAttribute(“com.mycompany.dbname”,”Alpha”); • Another servlet from the same Web application can get this value as follows: • String dbName= getServletContext().getAttribute(“com.mycompany.dbname”);
Keep in mind that these attributes are local to a Java Virtual Machine (JVM), and that in a distributed environment such global parameters should be stored in the HttpSession object. • The ServletContext class allows a servlet to load shareable file resources such as HTML, GIF, and so on. • Here’s an example: • InputStream in = getServletContext().getResourceAsStream(“/myLogo.gif”);
Performing URL Redirection • Servlets often need to redirect the processing of the user’s request to a different URL, servlet or a Java Server Page. • You can do this by using either of the following methods: • HttpServletResponse.sendRedirect() or • RequestDispatcher.forward()
Using RequestDispatcher • Let’s say LoginServlet needs to pass control to LostPasswordServlet if the user enters the wrong password. • The reference to the instance of the RequestDispatcher can be obtained from the ServletContext by means of either the getRequestDispatcher() or getNamedRequestDispatcher() method. • When this is done just call the dispatcher’s forward() method, providing the HttpServletRequest and HttpServletResponse as arguments.
Using RequestDispatcher ServletContext context = getServletContext(); RequestDispatcherrequestDisp = null; String password = req.getParameter(“pwd”); if (password.equals(“spring12”) { requestDisp = context.getRequestDispatcher(“MainServlet”); } else { requestDisp = context.getRequestDispatcher(“LostPasswordServlet”); } requestDisp.forward(req,res);
If the first servlet needs to stay in control and include its own output to the response object as well as the output produced by another servlet or JSP, the include() method should be used instead of forward(). For example: • requestDisp.include(req,res) • It’s worth mentioning that an instance of RequestDispatcher can also be obtained from the ServletRequest object. • The difference between calling getRequestDispatcher() on ServletRequest and calling getRequestDispatcher() on ServletContext is that ServletRequest enables you to specify a relative path as a method argument.
Using sendRedirect() • While the forward() method performs the redirection on the server side using original request and response objects, the sendRedirect() method sends the request with the new URL back to the client, which connects to this URL, thereby creating a new pair of request/response objects: • response.sendRedirect(“www.anothersite.com”) ; • the sendRedirect() method is slower than forward(), but it gives you more flexibility because it can redirect the user to any URL, while forward() works only within the same Web application.
The Lost Password screen example import javax.servlet.*; import javax.servlet.http.*; public class LostPasswordServlet extends HttpServlet { public void doPost(HttpServletRequestreq, HttpServletResponseres) throws ServletException, IOException { PrintWriterout = res.getWriter(); String id = req.getParameter(“id”); out.println(“<head><title>”); out.println(“Magazine Publisher Lost Password”); out.println(“</title></head><body>”);
out.println(“Dear “ + id + “<P>”); out.println(“Please enter the email address you have “); out.println(“registered with your Magazine Publisher”); out.println(“account. We will send instructions on “); out.println(“how to reset your password “); out.println(“to that address.<P>”); out.println(“<form action=\””http://”); out.println(“www.mymagpublisher.com/PasswordMailerServlet”); out.println(“method=Get>”); out.println(“Enter e-mail: <input type=Text “); out.println(“name=”email”>”); out.println(“<input type=\”Submit\””); out.println(“value=\”Send\”></form></body></html>”); }}
Session tracking with servlets • HTTP is a stateless protocol. This means that if a user inputs some data on a Web page and then goes to another page, the second page does not “know” what has been done on the first. • Session tracking allows the server application to remember the user’s input and carry it from page to page. • A session is some logical task that a user tries to accomplish on a Web site. Think of the so-called shopping cart application. • Session information can be stored either in the client or in the servertier. • The Java Servlets API enables you to store the session data by using cookies, rewriting the URL, and using hidden form fields • cookies or the session tracking API provided by the HTTPSession class.
Cookies • A cookie is a small file that a Web server may send to the user’s Web browser, which in turn saves it to the hard disk. • This file contains an ID that is unique to the computer, so the server can identify the user when he or she connects to that particular Web site again. • Whenever you connect to a Web site, your browser finds all cookies for the site and sends them to the URL as part of the HttpServletRequest object. • Internet browsers give you the option to disable cookies. • Your Web browser will store up to 20 cookies per Web site, and the size of a cookie cannot exceed 4K. • A servlet can also specify the maximum lifetime of the cookie in seconds.
The following code snippet shows how a servlet can create and send a cookiethat will store the user’s account ID: public void doGet(HttpServletRequestreq, HttpServletResponseres){ Cookie myCookie = new Cookie(“acctID”,”12345”); myCookie.setMaxAge(60*60*24); res.addCookie(myCookie); }
When a user connects to the same site again, a servlet can retrieve the client’s cookiesfrom the HttpServletRequest object, as shown here: Cookie [] cookies = req.getCookies(); for (i=0; i < cookies.length; i++){ Cookie currentCookie = cookie[i]; String name = currentCookie.getName(); String value = currentCookie.getValue(); if(name.equals(“acctID”)){ // find some data about the user based in the account ID and create a // personalized page. For example display the books which user // has been looking for during the previous visit, etc. } }
Cookies enable you to store the session information on the client side, which has the following advantages: • Cookies can survive server crashes because they are stored on the client’s hard disk. • They lighten the load on the server’s memory. • They simplify server fail-over procedure, because they may store the valuable data about the last user selections made before the server has crashed. • Cookies also have the following disadvantages: • Cookies can be read by unauthorized users. • They can increase the load on the network. • User can disable cookies in their Web browsers.
URL rewriting • URL rewriting allows the session ID to be attached to the end of the URL string to help the servlet container identify the client for subsequent requests. • The session info is appended in the same way as the parameters in an HTTP GET request. • The major advantage of URL rewriting is that it enables servlets to keep track of the session when a user disables cookies. • The automatic switch between the use of cookies and URL rewriting is a configurable parameter of the servlet container. • When a servlet appends the session info to the URL, it should encode this URL using the HttpServletResponse method urlEncode(). This method will determine whether the Web browser supports cookies, and if not it’ll attach the session ID to the URL.
For example, if the original HTML page has the following link <a href=”http://www.mymagpublisher.com/servlet/subscribeServlet”> • the servlet can rewrite this URL and append the session ID, if needed, as follows: String newURL= res.urlEncode(“http://www.mymagpublisher.com/servlet/ subscribeServlet”); out.println(“<a href=\””+newUrl + “\”>Subscribe to Magazine</a>”); • The Web browser might get the URL http://www.mymagpublisher.com/servlet/subscribeServlet;jsessionid=657487
Hidden fields • The hidden type is one of the valid types for the input fields of the HTML tag, and when a servlet prepares an HTML page it may include one or more hidden fields. • The following is a code fragment from a servlet that creates an HTML page and stores selected magazines in the HTML code. out.println(“<form action= http://www.mymagpublisher.com/servlet/subscribeServlet>”); out println(“Select another magazine: <input type=text name=item”); out.println(“<input type=submit value=Add>”); out.println(“<input type=hidden name=item value=Smart Cooking>”); out.println(“</form>”);
Hidden fields • The user will see an empty text field with a button, but when you check the source of this page, you’ll see the hidden field with the value Smart Cooking. • During subsequent requests the servlet can retrieve all the values from the hidden fields, as shown here: String[] selectedItems = request.getParameterValues(“item”); • All previously selected magazines (as contained in our shopping cart) will be stored in the selectedItems array. • Hidden fields give you more flexibility than URL rewriting, because no size restrictionexists.
session-tracking API with HttpSession object • Instead of sending the shopping cart across the network to the client, you can keep it inside the javax.servlet.http.HttpSession object in the servlet container’s memory. • The container creates one HttpSession object per client, and the servlet can store any objects as key/value pairs there. • These objects are the attributes of the HttpSession object.
The following line of code creates or finds a session object: HttpSessionmySession = request.getSession(true); • The getSession(true) call means “Find my session object, or create a new one if not found.” • The getSession(true) call should be used in the very first servlet. At this moment the application server generates a unique session ID and sends it to the user’s Web browser as a cookie or by using URL rewriting. • The getSession(false) call means “find my session object,” assuming that the object might have been created prior to this HTTP request. • If this call returns null, the session object may have been destroyed. • the servlet close the session by making the following call: HttpSession.invalidate();
Now let’s create a simple class that represents a magazine: class Magazine { String title; double price; } • This is what you can do in the doGet()method of the servlet: HttpSessionsession = request.getSession(true); Vector myShoppingCart = session.getAttribute(“shoppingCart”); if (myShoppingCart == null){ // This is the first call - create a Vector myShoppingCart= new Vector(); } Magazine selectedMag = new Magazine(); // create an instance of a magazine object selectedMag.title = request.getParameter(“magTitle”); selectedMag.price = Double.parseDouble(request.getParameter(“price”)); myShoppingCart.addElement(selectedMag); // Add the magazine to shopping cart session.setAttribute(“shoppingCart”, myShoppingCart); // Put the shopping cart back into the session object
Example of a LoginServlet with an access counter import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class LoginServlet extends javax.servlet.http.HttpServlet{ public void doPost(HttpServletRequestreq, HttpServletResponseres) throws ServletException, IOException { res.setContentType(“text/html”); PrintWriterout = res.getWriter(); String id = req.getParameter(“id”); String password = req.getParameter(“pwd”);
HttpSessionsession = request.getSession(true); Integer counter=session.getAttribute(“logAttempt”); if (counter == null){ // This is the first call - create a counter counter=new Integer(1); } else { // do not allow more that 5 attempts if (counter.intValue()>5){ res.sendRedirect(“BadLoginServlet”); } } // Store the counter in the session object session.setAttribute(“logAttempt”,counter);
out.println(“<HTML><BODY>”); if(“jsmith”.equalsIgnoreCase(id) && spring12”.equalsIgnoreCase(password)){ out.println(“Welcome “+ id +”!”); // store the user’s ID for other servlets session.setAttribute(“userID”,id); } else { out.println(“Id/Password combination is not valid”); } out.println(“</BODY></HTML>”); } }
Listeners • Listeners are Java classes that a programmer can write and deploy in the Web-application archive. • These listeners can be notified of lifecycle events and attribute changes. • Typically, a servlet-context creation event is used for the creation of such reusable objects as connections to the databases, messaging servers, and so on. • When a servlet context is about to be shut down these objects should be gracefully closed. • These interfaces are used in the same way as any other Java interface: Just write a class that implements one of them and specify its name in the deployment descriptor. • Each of the callback methods defined in these interfaces has one argument - an object describing an event.
The following code fragment demonstrates how to write a servlet-context listener that connects to an external messaging server when the servlet context is created. This listener closes the connection when the context is destroyed.
package com.magpub.listeners; public class MagPublisherContextListenerimplements ServletContextListener { private ServletContext context = null; public void contextInitialized(ServletContextEvent e){ this.context=e.getServletContext(); Connection mqCon = .... // Establish a connection to the JMS server // Store connection to the messaging server in the ServletContext object. context.setAttribute(“mqConnection”,mqCon); } public void contextDestroyed(ServletContextEvent e){ // disconnect from the messaging server mqCon = (Connection) context.getAttribute(“mqConnection”); mqCon.disconnect(); } }
Session listeners can be implemented in a similar way. • we need to create an administrative tool that displays all active users working with a MagPublisher servlet. • Every time a user creates a session we can send a JMS message to a queue. These messages will be retrieved and displayed by another GUI program. public class MagPublisherSessionListener implements HttpSessionListener { public void sessionCreated(HttpSessionEvent e) { // The code sending a JMS message to add a user goes here } public void sessionDestroyed(HttpSessionEvent e) { // The code sending a JMS message to remove a user goes here } }
The act of adding an object or attribute to, or removing it from, a session can be caught by implementing the HttpSessionAttributeListener. • If this attribute/object also implements the HttpSessionBindingListener interface, the servlet container sends a notification to this object saying something like “Hey, you’ve been bound to (or unbound from) a session!” • One more interface is HttpSessionActivationListener. The servlet container may decide to move session objects from one JVM to another, and it may passivate (temporarily remove from memory) and activate the session during this process. • A container may also persist sessions and reactivate them after restart. A container is required to send a notification about these events to all attributes bound to sessions implementing HttpSessionActivationListener.
Filters • Servlet filters are used for additional processing or transformation of data contained in the request or response objects. • Basically, filters allow you to plug in Java classes performing some business processing before or after the servlet. • This is done without changing the servlet’s code just by simple modification of the deployment descriptor elements located in the web.xml file. • Filters add an ability to change the behavior of the servlets without changing the servlets’ code. • They act like pre- or post-processors.
if (someInitParam==’a’){ out.println(“<HTML>”); ... }else if (someInitParam ==’b’){ out.println(“<?xml version=\”1.0\”?>”); ... } • However, if the output in the WML format is requested the servlet’s code has to be modified to add yet another else if statement. • Filters enable you to remove formatting or some other reusable processing of the incoming or outgoing data from the servlet’s class. • They act as plugins to the request and response objects and can perform additional processing for existing servlets without requiring modification to the servlets’ code.
The following reusable tasks are good candidates to be used in the filters rather than in the servlets themselves: • Encryption • Sign-on • Auditing • Data compressing • Performance benchmarking • Debug logging • Filters can also be chained to create a combination of functions without modifying the servlet’s code - just add another <FILTER> section to the deployment descriptor file to turn the filter on. • By modifying another configuration parameter <filter-mapping> you can apply the filter to one or multiple servlets.