Internet Technologies 6 - Servlets I
- F. Ricci
Internet Technologies 6 - Servlets I F. Ricci 2010/2011 Content - - PowerPoint PPT Presentation
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
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
Read the explicit data sent by the client Read the implicit HTTP request data sent by the
Generate the results Send the explicit data (i.e., the document) to the
Send the implicit HTTP response data
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/. * © 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();
} }
code
Servlet Container
Client Web Java Virtual Machine (JVM) Web Server Servlet 1 HTTP Request HTTP Response Servlet 2 Servlet n
Tomcat is distributed as a ZIP archive http://
unzip the download file, for instance into a root-
To run Tomcat you'll need to tell it where to find
Set the JAVA_HOME environment variable to
To run Tomcat: open a command window change directory to Tomcat's bin directory Type startup
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)
Go to netbeans: tools>servers to look at these
Create a directory in \webapps called hello Create a directory in \webapps\hello called WEB-INF and
Set the classpath C:\>set CLASSPATH=\apache-tomcat-6.0.16\common
Compile C:\>javac HelloWorld.java Deploy the web.xml file in C:\apache-
Or use an IDE (Netbeans) – separating sources (web
/bin/startup.bat
Point Browers to
All the Docs are there
Check out the
Here's the outline of a basic servlet that handles GET and
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); } }
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";
"<HTML>\n" + "<HEAD><TITLE>Hello (2)</TITLE></HEAD>\n" + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1>Hello</H1>\n" + "</BODY></HTML>"); } }
code
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
The JSP framework is a better solution code
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)";
"<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1>" + title + "</H1>\n" + "</BODY></HTML>"); } }
code
init Executed once when the servlet is first loaded
service Called in a new thread by server for each request Dispatches to doGet, doPost, etc.
doGet, doPost, doXxx Handles GET, POST, etc. requests Override these to provide desired behavior destroy Called when server deletes servlet instance
javadoc
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
HTTP/1.1 304 Not Modified And the browser shows the cashed url The servlet must only implement the following method to
public long getLastModified(HttpServletRequest
The app server will call it when a client requests the servlet And will send back a result only if the page was modified
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
LotteryNumbers code
You can do the same experiments with a telnet
<!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
request.getParameter(“FirstName") Returns URL-decoded value of first occurrence of
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
Returns a one-element array if param is not repeated Returns null if no such parameter is in the query request.getParameterNames() or
Returns Enumeration or Map of request parameters Usually reserved for debugging.
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();
"<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
getform postform
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";
"<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
Enumeration paramNames = request.getParameterNames(); while(paramNames.hasMoreElements()) { String paramName = (String)paramNames.nextElement();
String[] paramValues = request.getParameterValues(paramName); if (paramValues.length == 1) { String paramValue = paramValues[0]; if (paramValue.length() == 0)
else
} else {
for(int i=0; i<paramValues.length; i++) {
}
} }
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
You cannot safely insert arbitrary strings into servlet
< and > can cause problems anywhere & and " can cause problems inside of HTML
You sometimes cannot manually translate The string is derived from a program excerpt or
The string is derived from HTML form data Failing to filter special characters from form data
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("<"); break; case '>': filtered.append(">"); break; case '"': filtered.append("""); break; case '&': filtered.append("&"); break; default: filtered.append(c); } } return(filtered.toString()); } …
code
public class BadCodeServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { …
"<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
form calling the badservlet
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
goodservlet
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
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,
HTTP 1.0 All request headers are optional HTTP 1.1 Only Host is required Conclusion Always check that request.getHeader is
Call servlet
public class ShowRequestHeaders extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
(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
"<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();
}
} /** 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); } }
Accept Indicates MIME types browser can handle Can send different content to different clients. For
Accept-Encoding Indicates encodings (e.g., gzip or compress)
See following example
Authorization User identification for password-protected
Instead of HTTP authorization, use HTML forms
Servers have high-level way to set up
Connection In HTTP 1.0, keep-alive means browser can
Persistent connections mean that the web
Servlets can't do this unilaterally; the best
Cookie
Gives cookies previously sent to client Use getCookies, not getHeader (we shall do
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
If-Modified-Since Indicates client wants page only if it has been changed
Don’t handle this situation directly; implement
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
Can be easily spoofed; don't let this header be sole
Some browsers (Opera), ad filters (Web Washer), and
User-Agent Best used for identifying category of client
Web browser vs. I-mode cell phone, etc.
For Web applications, use other parameters if
Again, can be easily spoofed We shall touch this later
Dilbert used with permission of United Syndicates Inc.
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
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)) {
response.setHeader("Content-Encoding", "gzip"); } else {
}
code
…
(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++) {
}
} }
Uncompressed (28.8K modem),
Compressed (28.8K modem),
Caution:
call call
Use User-Agent only when necessary Otherwise, you will have difficult-to-maintain code that
Check for null The header is not required by the HTTP 1.1 specification,
To differentiate among Firefox, Netscape, and Internet
Both Firefox and Internet Explorer say “Mozilla” at the
Note that the header can be faked If a client fakes this header, the servlet cannot tell the
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
call
The Referer header designates the location of
No Referer is set if the user typed the address of
You can customize a page depending on how the
Customize the layout of a page according to
Change the content if the user come from the
Supply a link to go back Track the effectiveness of a banner or a link.