internet technologies 6 - servlets i - unibzricci/it/slides/6-servlets-1.pdf · 2011. 4. 7. ·...

Post on 09-Sep-2021

2 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Internet Technologies 6 - Servlets I

F. Ricci

2010/2011

Content

  Basic Servlets

  Tomcat

  Servlets lifecycle

  Servlets and forms

  Reading parameters

  Filtering text from HTML-specific characters

  Reading headers

  Sending compressed content

  Differentiating among browsers

  Referer

Most of the slides were made available by www. coreservlets.com

Servlet Roles

  Read the explicit data sent by the client

  Read the implicit HTTP request data sent by the browser

  Generate the results

  Send the explicit data (i.e., the document) to the client

  Send the implicit HTTP response data

HelloWorld

import java.io.*; import javax.servlet.*; import javax.servlet.http.*;

/** Very simplistic servlet that generates plain text. * <P> * Taken from More Servlets and JavaServer Pages * from Prentice Hall and Sun Microsystems Press, * http://www.moreservlets.com/. * &copy; 2002 Marty Hall; may be freely used or adapted. */

public class HelloWorld extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); out.println("Hello World"); } } code

Servlet Container

Servlet Architecture

Client Web

Java Virtual Machine (JVM)

Web Server

Servlet 1

HTTP Request

HTTP Response

Servlet 2

Servlet n

Installing and Running Tomcat

  Tomcat is distributed as a ZIP archive http://tomcat.apache.org

  unzip the download file, for instance into a root-level directory: C:\apache-tomcat-6.0.16

  To run Tomcat you'll need to tell it where to find your J2SE SDK installation

  Set the JAVA_HOME environment variable to C:\Program Files\Java\jdk1.6.0_04

  To run Tomcat:

  open a command window

  change directory to Tomcat's bin directory

  Type startup

Tomcat Directory Structure

Tomcat binaries: startup, shutdown

All jar libraries: e.g. servlet-api.jar

Configuration files: e.g. when you build your application in Netbeans a new file is added to indicate where is deployed (e.g., C:\apache-tomcat-6.0.16\conf\Catalina\localhost\coresjsp.xml)

Directories of the web applications deployed here, possibly generated by .war files deployed here (with a web.xml file)

Catalina Base

  Go to netbeans: tools>servers to look at these details

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application

2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>bob</servlet-name> <servlet-class>HelloWorld</servlet-class> </servlet>

<servlet-mapping> <servlet-name>bob</servlet-name> <url-pattern>/HelloWorld</url-pattern> </servlet-mapping> </web-app>

Compiling and deploying

  Create a directory in \webapps called hello

  Create a directory in \webapps\hello called WEB-INF and then a subdirectory classes where to put the sources and the compiled files

  Set the classpath

  C:\>set CLASSPATH=\apache-tomcat-6.0.16\common\lib\servlet-api.jar

  Compile

  C:\>javac HelloWorld.java

  Deploy the web.xml file in C:\apache-tomcat-6.0.16\webapps\hello\WEB-INF

  Or use an IDE (Netbeans) – separating sources (web directory) and deployment (build directory).

Starting Tomcat

  /bin/startup.bat or startup.sh

  Point Browers to http://localhost:8080 should see default page

  All the Docs are there on the default page!

  Check out the examples pages, good tutorials

Basic Servlet Structure

  Here's the outline of a basic servlet that handles GET and POST requests in the same way:

import java.io.*;

import javax.servlet.*; import javax.servlet.http.*;

public class SomeServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); // Use "out" to send content to browser } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }

}

HelloWorld HTML

import java.io.*; import javax.servlet.*; import javax.servlet.http.*;

public class HelloServlet2 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 (2)</TITLE></HEAD>\n" + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1>Hello</H1>\n" + "</BODY></HTML>"); } }

code

Some Simple HTML-Building Utilities

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"); } ... }

  Don’t go overboard   Complete HTML generation packages

usually work poorly   The JSP framework is a better solution

code

HelloServlet3: Packages and Utilities

package coreservlets;

import java.io.*; import javax.servlet.*; import javax.servlet.http.*;

public class HelloServlet3 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); String title = "Hello (3)"; out.println(ServletUtilities.headWithTitle(title)+ "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1>" + title + "</H1>\n" + "</BODY></HTML>"); } }

code

The Servlet Life Cycle (Servlet Interface)

  init

  Executed once when the servlet is first loaded Not called for each request

  service

  Called in a new thread by server for each request

  Dispatches to doGet, doPost, etc. Do not override this method!

  doGet, doPost, doXxx

  Handles GET, POST, etc. requests

  Override these to provide desired behavior

  destroy

  Called when server deletes servlet instance Not called after each request.

