4. Protect JSPs Behind WEB-INF
To better protect your JavaServer Pages from unauthorized access or viewing, it's a good
idea to store your pages in a directory that is below the Web application's
It's very typical for JSP developers to keep their pages in subdirectories under the Web application root. For example, Figure 2 shows a typical directory structure for a storefront application. The JSPs relating to catalog are placed in the catalog subdirectory under the storefront directory. The same might be true for the customer JSPs, order JSPs, and so on.
Figure 2. JSPs are placed into separate directories based on functionality.
The problem with this approach is that these pages are a little more susceptible to a user being able to view the source of the JSPs, or at least call the JSP directly. In some cases, this might not be a huge issue, but under certain circumstances it can be a security risk. It could also present a problem if users are allowed to circumvent the Struts controller by invoking a JSP directly.
To reduce this risk, you can move the pages into a directory underneath
on the Servlet specification,
WEB-INF is not part of the public document tree of the
Web application. Therefore, no resource within the
WEB-INF directory (nor those
beneath it) may be served directly to a client. We can still use JSPs stored underneath the
WEB-INF to render views for a client; however, a client may not request one of the JSPs
directly. This helps to protect your site from unwanted access and at the same time,
allows you to render views using JSPs.
Using the previous example, the directory would like the one in Figure 3, after the JSPs
are moved into a directory called JSP underneath the
Figure 3. The JSPs are more secure underneath the WEB-INF directory.
Once the JSPs are located underneath the
WEB-INF directory, you must use "WEB-INF" as part of the URL when referencing the pages. For example, suppose we had an Action
mapping in our Struts configuration file for a
logoff action. The paths to JSPs must
WEB-INF at the beginning.
<action path="/logoff" type="org.apache.struts.webapp.example.LogoffAction"> <forward name="success" path="/WEB-INF/jsp/index.jsp"/> </action>
The only trick with using this approach, which is good practice with Struts in any case, is that you should always front your JSPs with a Struts action. Even if the Action is a very basic JSP, you should always call an Action that in turn invokes the JSP.
A final comment when storing your JSPs underneath
WEB-INF: not all containers
support this feature. Earlier versions of WebLogic did not interpret the Servlet
specification the same as others, and it was not possible to do this. This is reported to be
changed with newer versions of WebLogic. Just be sure to check your specific container.
5. Use the Prebuilt Actions
The Struts framework comes with several prebuilt Action classes that can save a
tremendous amount of development time. The most beneficial of these are the
org.apache.struts.actions.ForwardAction and the
There are probably many cases in your application where you want an Action to just
forward to a JSP. In fact, the previous tip stated that it's good practice to always front a
JSP with an Action. If you have the case where you don't need to perform any logic in
the Action but would like to follow the convention of going through an Action to access a
ForwardAction can save you from creating many empty Action classes. The
benefit of the
ForwardAction is that you don't have to create an Action class of your
own. All you have to do is to declaratively configure an Action mapping in your Struts
For example, suppose that you had a JSP called index.jsp and instead of calling this page directly, you would rather have the application go through an Action class. What you can do is set up an Action mapping like this:
<action path="/home" parameter="/index.jsp" type="org.apache.struts.actions.ForwardAction" scope="request" validate="false"> </action>
home action is invoked, the
ForwardAction performs a forward to the index.jsp page.
While we are discussing forwarding without having to provide an Action class, it should
also be mentioned that you could also use the forward attribute of the
<action> element to achieve the same behavior. The
<action> element would look like this:
<action path="/home" forward="/index.jsp"> </action>
Both approaches save you time and help to reduce the number of files needed by an application.
DispatchAction is another Action that is included with the framework that saves a
tremendous amount of development time. Instead of providing a single
per Action class (and thus tying one Action to one business method), the
allows you to encode several business-related methods within a single Action class. By
doing this, the number of Action classes can be reduced and the related business methods
can be grouped together, which can make maintenance somewhat easier.
To use the
DispatchAction functionality, you need to create a class that extends the
DispatchAction. For each business method that you want to provide, you need to
provide a method with a particular method signature. If for example, you had a method
that you wanted to call to add items to the user's shopping cart, we could create a class
ShoppingCartDispatchAction that had the following method:
public ActionForward addItem( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception;
This class would probably also have a
deleteItem() method, a
clearCart() method, and others. So instead of creating different Action classes for each of these, we can combine
them into a single Action class.
To invoke one of the methods in the
ShoppingCartDispatchAction, just include a
parameter in the URL that matches one of the method names. So, to invoke the
method, the URL would look something like:
The parameter named
method identifies the method to invoke within the
ShoppingCartDispatchAction. The name of the parameter can be configured to be just
about anything you want. The one used here, "
method," is just an example. You
configure it within the Struts configuration file.