1 servlets & jsps, part 2: persistency & contexts – everything you ever wanted to know but...
Post on 22-Dec-2015
225 views
TRANSCRIPT
1
Servlets & JSPs, Part 2:Servlets & JSPs, Part 2:Persistency & Contexts –Persistency & Contexts –
Everything you ever wanted to know Everything you ever wanted to know but were afraid to askbut were afraid to ask
3
The Servlet Context ObjectThe Servlet Context Object
• A Servlet context represents the Web application in which Servlets live.
• There is a single ServletContext per Web-app.
• You can get the Servlet context from within doXXX using the method getServletContext().
• In JSPs there’s no need to call this method - it’s already stored in a variable called application.
• Different Servlets in the same web-app will get the same ServletContext object, when calling getServletContext() (also during different sessions – discussed later).
4
Uses of ServletContextUses of ServletContext• Communicating with the Servlet container (e.g., Apache
Tomcat)
• Stores Web application initialization parameters.
• Stores and can be used to manipulate application-shared attributes (objects that are kept throughout the application's life).
• Can be used to access the logger.
• Can be used to dispatch requests to other resources
• The context can be locked (using synchronize) to protect a critical section from all Web-application accesses.
5
ServletContext MethodsServletContext Methods• Access initialization parameters:
getInitParameter(String name), getInitParameterNames()
• Read Web-application scoped attributes:getAttribute(String name), getAttributeNames()
• Manipulate Web-application scoped attributes:setAttribute(String, Object), removeAttribute(String)
• Transform context-relative paths to absolute paths and vice versa:getRealPath(String path), URL getResource(String path)
e.g. get the servlet’s class filename
from its mapping
Run http://localhost/dbi/context.htmlJNDI = Java Naming and Directory Interface
e.g. get the URL from a static resource
(doesn’t work well with
servlet-mappings)
6
More ServletContext MethodsMore ServletContext Methods
• Write to the application log:
log(String msg), log(String message, Throwable exception)
• Get a request dispatcher (discussed later): RequestDispatcher getRequestDispatcher(String path)
• Name and version of the Servlet container: String getServerInfo()
Also writes the stack trace
$CATALINA_BASE/logs/…
7
An Example: Service CountAn Example: Service Count
public class CounterServlet extends HttpServlet { public void init() throws ServletException { Integer counter = (Integer) getServletContext().getAttribute("counter"); if (counter == null) { getServletContext().setAttribute("counter",new Integer(0)); }}
We cannot use int since
an attribute must not
be a primitive
The counter may already be initialized, if the server is running
but the instance of CounterServlet was removed from the
memory (or if another Servlet already created it).
In this case we wouldn’t like to reinitialize the counter with 0.
8
public void doGet(HttpServletRequest req,HttpServletResponse res) throws ServletException, IOException {
PrintWriter out = res.getWriter(); res.setContentType("text/html"); int counter = 0; synchronized(this) { counter = ((Integer)getServletContext(). getAttribute("counter")).intValue(); getServletContext(). setAttribute("counter",new Integer(++counter)); } out.println("<html><head><title>Counter</title><body><h1>" + "[" + counter + "]</h1></body></html>");}}
The character encoding of the
response cannot be set after
the writer was created
A new Integer must
be created since
the value of an
Integer cannot be
modified (why?)
9
Context ListenersContext Listeners
• A context listener is an object that reacts to the following events:- Context initialization
- Context destruction
• We can use a context listener to perform application initialization or termination tasks
• To implement such a listener,- Implement the interface ServletContextListener- Put the class file in myApp/WEB-INF/classes like all the other
classes
- Register the listener with the server
Read more about the ServletContextListener Interface
10
Cheating with Service CountCheating with Service Countpublic class CounterInitializer implements ServletContextListener { public void contextInitialized(ServletContextEvent sce) { sce.getServletContext(). setAttribute("counter",new Integer(1000)); }
public void contextDestroyed(ServletContextEvent sce) {}} <web-app>
<listener> <listener-class>CounterInitializer</listener-class> </listener></web-app>
Uncomment the listener lines in web.xml or use web2.xml
For whoever needs a reminder, web.xml was
discussed in depth in the Tomcat lecture
12
CookiesCookies
• Cookies are a general mechanism that server-side applications can use to both store and retrieve long-term information on the client side
• Servers send cookies in the HTTP response and browsers are expected to save and to send the cookie back to the Server, whenever they make additional requests to the Server
13
• Java Servlet API provides comfortable mechanisms to handle cookies
• The class javax.servlet.http.Cookie represents a cookie
- Getter methods:
• getName(), getValue(), getPath(), getDomain(), getMaxAge(), getSecure()…
- Setter methods:
• setValue(), setPath(), setDomain(), setMaxAge()…
The domain to which the cookie
is attached
Servlets and Cookies APIServlets and Cookies API
Kind of expiration
date
The path (prefix) to which
the cookie is attached
Send cookies on secure
connections only or
on any connection
Read more about the Cookie Class
14
Servlets and Cookies API (cont)Servlets and Cookies API (cont)
• Get the cookies from the servlet request:
Cookie[] HttpServletRequest.getCookies()
• Add a cookie to the servlet response:
HttpServletResponse.addCookie(Cookie cookie)
15
An ExampleAn Example
<html>
<head><title>Insert your Name</title></head>
<body> <h1>What is your name?</h1>
<form action="welcomeback" method="get">
<p>
<input type="text" name="username" />
<input type="submit" />
</p>
</form>
</body>
</html>
getname.html
16
An Example (cont)An Example (cont)
public class WelcomeBack extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
String user = req.getParameter("username");
if (user == null) { // Find the "username" cookie
Cookie[] cookies = req.getCookies();
for (int i = 0; cookies != null && i < cookies.length; ++i) {
if (cookies[i].getName().equals("username"))
user = cookies[i].getValue();
}
} else res.addCookie(new Cookie("username", user));
WelcomeBack.java
Look for “username”
cookie
If “user” parameter was sent, create a
“username” cookie
Look for
“username”
parameter in the
query
17
An Example (cont)An Example (cont)
if (user == null) // No parameter and no cookie
res.sendRedirect("getname.html");
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<html><body><h1>Welcome Back " + user
+ "</h1></body></html>");
}
} WelcomeBack.java
Run /dbi/welcomeback twice or more.Check the sent headers
Delay setting the
ContentType until it’s
clear that a content
should be sent at all
19
Sessions – A ReminderSessions – A Reminder• HTTP is stateless• But some web applications need states (e.g. online
stores)• A session captures the notion of a continuous interaction
between a server and a client• Session management should be efficient
- The client should not send the whole shopping cart every time a single product is added (Once upon a time There was a shopping site which saved the entire cart, including prices and discounts in a cookie – why is this really really bad?)
• We’ll discuss 2 mechanisms- Session Cookies- URL rewriting
20
Session CookiesSession Cookies
Web browser 1
Web server
request request
ServletServlet
id1
response
put cookie id1
response
Create Session
id1
The cookie contains the session-ID: a unique (sometimes random) identifier
assigned by the Servlet container. This is an example for something called
an opaque identifier (coat-checks, typically implemented in C with void*
are another very different example worth knowing). Why is it a good
strategy to “store” the session data using an opaque identifier on the client?
21
Session CookiesSession Cookies
Web browser 2
Web server
request request
ServletServlet
id1
response
put cookie id2
response
Create Session
id2id2
22
Session CookiesSession Cookies
Web server
request
ServletServlet
id1
response response
request
Cookie: id1
id2
Session read/write
Web browser 1
id1
23
Session CookiesSession Cookies
Web server
request
ServletServlet
id1
response response
request
Cookie: id2
id2
Session read/write
Web browser 2
id2
25
Here’s an example that demonstrates the session is attached to a specific application:
1. Two new applications are available – test1, test2
2. Read the code of /test1/test1.jsp
3. Read the code of /test2/test2.jsp
4. Run /test1/test1.jsp, and use the links to go to the other application’s JSP and back several time.Notice that 2 session-cookies are set by the server, one for every application.
5. Invalidate any of the application’s session and notice that the other application is still valid
A Session is attached to an ApplicationA Session is attached to an Application
26
Accessing the Session DataAccessing the Session Data
• The session object is represented by the class HttpSession.
• Use the methods HttpServletRequest.getSesssion() or HttpServletRequest.getSesssion(true) within doXXX to get the current HttpSession object, or to create one if it doesn’t exist. In JSP simply access the object session (we’ll learn later how to tell a JSP not to create a session).- Only when a new session is created, the server automatically
add a session cookie to the response (set-cookie header)- As a result you must call this method before the response is
committed (don’t worry, JSP calls it before your code runs).
• Use HttpServletRequest.getSesssion(false) if you do not want to create a new session when no session exists.
27
HttpSession MethodsHttpSession Methods• Session data is accessed in a hash-table fashion:
- setAttribute(String name,Object value)
- Where is this value stored? (server-side or client-side)
- Object getAttribute(String name)
• More methods:
- getId()
- removeAttribute()
- Enumeration getAttributeName()
- isNew()
- getCreationTime(),
getLastAccessedTime()
True iff there’s an active session
which the client hasn’t joined yet.
That is:
• The server created a session and
sent session-cookie
• This session timeout was not
reached,
• No response from the client
containing this session-cookie
was received
The session-id
discussed earlier
Read more about the HttpSession Interface
28
Session Expiration – Client sideSession Expiration – Client side• Session may expire because of client-side reasons
- The client agent runs on another process (was restarted)
- Session cookie has expired (exceeded max-age)
- Client used external links (writing the URL explicitly in the address-bar) instead of the server’s rewritten ones
Unless the session-cookie has max-age and you manage to open another
browser before max-age expired.
For example open http://localhost/dbi/session?timeout=100&reload=
50&maxage=20
Close your browser and open a new one with this URL again…
We’ll discuss the code in few more slides
Applies to URL-Rewriting (discussed soon). If the client uses cookies,
external links should raise no problem. (The session-cookie will be
sent, though only to URLs under the path like always…)
29
Session Expiration – Server sideSession Expiration – Server side• Server calls session.invalidate()
- User asked to logout
• Session idle time has passed
- You can also set/get the timeout of a specific session
and override the server default values using session.getMaxInactiveInterval(),
session.setMaxInactiveInterval()
<web-app> <session-config>
<session-timeout>10</session-timeout> </session-config></web-app>
web.xml
Timeout is given in
minutes.
A zero or negative value
means infinite timeout
webapps/myApp/WEB-INF/web.xml
30
Session Expiration ExampleSession Expiration Examplepublic class SessionTester extends HttpServlet {
private int nReloads = 1;
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
int timeout = Integer.parseInt(request.getParameter("timeout"));
int refresh = Integer.parseInt(request.getParameter("reload"));
int maxage =
Integer.parseInt(request.getParameter("maxage"));
HttpSession session = request.getSession();
SessionTester.java
#Reloads (#GET request) with the
same session
Either find an existing session (in this case the client already accepted its
session-cookie which was sent in a previous response and sent it back in
the current request), OR create a new session and send a session cookie
Read request
paramters
31
if (session.isNew()) {
session.setMaxInactiveInterval(timeout);
nReloads = 1;
Cookie newCookie = new Cookie("JSESSIONID", session.getId());
newCookie.setMaxAge(maxage);
newCookie.setPath(request.getContextPath());
response.reset();
response.addCookie(newCookie);
} else { ++nReloads; }
response.setContentType("text/html");
PrintWriter out = response.getWriter();
Date found = (Date)session.getAttribute("lastdate");
Date now = new Date();
Reset counter
Search for “lastdate” in the session. This
attribute value is the session’s creation date
Only if a new session was created
Delete the headers
containing the old
cookie and add the
new cookie
Advance the counter
Set server-side limits on
session
Create a new cookie
identical to the old one
and set client-side
limits on the session
using the max-age
32
out.println("<html><head><title>Session Tester</title>");
out.println("<meta http-equiv=\"refresh\" content=\""
+ refresh + "\"/></head>\n");
out.println("<body>");
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; ++i) {
out.println("<h2>Client sent cookie : " + cookies[i].getName()
+ " = " + cookies[i].getValue() + "</h2>\n");
}
if ((cookies == null) || (cookies.length) == 0) {
out.println("<h2>Client sent no cookies</h2>\n");}
Set the refresh rate
Print the request cookies
Or print that there are no cookies…
33
if (session.isNew()) {
out.println("<h2>(New) Session ID = " + session.getId() + "</h2>\n");}
else { out.println("<h2>Session ID = " + session.getId() + "</h2>\n");}
out.println("<h2>Session max inactive interval = " +
session.getMaxInactiveInterval() + "</h2>\n");
out.println("<h2>Current date = " + now + "</h2>\n");
if (found == null) {session.setAttribute("lastdate", now);
out.println("<h2>No lastdate found in session<h2>\
n");}
else {out.println("<h2>Found in session lastdate = " + found + "<h2>\n");}
out.println("<h2>#Responses with this session = " + nReloads + "</h2>\n");
out.println("</body></html>"); }
Set the new
session’s
creation date
Print the session ID and declare if it’s a new one
34
Running the exampleRunning the example1. Run http://localhost/dbi/session.html
with timeout=10, reload=5, max-age=20.notice that the set-cookie isn’t sent in the response unless a new session is created
2. Rerun with timeout=20, reload=5, max-age=10
3. Now deny to the servlet cookies modification request.Check the sent request headers, notice that in the next reload the server will ask again to set the session-cookie with a new session ID
4. Run http://localhost/dbi/session?timeout=100&reload=50&maxage=100Run http://127.0.0.1/dbi/session?timeout=100&reload=50&maxage=100notice that a new session is created since the HOST string is different even tough 127.0.0.1 is the IP of localhost
5. Run http://localhost/dbi/session2?timeout=100&reload=5This is a similar code without the explicit new cookie creation and max-age feature.Deny to save the session-cookie and notice that you’ll be asked to save a session-cookie after every reloadConclude that the call getSession() itself creates a new set-cookie header if no session was accepted by the user, and not the header manipulation code in which purpose is to set the max-age cookie property
If the client denies, it will not
send this cookie back with
future requests
35
Example: A Basic Shopping CartExample: A Basic Shopping Cart
• In the following example a basic shopping cart for an online store is implemented
• The application consists of two Servlets:- Store.java: the main store site
- ShoppingCart.java: handles cart manipulation
36
Online-Store ExampleOnline-Store Example
public class Store extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<html><head>"
+ "<link rel=\"stylesheet\" type=\"text/css\""
+ " href=\"cartstyle.css\"/></head><body>");
HttpSession session = req.getSession();
if (session.getAttribute("item-list") == null) {
out.println("<h1>Hello new visitor!</h1>");
session.setAttribute("item-list", new LinkedList());
}
List itemList = (List) session.getAttribute("item-list");
Store.java
37
Online-Store Example (cont)Online-Store Example (cont)
out.println("<h2>Your Shopping Cart:</h2><ol>");
for (Iterator it = itemList.iterator(); it.hasNext();)
out.println("<li>" + it.next() + "</li>");
out.println("</ol>");
out.println("<form method=\"post\" action=\"cart\">");
out.println("<p>Add item:<input name=\"item\" type=\"text\"/>"
+ "<input type=\"submit\" value=\"send\"/></p>"
+ "<p><input type=\"submit\" value=\"empty cart\" "
+ "name=\"clear\"/></p></form>");
out.println("</body></html>");
}
} Store.java
2 buttons of type submit and
therefore they are named
(the 2nd one) , so the
servlet can identify which
one was pressed
38
Online-Store Example (cont)Online-Store Example (cont)
public class ShoppingCart extends HttpServlet {
public void doPost(HttpServletRequest req, HttpServletResponse
res) throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();
List items = (List) req.getSession().getAttribute("item-list");
out.println("<html><head><link rel=\"stylesheet\""
+ " type=\"text/css\" href=\"cartstyle.css\"/>"
+ "</head><body>");
ShoppingCart.java
39
Online-Store Example (cont)Online-Store Example (cont)
if (req.getParameter("clear") != null) {
items.clear();
out.println("<h2>Your Shopping Cart is Empty!</h2>");
} else {
String item = req.getParameter("item");
items.add(item);
out.println("<h2>The item <i>" + item +
"</i> was added to your cart.</h2>");
}
out.println("<h2><a href=\"store\">Return to the store</a></h2>");
out.println("</body></html>");
}} ShoppingCart.java
40
URL RewritingURL Rewriting• Cookies might cause some security risk
- Would you really like any server to put files claimed to be “cookies” on you computer ?
- A computer is being used by multiple users• User A buys some products• User B comes right after user A finished working• Cookies are kept as local files• User B can read the private content of A’s cookies
• Solution 1- Use session cookies instead of other cookies so that B can
only read the session ID- But B can still read the domain and the path (e.g., and
discover that A visited adult sites or divorce lawyers sites)
• Solution 2- Use URL-rewriting (user A still better clean her history…)
41
URL RewritingURL Rewriting
Web browser
Web server
request request
ServletServlet
id1
response response
Create Session
<HTML…>
< A HREF=“servletURL;sessID=id1>”
/<…HTML>
The domain and path are not sent with
the rewritten URLs, since the
session-ID is attached to the URL
only as long as the user follows inner
links. If the user writes a complete
URL in the address-bar, she will
probably won’t copy the session-ID
part (or it will have expired)
42
URL RewritingURL Rewriting
Web server
request
ServletServlet
id1
response response
request
)no cookie(
id2
Session read/write
Web browser 1
GET servletURL;sessID=id1 HTTP/1.0
<HTML…>
<A HREF=“servletURL2;sessID=id1>”
/<…HTML>
43
Servlet URL RewritingServlet URL Rewriting
• Use the following methods of the doXXX response object to rewrite URLs:- String HttpServletResponse.encodeURL(String url)
• Use for HTML hyperlinks
- String HttpServletResponse.encodeRedirectURL(String url)• Use for HTTP redirections
• These methods contain the logic to determine whether the session ID needs to be encoded in the URL
• For example, if the request has a session cookie, then url is returned unchanged
• Some servers implement the two methods identically
44
Back to our StoreBack to our Store• The Store example assumes that the client supports cookies
• To fix the program, we should encode the links we supply:• Store.java:
"<form method=\"post\" action=\"" + res.encodeURL("cart") + "\">"
• ShoppingCart.java: “<a href=\"" + res.encodeURL("store") + "\">"
Clear the cookies, run again http://localhost/dbi/store, and this time deny saving cookies.
How does the server know before the client denies/accepts what to put in the href?
First understand the problem and try to think how you would solve it.
Now check the first item’s URL sent to /cart and compare to the other items. You could also compare the source of /store at the 1st access and on subsequent accesses
45
The Session ListenerThe Session Listener
• The session listener reacts to the following events:- A new session has been created
- A session is being destroyed
• To obtain a session listener, implement the interface javax.servlet.http.HttpSessionListener
Read more about the HttpSessionListener Interface
Right now you should be experiencing a strong feeling of déjà
vu, as we’ve already met ContextListeners that react in a
similar way to the events of context creation / destruction…
46
Session-Listener Example (cont)Session-Listener Example (cont)
public class CartInitializer implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent se) {
List itemList = new LinkedList();
se.getSession().setAttribute("item-list",itemList);
itemList.add("A Free Apple");
}
public void sessionDestroyed(HttpSessionEvent se) {}
} CartInitializer.java
<listener>
<listener-class>CartInitializer</listener-class>
</listener> web.xml
Run again http://localhost/dbi/store, only this time uncomment the listener
48
Implicit ObjectsImplicit Objects
• As seen before, some useful variables, like request and session are predefined
• These variables are called implicit objects
• Implicit objects are part of the JSP specifications
• Implicit objects are defined in the scope of the service method- Can these be used in JSP Declarations? (what would
you expect their to be within a declaration?)- What about redefinitions within JSP Scriptlets?Check the result of : no-redefinition, redefinition within a Declaration, redefrinition within a Scriptlet
49
The objectsThe objects request request and and responseresponse
• request and response are the HttpServletRequest and HttpServletResponse arguments of the service method
• Using these objects, you can:
• Read request parameters
• Set response headers
• etc. (everything we learned and will learn in Servlet lectures)
Read more about HttpServletRequest Interface, HttpServletResponce Interface
50
The objectThe object out out
• This is the Writer used to write output into the response body
• This object implements the interface JspWriter that combines the functionality of PrintWriter and BufferedWriter
• Recall that you can adjust the buffer size, or turn buffering off, through use of the buffer attribute of the page directive
Read more about JspWriter Class
51
The objectThe object pageContext pageContext• pageContext is a new object introduced by JSP
• This object stores all important elements used by the
generated Servlet, like the application context, the session,
the output writer, etc.
• It enables vendors to extend their JSP implementation
- E.g. Apache could extend the PageContext class so it’ll store some
additional application context, extend HttpJspBase
class so that the new PageContext could be obtained …
• This object is also used to store page-scoped attributes
(e.g., Java Beans - discussed later)
• This object is a field of Apache’s HttpJspBase classRead more about PageContext Class
52
The objectThe object session session• This is the HttpSession object associated with the
request
• If the session attribute in the page directive is turned off (<%@ page session="false" %>) then this object is not available (use this if you do not want to always automatically create a session or want to create the session yourself – try to find examples for scenarios which require this).
• Otherwise (by default) a session is created.
Read more about HttpSession Interface
Check the result of using a session after defining “no session”
53
The objectThe object config config
• This is the ServletConfig of the page, as received in the init() method
• Reminder: contains Servlet specific initialization parameters
• Later, we will study how initialization parameters are passed to JSP pages
• Recall that you can also obtain the ServletContext from config as explained in the next slide…
Read more about ServletConfig Interface
54
The objectThe object application application
• This is the ServletContext as obtained via
getServletConfig().getContext()
• Reminder from about an hour ago:
- The ServletContext is shared by all Servlets belonging to the
same Web-application (including those generated from JSP)
- Getting and setting attributes is accomplished using
getAttribute and setAttribute of ServletContext
- You can use this object to get application-wide initialization
parameters
Read more about ServletContext Interface
55
Page Scope VariablesPage Scope Variables
• service() local variables
• pageContext attributes
client 1
client 2
a.jsp
b.jsp
i.e. objects defined within Scriptlets
i.e. objects set using pageContext.setAttribute()
The JSPs reside in the same application in the following
examples
The values of these variables are only retained for the
single execution of one JSP in
response to one client.
56
Request ScopeRequest Scope
• request attributes
client 1
client 2
a.jsp
b.jsp
client 1
client 2
a.jsp
b.jsp
A simple scenario
A more complex scenario in which the request is
forwarded to another JSP
57
Session ScopeSession Scope
• session attributes
client 1
client 2
a.jsp
b.jsp
Many JSPs (which belong to the same
application) have the same session
attributes when responding to the
same single Client
i,e. set with session.setAttribute()
Run http://localhost/test1/test1.jspConclude that there is a different session for every application.
58
Servlet ScopeServlet Scope
• Servlet members
client 1
client 2
a.jsp
b.jsp
i.e. defined within Declarations.
The data members of a single JSP
have the same values for all clients since there’s only a
single instance of the
generated Servlet sub-
class
59
Application ScopeApplication Scope
• application attributes
client 1
client 2
a.jsp
b.jsp
i.e. defined using application.setAttribute()
Possibly many JSPs to many Clients
60
Servlet Package and Helper ClassesServlet Package and Helper Classes
• The generated Servlet has a named package
• In Tomcat, this package is: org.apache.jsp
• In Java, you cannot use classes from the default package (i.e. with no package declaration) from a named package!
• Therefore, helper classes used by JSP pages must have a named package
For example, classes which are imported using the page directive
62
The Request DispatcherThe Request Dispatcher
• The RequestDispatcher object is used to send a client request to any (other) resource on the server
• Such a resource may be dynamic (e.g. a Servlet or a JSP file) or static (e.g. an HTML document)
• To send a request to a resource x, use:getServletContext().getRequestDispatcher("x")
Path must begin with a “/” and is interpreted as relative to
the current context root (web application directory)
63
Request Dispatcher MethodsRequest Dispatcher Methods
• void forward(ServletRequest request,
ServletResponse response)
- Forwards a request from a Servlet to another resource (do
not write to the contents if calling this)
• void include(ServletRequest request,
ServletResponse response)
- Includes the content of a resource in the response of the
current servlet (may write to the contents before or after)
Read more about the RequestDispatcher Interface
64
Passing on DataPassing on Data
• 3 different ways to “pass data” to (that is, make data available to) the Servlet or JSP to which the request is forwarded:
- Data that will be used only for this request:
request.setAttribute("key", value);
- Data will be used for this client (also for future requests):
session.setAttribute("key", value);
- Data that will be used in the future for every client:
context.setAttribute("key", value);
65
An ExampleAn Example
• The Servlet JokesAndImages enables a user to choose a random joke or a random image
• The server has 5 images in the directory images/ and 5 jokes (txt files) in the directory jokes/
• Empty requests are forwarded to an HTML file that enables the user to choose a joke or an image
• Requests to a joke are forwarded to the servlet Jokes
• Requests to an image are forwarded to a random image from the directory images/
66
Jokes and ImagesJokes and Images
<html>
<head><title>Images and Jokes</title></head>
<body>
<h1>Please Select:</h1>
<form method="post" action="JokesAndImages">
<h2>
<input type="submit" name="joke"
value="A Joke" />
<input type="submit" name="image"
value="An Image" />
</h2>
</form>
</body></html> imagesJokesOptions.html
67
Jokes and Images (cont)Jokes and Images (cont)
public class JokesAndImages extends HttpServlet {
public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
int randomNum = 1 + Math.abs((new Random()).nextInt() % 5);
if (req.getParameter("joke") != null) {
req.setAttribute("jokeNumber", new Integer(randomNum));
getServletContext().getRequestDispatcher("/Jokes").forward(req,res);
} else if (req.getParameter("image") != null) {
getServletContext().getRequestDispatcher("/images/image" +
randomNum + ".gif").forward(req, res);
} else getServletContext().getRequestDispatcher
("/imagesJokesOptions.html"). forward(req,res);
}
public void doGet ... }} JokesAndImages.java
68
Jokes and Images (cont)Jokes and Images (cont)public class Jokes extends HttpServlet {
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html"); PrintWriter out = res.getWriter();
out.println("<html><body><h1>A Joke</h1><pre>");
int jokeNum = ((Integer) req.getAttribute("jokeNumber")).intValue();
getServletContext().getRequestDispatcher
("/jokes/joke" + jokeNum + ".txt").include(req, res);
out.println("\n</pre>");
out.println("<a href=\"" + req.getRequestURL() + "\">Back</a>");
out.println("</body></html>");
}}
Jokes.java
Actually since this request was forwarded using a RequestDispatcher, the
URL reflects the path used to obtain the RD and not the path specified
by the client as usual. You can use another request parameter, or simply
some plain old Javascript (history.back()) to fix this problem.
Check http://localhost/dbi/forward1 to understand this problem.
69
Forwarding versus RedirectionForwarding versus Redirection• HttpServletResponse.SendRedirect() requires extra
communication on part of the client (Why?)
• SendRedirect does not pass the request, therefore the request parameters cannot be obtained easily
• You can’t reach external resources with RequestDispatcher but you can use SendRedirect
• You can forward to resources inside WEB-INF (why is this good?)
• SendRedirect ends up with a different URL on the client
• Be careful: Which image will be loaded in the following scenario? Servlet /forwardjoke forwards to /jokes/joke1.html and joke1.html contains <img src="image1.gif".../>
You can use either the session or the context to pass those parameters
Open /dbi/image1.gif, /dbi/jokes/image1.gif, /dbi/jokes/joke1.html, /dbi/forwardjoke and check…