javadoc

Example of usage of init

  If a servlet get a request for a url with the http header

  if-Modified-Since: Mon, 12 Nov 2010 18:00:00 GMT

  It can check if something has really changed the output after that date – if not the servlet sends back a reply:

  HTTP/1.1 304 Not Modified

  And the browser shows the cashed url

  The servlet must only implement the following method to know when it has been modified the last time:

  public long getLastModified(HttpServletRequest request)

  The app server will call it when a client requests the servlet

  And will send back a result only if the page was modified (according to the value returned by the method) after Mon, 12 Nov 2010 18:00:00 GMT

Code

  The init method set the time the page was modified

public void init() throws ServletException {

// Round to nearest second (i.e, 1000 milliseconds)

modTime = System.currentTimeMillis()/1000*1000;

for(int i=0; i<numbers.length; i++) {

numbers[i] = randomNum();

}

}

  An then overwrite the method that tells when the page was modified

public long getLastModified(HttpServletRequest request) {

return(modTime); }

LotteryNumbers code

Calls to the servlet

The page was modified after 8:00:00 GMT

The page was not modified after 9:00:00 GMT

Calls to the servlet

  You can do the same experiments with a telnet connection (e.g., using putty)

HTML Form

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<HTML> <HEAD><TITLE>A Sample Form Using GET</TITLE></HEAD> <BODY> <H2 ALIGN="CENTER">A Sample Form Using GET</H2> <FORM ACTION="http://localhost:8080/coresjp/ServletForm"> <CENTER>

First name: <INPUT TYPE="TEXT" NAME="FirstName" VALUE=""><BR/> Last name: <INPUT TYPE="TEXT" NAME="LastName" VALUE=""><P> <INPUT TYPE="SUBMIT"> </CENTER> </FORM> </BODY> </HTML>

form

Reading form data in servlets

  request.getParameter(“FirstName")

  Returns URL-decoded value of first occurrence of FirstName parameter in query string

  Works identically for GET and POST requests

  Returns null if no such parameter is in query data

  request.getParameterValues(“FirstName")

  Returns an array of the URL-decoded values of all occurrences of FirstName parameter in query string

  Returns a one-element array if param is not repeated

  Returns null if no such parameter is in the query

  request.getParameterNames() or request.getParameterMap()

  Returns Enumeration or Map of request parameters

  Usually reserved for debugging.

Reading parameters

import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import java.util.*;

public class ServletForm extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

response.setContentType("text/html"); PrintWriter out = response.getWriter();

out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">" + "<HTML>\n" + "<HEAD><TITLE>ServletForm</TITLE></HEAD>\n" + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1 ALIGN=\"CENTER\">ServletForm</H1>\n" + "<UL>\n" + "<LI><B>FirstName</B>: "+ request.getParameter("FirstName")+"\n"+ "<LI><B>LastName</B>: "+ request.getParameter("LastName")+"\n"+ "</UL>\n" + "</BODY></HTML>"); }

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }

ServletForm code

Example: reading all parameters

getform postform

Reading All Parameters

public class ShowParameters 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";

String title = "Reading All Request Parameters";

out.println(docType +

"<HTML>\n" +

"<HEAD><TITLE>"+title + "</TITLE></HEAD>\n"+

"<BODY BGCOLOR=\"#FDF5E6\">\n" +

"<H1 ALIGN=CENTER>" + title + "</H1>\n" +

"<TABLE BORDER=1 ALIGN=CENTER>\n" +

"<TR BGCOLOR=\"#FFAD00\">\n" +

"<TH>Parameter Name<TH>Parameter Value(s)");

code

Reading All Parameters

Enumeration paramNames = request.getParameterNames(); while(paramNames.hasMoreElements()) { String paramName = (String)paramNames.nextElement(); out.print("<TR><TD>" + paramName + "\n<TD>"); String[] paramValues = request.getParameterValues(paramName); if (paramValues.length == 1) { String paramValue = paramValues[0]; if (paramValue.length() == 0) out.println("<I>No Value</I>"); else out.println(paramValue); } else { out.println("<UL>"); for(int i=0; i<paramValues.length; i++) { out.println("<LI>" + paramValues[i]); } out.println("</UL>"); } } out.println("</TABLE>\n</BODY></HTML>"); }

Reading All Parameters

public void doPost(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response);

}

}

Filtering Strings for HTML-Specific Chars

  You cannot safely insert arbitrary strings into servlet output

  < and > can cause problems anywhere   & and " can cause problems inside of HTML

