Programming Jakarta Struts, 2nd Edition [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Programming Jakarta Struts, 2nd Edition [Electronic resources] - نسخه متنی

Chuck Cavaness

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








2.5 Forward Versus Redirect


It's often necessary for more than one component to
share control of a request. For example, one servlet may be
responsible for authenticating and authorizing a client, while
it's the job of a different servlet to retrieve some
data for the user. The sharing of a request can be accomplished in
several different ways.

There are important differences between how a web container processes a forward
request versus how it processes a redirect. The Struts front
controller servlet, discussed in Chapter 1,
will always perform one or the other for a typical request, so
it's important that you understand these differences
and the impact that each mechanism will have on your application.


2.5.1 Using a Redirect


When the sendRedirect() method
is invoked, it causes the web container to return to the browser a
response indicating that a new URL should be requested. Because the
browser issues a completely new request, any objects that are stored
as request attributes before the redirect occurs will be lost. This
is one of the biggest differences between a forward and redirect.
Figure 2-5 illustrates why this occurs.


Figure 2-5. A redirect causes the browser to issue a new request

Because of the extra round trip that occurs, a redirect is slower
than a forward. Example 2-1 provides an example
servlet that performs a redirect for a JSP page called
result.jsp when a request for the servlet is
issued.


Example 2-1. A Java servlet that performs a redirect when it receives a request

package com.oreilly.struts.chapter2examples;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.RequestDispatcher;
public class RedirectServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException {
redirect(request, response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException {
redirect(request, response);
}
/**
* Set a few URL parameters and objects for the request to see what happens
* to them during a redirect.
*/
protected void redirect(HttpServletRequest req, HttpServletResponse resp)
throws ServletException,IOException {
log("A request arrived for " + req.getServletPath( ));
req.setAttribute("firstName", "John");
req.setAttribute("lastName", "Doe");
String contextPath = req.getContextPath( );
String redirectStr = contextPath + "/result.jsp?username=foo&password=bar";
log("redirecting to " + redirectStr);
// Always call the encodeRedirectURL method when perfoming a redirect
resp.sendRedirect(resp.encodeRedirectURL(redirectStr));
}
}

When the servlet in Example 2-1 receives either a
GET or POST request, it calls the redirect()
method and passes to it the HttpServletRequest and
HttpServletResponse objects. The method sets two
String objects into the request, to demonstrate
that they will not be available after the redirect, and it creates a
String that will become the URL for which the
client is told to make a new request. After the
encodeRedirectURL() method is called and passed
the redirect string, the sendRedirect() method is
invoked on the response object.


All URLs passed to the sendRedirect() method
should be run through the encodeRedirectURL()
method, so that the session ID can be included if the browser
doesn't support cookies and session tracking needs
to occur. The Struts framework performs this step automatically in
the RequestProcessor during normal action
processing.

The JSP page to which the servlet will redirect is shown in Example 2-2.


Example 2-2. The result.jsp page

<html>
<head>
<title>Struts Redirect/Forward Example</title>
</head>
<body>
<img src="/image/library/english/10003_images\tomcat-power.gif">
<br>
<%
String firstName = (String)request.getAttribute( "firstName" );
if ( firstName == null ){
firstName = "Not found in request";
}
String lastName = (String)request.getAttribute( "lastName" );
if ( lastName == null ){
lastName = "Not found in request";
}
%>
<b>First Name:</b> <%=firstName%><br>
<b>Last Name:</b> <%=lastName%><br>
</body>
</html>

When you enter the URL for this servlet (http://localhost:8080/servlet/com.oreilly.
struts.chapter2examples.RedirectServlet) in a browser, the
browser output will look like Figure 2-6.


Figure 2-6. The output page when the RedirectServlet is called

Notice that the first name and last name arguments that were set in
the servlet were not found in the request. This is because a second
request actually was issued for this page. Fortunately, we can peek
behind the scenes and observe what's taking place.


The URL parameters username and
password were included in this example just to
illustrate that they are still present after a redirect occurs. You
should never add confidential
information such as passwords to the query string.

Let's look at the HTTP response that comes back to
the client when the RedirectServlet is requested.
We can view the response using a standard Telnet session. An HTTP
connection uses a simple network socket to communicate with the
server, so we can partially simulate the interaction between a
browser and a server using the Telnet application. You can establish
a connection to a web server using Telnet by connecting to the port
on which the server is listening (usually port 80 or, in the case of
Tomcat, 8080):

telnet localhost 8080

You can do this from the command line, whether
you're using a DOS shell or Unix. The Telnet session
will alert you if it's unable to connect to a server
with the specified hostname and port number.

If a connection is established, the Telnet session will sit and wait
for you to enter the HTTP request information. The only information
you are required to enter is the first line of the request, which
tells the server what resource the client wants. Each line in the
request is a text line, separated by a newline character. The request
header ends with a blank line, so you actually have to press Enter
twice to let Telnet know you are done with the request. Figure 2-7 shows the HTTP response message Tomcat returns
when a request is made for the RedirectServlet
resource.


Figure 2-7. Telnet can be used to inspect the HTTP response headers

In Figure 2-7, the first line of the request issues
a GET and a path for a resource. The path is the portion of the HTTP
request that comes after the hostname and includes the preceding
/ character. The HTTP/1.0
string at the end of the GET request is the HTTP version protocol.


HTTP Version 1.1 added a number of optimizations over 1.0. However,
there are additional request headers that must be included in an HTTP
1.1 request, which would make this example more complicated than
necessary. Therefore, 1.0 was used to issue the request.

Everything after the first line is a response from the server. The
entire HTML output at the bottom comes from Tomcat; it indicates that
the original request has performed a redirect and that the client
should request a new URL.

If you look at the Location response header, which
is the third line in Figure 2-7, you can see that
the server has informed the client what the URL for the new request
should be. Any URL parameters attached to the original request will
be present in the new request. When the browser issues the new
request, these parameters will be sent along with it. This technique
of using Telnet provides a simple way of interacting with a web
server and viewing what responses it sends back to the client.

Hopefully, you now have a better understanding of how a redirect
works. It should also be clear why any objects placed into the
original request are not available to the redirected resource. This
will become very important later, when we discuss the Struts
framework.


Notice that in Example 2-1, the redirect string
didn't explicitly contain the hostname and port that
the client needed to use for the new request. It's
the job of the servlet container to translate the relative URL to a
fully qualified URL for transmission back to the client.


2.5.2 Using a Forward


A forward
differs from a redirect in several ways. When you invoke a forward
for a request, the request is sent to another resource on the server,
without the client being informed that a different resource is going
to process the request. This process occurs completely within the web
container, and the client is never the wiser. Unlike with a redirect,
objects can be stored in the request and passed along for the next
resource to use. Figure 2-8 illustrates the steps
that take place when a request is forwarded.


Figure 2-8. When a forward occurs, the client is not notified

Because a forward takes place completely on the server and there is
no communication with the client, the performance is better than with
a redirect. However, there are some differences in how a forward
deals with relative URLs. Example 2-3 should make
this clearer.


Example 2-3. A Java servlet that performs a forward when it receives a request

package com.oreilly.struts.chapter2examples;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.RequestDispatcher;
public class ForwardServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException {
forward(request, response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException {
forward(request, response);
}
/**
* Set a few URL parameters and objects for the request to see what happens
* to them during a redirect.
*/
protected void forward(HttpServletRequest req, HttpServletResponse resp)
throws ServletException,IOException {
log("A request arrived for " + req.getServletPath( ));
String forwardStr = "/result.jsp?username=foo&password=bar";
req.setAttribute("firstName", "John");
req.setAttribute("lastName", "Doe");
log("forwarding to " + forwardStr);
RequestDispatcher dispatcher = req.getRequestDispatcher(forwardStr);
dispatcher.forward(req, resp);
}
}

When the servlet in Example 2-3 receives either a
GET or POST request, it calls the forward()
method and passes the HttpServletRequest and
HttpServletResponse objects to it. As with the
redirect example, two String objects are set into
the request. However, in contrast with the redirect example, the
objects will be available after the forward. Next, the servlet
creates a path to which the request will be passed. A
RequestDispatcher is created, and the
forward() method is invoked on it.
We'll use the same JSP page from Example 2-2. In the browser, we enter a URL such as
http://localhost:8080/servlet/com.oreilly.struts.chapter2examples.ForwardServlet.

The browser output should look similar to Figure 2-9.


Figure 2-9. The output page when the ForwardServlet is called

There are two things to note about Figure 2-9. The
first is that the first and last name fields have values. This is
because the objects were placed into the request before the forward
occurred, and result.jsp was able to retrieve
the values and use them in the page.

The second is the URL in the address bar. Notice that the URL back in
Figure 2-6 showed the new URL, whereas it
didn't change in Figure 2-9. This
shows further that the client is not aware that a forward
occurredthe browser was not notified that a different servlet
handled the request.


The forward(
)
method of the RequestDispatcher class
can be called only when no output has been committed to the client.
Writing something to the response object and then calling
forward() may result in an
IllegalStateException being thrown by the
container.


2.5.3 Which Is Best for Struts?


It's difficult to decree whether Struts applications
should use redirects or forwards, as we haven't
discussed the framework yet. However, there are some key points about
using each approach. Both mechanisms have their pros and cons within
Struts and web applications in general. For many situations, a
forward is recommended over a redirect, because objects that are
stored in the request scope are easily available to the presentation
components. In fact, using a forward is the default for the Struts
framework. Another advantage of forwards is that
they're much more efficient, as the client is not
required to issue a new request.

There are some situations, however, where a redirect is necessary or
preferred over a forward. When forwards are used, the URLs are not
always consistent with the state of the client application. If the
browser's Refresh button is pressed, an incorrect
request may occur. This problem will be explored further in Chapter 5.

If you are using
relative paths for images and other
resources in your JSP pages, forwards can be problematic. Because the
browser has no indication that a forward has occurred, the relative
paths will be relative to the initial servlet, not to the JSP to
which it was forwarded. As you'll see in Chapter 8, the Struts framework provides a JSP custom
tag that can help to alleviate the hassle associated with this
behavior.


    / 181