attributes   You sometimes cannot manually translate

  The string is derived from a program excerpt or another source where it is already in some standard format

  The string is derived from HTML form data   Failing to filter special characters from form data

makes you vulnerable to cross-site scripting attack.

Filtering Strings for HTML-Specific Chars

public class ServletUtilities { public static String filter(String input) { if (!hasSpecialChars(input)) { return(input); } StringBuffer filtered = new StringBuffer(input.length()); char c; for(int i=0; i<input.length(); i++) { c = input.charAt(i); switch(c) { case '<': filtered.append("&lt;"); break; case '>': filtered.append("&gt;"); break; case '"': filtered.append("&quot;"); break; case '&': filtered.append("&amp;"); break; default: filtered.append(c); } } return(filtered.toString()); } …

code

No Filtering

public class BadCodeServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { … out.println(docType + "<HTML>\n" + "<HEAD><TITLE>"+title+"</TITLE></HEAD>\n" + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1 ALIGN=\"CENTER\">" + title + "</H1>\n"+ "<PRE>\n" + getCode(request) + "</PRE>\n" + "Now, wasn't that an interesting sample\n" + "of code?\n" + "</BODY></HTML>"); }

protected String getCode(HttpServletRequest request) { return(request.getParameter("code")); } }

code

Spaces and line breaks are preserved

Special Chars: no filtering

form calling the badservlet

Servlet that does Filtering

public class GoodCodeServlet extends BadCodeServlet {

protected String getCode(HttpServletRequest request) {

return

(ServletUtilities.filter(super.getCode(request)));

//get the code as in the super class and then do the filter

}

}

code

Filtering

goodservlet

A Typical HTTP Request

GET /servlet/Search?keywords=servlets+jsp HTTP/1.1 Accept: image/gif, image/jpg, */* Accept-Encoding: gzip Connection: Keep-Alive Cookie: userID=id456578 Host: www.somebookstore.com Referer: http://www.somebookstore.com/findbooks.html User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)

  You need to understand HTTP to be effective with servlets and JSP

Reading Request Headers

  General methods of the HttpServletRequest

  getHeader(String name) the first one with that name

  getHeaders(String name) all occurrences of the header

  getHeaderNames

  Specialized methods of the HttpServletRequest

  getCookies

  getAuthType and getRemoteUser

  getContentLength

  getContentType

  getDateHeader

  getIntHeader

  Related info

  getMethod, getRequestURI , getQueryString, getProtocol

Checking For Missing Headers

  HTTP 1.0   All request headers are optional

  HTTP 1.1   Only Host is required

  Conclusion   Always check that request.getHeader is

non-null before trying to use it

String val = request.getHeader("Some-Name");

if (val != null) { … }

All Request Headers (Firefox)

Call servlet

Request Headers (Internet Explorer)

Making a Table of Request Headers

public class ShowRequestHeaders extends HttpServlet {

public void doGet(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

out.println

(docType +

"<HTML>\n" +

"<HEAD><TITLE>"+title+"</TITLE></HEAD>\n"+

"<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" +

code

Request Headers (Continued)

"<TABLE BORDER=1 ALIGN=\"CENTER\">\n" + "<TR BGCOLOR=\"#FFAD00\">\n" + "<TH>Header Name<TH>Header Value"); 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>"); }

/** Since this servlet is for debugging, have it * handle GET and POST identically. */

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }

Common HTTP 1.1 Request Headers

  Accept

  Indicates MIME types browser can handle

  Can send different content to different clients. For example, PNG files have good compression characteristics but are not widely supported in browsers. A servlet could check to see if PNG is supported, sending <IMG SRC="picture.png" ...> if it is supported, and <IMG SRC="picture.gif" ...> if not.

  Accept-Encoding

  Indicates encodings (e.g., gzip or compress) browser can handle.

  See following example

Common HTTP 1.1 Request Headers

  Authorization   User identification for password-protected

pages   Instead of HTTP authorization, use HTML forms

to send username/password and store info in session object - this approach is usually preferable because standard HTTP authorization results in a small, terse dialog box that is unfamiliar to many users

  Servers have high-level way to set up password-protected pages without explicit programming in the servlets.

Common HTTP 1.1 Request Headers

  Connection

  In HTTP 1.0, keep-alive means browser can handle persistent connection - in HTTP 1.1, persistent connection is default

  Persistent connections mean that the web server can reuse the same socket over again for requests very close together from the same client (e.g., the images associated with a page, or cells within a framed page).

  Servlets can't do this unilaterally; the best they can do is to give the web server enough info to permit persistent connections - they should set Content-Length response header.

Common HTTP 1.1 Request Headers

  Cookie   Gives cookies previously sent to client   Use getCookies, not getHeader (we shall do

that in a next lecture)

  Host   Indicates host given in original URL   This is a required header in HTTP 1.1   This fact is important to know if you write a

custom HTTP client (e.g., WebClient we used before) or telnet to a server and use the HTTP/1.1 version.

Common HTTP 1.1 Request Headers

  If-Modified-Since   Indicates client wants page only if it has been changed

after specified date   Don’t handle this situation directly; implement getLastModified instead

  See lottery-number example we have already shown   Referer

  URL of referring Web page

  Useful for tracking traffic; logged by many servers

  Can also be used to let users set preferences and then return to the page they came from

  Can be easily spoofed; don't let this header be sole means of deciding how much to pay sites that show your banner ads

  Some browsers (Opera), ad filters (Web Washer), and personal firewalls (Norton) screen out this header.

Common HTTP 1.1 Request Headers

  User-Agent   Best used for identifying category of client

 Web browser vs. I-mode cell phone, etc.   For Web applications, use other parameters if

possible   Again, can be easily spoofed   We shall touch this later

Sending Compressed Web Pages

Dilbert used with permission of United Syndicates Inc.

Sending Compressed Pages: GzipUtilities.java

public class GzipUtilities { public static boolean isGzipSupported (HttpServletRequest request) { String encodings = request.getHeader("Accept-Encoding"); return((encodings != null) && (encodings.indexOf("gzip") != -1)); }

public static boolean isGzipDisabled (HttpServletRequest request) { String flag = request.getParameter("disableGzip"); return((flag != null)&& // if the parameter is not null (!flag.equalsIgnoreCase("false"))); // and not "false" }

public static PrintWriter getGzipWriter (HttpServletResponse response) throws IOException { return(new PrintWriter (new GZIPOutputStream (response.getOutputStream()))); } }

code

Sending Compressed Pages: LongServlet.java

public class LongServlet extends HttpServlet {

public void doGet(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

// Change the definition of "out" depending on

// whether or not gzip is supported.

PrintWriter out;

if (GzipUtilities.isGzipSupported(request) &&

!GzipUtilities.isGzipDisabled(request)) {

out = GzipUtilities.getGzipWriter(response);

response.setHeader("Content-Encoding", "gzip");

} else {

out = response.getWriter();

}

code

Sending Compressed Pages: LongServlet.java

out.println

(docType +

"<HTML>\n" +

"<HEAD><TITLE>" + title + "</TITLE></HEAD>\n" +

"<BODY BGCOLOR=\"#FDF5E6\">\n" +

"<H1 ALIGN=\"CENTER\">" + title + "</H1>\n");

String line = "Blah, blah, blah, blah, blah. " +

"Yadda, yadda, yadda, yadda.";

for(int i=0; i<10000; i++) {

out.println(line);

}

out.println("</BODY></HTML>");

out.close();

}

}

Sending Compressed Pages: Results

  Uncompressed (28.8K modem), Firefox, Netscape and Internet Explorer: > 50 seconds

  Compressed (28.8K modem), Firefox, Netscape and Internet Explorer: < 5 seconds

  Caution: be careful about generalizing benchmarks

call

call

Differentiating Among Different Browser Types

  Use User-Agent only when necessary   Otherwise, you will have difficult-to-maintain code that

consists of tables of browser versions and associated capabilities

  Check for null   The header is not required by the HTTP 1.1 specification,

some browsers let you disable it (e.g., Opera), and custom clients (e.g., Web spiders or link verifiers) might not use the header at all

  To differentiate among Firefox, Netscape, and Internet Explorer, check for “MSIE,” not “Mozilla”   Both Firefox and Internet Explorer say “Mozilla” at the

beginning of the header   Note that the header can be faked

  If a client fakes this header, the servlet cannot tell the difference.

Differentiating Among Different Browser Types

public class BrowserInsult extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); String title, message; // Assume for simplicity that Firefox and IE are // the only two browsers. String userAgent = request.getHeader("User-Agent"); if ((userAgent != null) && (userAgent.indexOf("MSIE") != -1)) { title = "Microsoft Minion"; message = "Welcome, O spineless slave to the " + "mighty empire."; } else { title = "Hopeless Firefox Rebel"; message = "Enjoy it while you can. " + "You <I>will</I> be assimilated!"; }

code

Differentiating Among Browser Types (Result)

call

Referer

  The Referer header designates the location of the page users were on when they clicked on a link

  No Referer is set if the user typed the address of the page

  You can customize a page depending on how the user reached it   Customize the layout of a page according to

the site that link to   Change the content if the user come from the

same domain or another domain   Supply a link to go back   Track the effectiveness of a banner or a link.

top related