·
select the proper view to respond to the user.
The
Struts controller delegates most of this grunt work to the Request Processor and Action classes.
In addition to being the front controller for your application, the
ActionServlet instance also is responsible for initialization and clean-up of
resources. When the controller initializes, it first loads the application
config corresponding to the "config" init-param. It then goes through
an enumeration of all
init-param
elements, looking for those elements who's name starts with config/
. For each of these elements, Struts loads the
configuration file specified by the value of that init-param
, and assigns a "prefix" value to that
module's ModuleConfig instance consisting of the piece of the init-param
name following "config/". For example,
the module prefix specified by the init-param config/foo
would be "foo". This is important to
know, since this is how the controller determines which module will be given
control of processing the request. To access the module foo, you would use a
URL like: http://localhost:8080/myApp/foo/someAction.do
For
each request made of the controller, the method
process(HttpServletRequest,
HttpServletResponse)
will be called. This method simply
determines which module should service the request and then invokes that
module's RequestProcessor's process method, passing the same request and
response.
Request
Processor :
The RequestProcessor is where the majority
of the core processing occurs for each request. Let's take a look at the helper
functions the process method invokes in-turn:
processPath |
Determine the path that invoked us. This will be
used later to retrieve an ActionMapping.
|
processLocale |
Select a locale for this request, if one hasn't
already been selected, and place it in the request.
|
processContent |
Set the default content type (with optional
character encoding) for all responses if requested.
|
processNoCache |
If appropriate, set the following response
headers: "Pragma", "Cache-Control", and
"Expires".
|
processPreprocess |
This is one of the "hooks" the
RequestProcessor makes available for subclasses to override. The default
implementation simply returns
true . If you subclass
RequestProcessor and override processPreprocess you should either return true
(indicating process should continue processing the request) or false
(indicating you have handled the request and the process should return) |
processMapping |
Determine the ActionMapping associated with this
path.
|
processRoles |
If the mapping has a role associated with it, ensure
the requesting user is has the specified role. If they do not, raise an error
and stop processing of the request.
|
processActionForm |
Instantiate (if necessary) the ActionForm
associated with this mapping (if any) and place it into the appropriate
scope.
|
processPopulate |
Populate the ActionForm associated with this
request, if any.
|
processValidate |
Perform validation (if requested) on the
ActionForm associated with this request (if any).
|
processForward |
If this mapping represents a forward, forward to
the path specified by the mapping.
|
processInclude |
If this mapping represents an include, include
the result of invoking the path in this request.
|
processActionCreate |
Instantiate an instance of the class specified by
the current ActionMapping (if necessary).
|
processActionPerform |
This is the point at which your action's
perform
or execute method will be called. |
processForwardConfig |
Finally, the process method of the
RequestProcessor takes the ActionForward returned by your Action class, and
uses to select the next resource (if any). Most often the ActionForward leads
to the presentation page that renders the response.
|
Action class
The
Action
class defines two methods that could be executed depending on your servlet
environment:
public ActionForward execute(ActionMapping mapping,
ActionForm form,
ServletRequest request,
ServletResponse response)
throws Exception;
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception;
Since the majority of Struts projects are
focused on building web applications, most projects will only use the
"HttpServletRequest" version. A non-HTTP execute() method has been
provided for applications that are not specifically geared towards the HTTP
protocol.
The
goal of an
Action
class is to process a request, via its execute
method, and return an ActionForward
object that identifies where control should be forwarded (e.g. a JSP, Tile
definition, Velocity template, or another Action) to provide the appropriate
response. In the MVC/Model 2 design pattern, a typical Action
class will often implement logic like the following in its execute
method:
·
Validate
the current state of the user's session (for example, checking that the user
has successfully logged on). If the
Action
class finds that no logon exists, the
request can be forwarded to the presentation page that displays the username
and password prompts for logging on. This could occur because a user tried to
enter an application "in the middle" (say, from a bookmark), or
because the session has timed out, and the servlet container created a new one.
·
If
validation is not complete, validate the form bean properties as needed. If a
problem is found, store the appropriate error message keys as a request
attribute, and forward control back to the input form so that the errors can be
corrected.
·
Perform
the processing required to deal with this request (such as saving a row into a
database). This can
be done by logic code embedded within the
Action
class itself, but should generally be performed by calling
an appropriate method of a business logic bean.
·
Update
the server-side objects that will be used to create the next page of the user
interface (typically request scope or session scope beans, depending on how
long you need to keep these items available).
·
Return
an appropriate
ActionForward
object that identifies the presentation
page to be used to generate this response, based on the newly updated beans.
Typically, you will acquire a reference to such an object by calling findForward
on either the ActionMapping
object you received (if you are using a
logical name local to this mapping), or on the controller servlet itself (if
you are using a logical name global to the application).
In Struts 1.0, Actions called a
perform
method instead of the now-preferred execute
method. These methods use the same parameters and differ only in which
exceptions they throw. The elder perform
method throws SerlvetException
and IOException
.
The new execute
method simply throws Exception
.
The change was to facilitate the Declarative Exception handling feature
introduced in Struts 1.1.
The
perform
method may still be used in Struts 1.1 but is deprecated. The Struts 1.1 method
simply calls the new execute
method and wraps any Exception
thrown as a ServletException
.
Action Form class
An
ActionForm represents an HTML form that the user interacts with over one or
more pages. You will provide properties to hold the state of the form with
getters and setters to access them. ActionForms can be stored in either the
session (default) or request scopes. If they're in the session it's important
to implement the form's
reset
method to initialize the form before each use. Struts sets the ActionForm's
properties from the request parameters and sends the validated form to the
appropriate Action's execute
method.
When
you code your
ActionForm
beans, keep the following principles in mind:
·
The
ActionForm
class itself requires no specific methods
to be implemented. It is used to identify the role these particular beans play
in the overall architecture. Typically, an ActionForm
bean will have only property getter and
property setter methods, with no business logic.
·
The
ActionForm object also offers a standard validation mechanism. If you override
a "stub" method, and provide error messages in the standard
application resource, Struts will automatically validate the input from the
form (using your method). See "Automatic Form Validation" for details. Of course, you can also
ignore the ActionForm validation and provide your own in the Action object.
·
Define a
property (with associated
getXxx
and setXxx
methods) for each field that is present in
the form. The field name and property name must match according to the usual
JavaBeans conventions (see the Javadoc for the java.beans.Introspector
class for a start on information about
this). For example, an input field named username
will cause the setUsername
method to be called.
·
Buttons
and other controls on your form can also be defined as properties. This can
help determine which button or control was selected when the form was
submitted. Remember, the ActionForm is meant to represent your data-entry form,
not just the data beans.
·
Think of
your ActionForm beans as a firewall between HTTP and the Action. Use the
validate
method to ensure all required properties
are present, and that they contain reasonable values. An ActionForm that fails
validation will not even be presented to the Action for handling.
·
You may
also place a bean instance on your form, and use nested property references.
For example, you might have a "customer" bean on your ActionForm, and
then refer to the property "customer.name" in your presentation page.
This would correspond to the methods
customer.getName()
and customer.setName(string
Name)
on your customer
bean. See the Tag Library Developer Guides for more about using nested syntax
with the Struts JSP tags.
·
Caution: If you nest an existing bean instance on
your form, think about the properties it exposes. Any public property on an
ActionForm that accepts a single String value can be set with a query string.
It may be useful to place beans that can affect the business state inside a
thin "wrapper" that exposes only the properties required. This
wrapper can also provide a filter to be sure runtime properties are not set to
inappropriate values.
Action
class Design guidelines
Remember
the following design guidelines when coding
Action
classes:
·
Write code for a multi-threaded environment - The controller servlet creates only one instance of your
Action
class, and uses this one instance to service all
requests. Thus, you need to write thread-safe Action
classes. Follow the same guidelines you
would use to write thread-safe Servlets. Here are two general guidelines that
will help you write scalable, thread-safe Action classes:
o Only Use Local Variables - The most important principle that aids
in thread-safe coding is to use only local variables, not instance variables, in your
Action
class. Local variables are created on a
stack that is assigned (by your JVM) to each request thread, so there is no
need to worry about sharing them. An Action
can be factored into several local
methods, so long as all variables needed are passed as method parameters. This
assures thread safety, as the JVM handles such variables internally using the
call stack which is associated with a single Thread.
o Conserve Resources - As a general rule, allocating scarce
resources and keeping them across requests from the same user (in the user's
session) can cause scalability problems. For example, if your application uses
JDBC and you allocate a separate JDBC connection for every user, you are
probably going to run in some scalability issues when your site suddenly shows
up on Slashdot. You should strive to use pools and release resources (such as
database connections) prior to forwarding control to the appropriate View
component -- even if a bean method you have called throws an exception.
·
Don't throw it, catch it! - Ever used a commercial website only to
have a stack trace or exception thrown in your face after you've already typed
in your credit card number and clicked the purchase button? Let's just say it
doesn't inspire confidence. Now is your chance to deal with these application
errors - in the
Action
class. If your application specific code
throws expections you should catch these exceptions in your Action class, log
them in your application's log (servlet.log("Error
message", exception)
) and
return the appropriate ActionForward.
It is wise to avoid creating lengthy and
complex Action classes. If you start to embed too much logic in the
Action
class itself, you will begin to find the Action
class hard to understand, maintain, and impossible to reuse. Rather than
creating overly complex Action classes, it is generally a good practice to move
most of the persistence, and "business logic" to a separate
application layer. When an Action class becomes lengthy and procedural, it may
be a good time to refactor your application architecture and move some of this
logic to another conceptual layer; otherwise, you may be left with an
inflexible application which can only be accessed in a web-application
environment. Struts should be viewed as simply the foundation for implementing MVC in your applications.
Struts provides you with a useful control layer, but it is not a fully featured
platform for building MVC applications, soup to nuts.
The MailReader example application included
with Struts stretches this design principle somewhat, because the business
logic itself is embedded in the
Action
classes. This should be considered something of a bug in the design of the
example, rather than an intrinsic feature of the Struts architecture, or an
approach to be emulated. In order to demonstrate, in simple terms, the
different ways Struts can be used, the MailReader application does not always
follow best practices.
Action mapping implementation
In order to
operate successfully, the Struts controller servlet needs to know several
things about how each request URI should be mapped to an appropriate
Action
class. The required knowledge has been
encapsulated in a Java class named ActionMapping,
the most important properties are as follows:
o
type
- Fully
qualified Java class name of the Action implementation class used by this
mapping.
o
name
- The name of
the form bean defined in the config file that this action will use.
o
path
- The request
URI path that is matched to select this mapping. See below for examples of how
matching works and how to use wildcards to match multiple request URIs.
o
unknown
- Set to true
if this action should be configured as the default for this application, to
handle all requests not handled by another action. Only one action can be
defined as a default within a single application.
o
validate
- Set to true
if the validate
method of the action associated with this mapping
should be called.
o
forward
- The request
URI path to which control is passed when this mapping is invoked. This is an
alternative to declaring a type
property.
Writing Action Mappings
How does the controller servlet learn about
the mappings you want? It would be possible (but tedious) to write a small Java
class that simply instantiated new
ActionMapping
instances, and called all of the appropriate setter methods. To make this
process easier, Struts uses the Jakarta Commons Digester component to parse an
XML-based description of the desired mappings and create the appropriate
objects initialized to the appropriate default values. See the Jakarta Commons website
for more information about the Digester.
The
developer's responsibility is to create an XML file named
struts-config.xml
and place it in the WEB-INF directory of your application. This format of this
document is described by the Document Type Definition (DTD) maintained at
http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd.
This chapter covers the configuration elements that you will typically write as
part of developing your application. There are several other elements that can
be placed in the struts-config file to customize your application. See "Configuring
Applications" for more about the other elements in
the Struts configuration file.
The controller uses an internal copy of
this document to parse the configuration; an Internet connection is not
required for operation.
The
outermost XML element must be
<struts-config>
.
Inside of the <struts-config> element, there are three important elements
that are used to describe your actions:
·
<form-beans>
·
<global-forwards>
·
<action-mappings>
<form-beans>
This section contains your form bean definitions. Form beans are descriptors that are used to create ActionForm instances at runtime. You use a <form-bean> element for each form bean, which has the following important attributes:
This section contains your form bean definitions. Form beans are descriptors that are used to create ActionForm instances at runtime. You use a <form-bean> element for each form bean, which has the following important attributes:
·
name
: A unique identifier for this bean, which
will be used to reference it in corresponding action mappings. Usually, this is
also the name of the request or session attribute under which this form bean
will be stored.
·
type
: The fully-qualified Java classname of the
ActionForm subclass to use with this form bean.
<global-forwards>
This section contains your global forward definitions. Forwards are instances of the ActionForward class returned from an ActionForm's
This section contains your global forward definitions. Forwards are instances of the ActionForward class returned from an ActionForm's
execute
method. These map logical names to specific resources (typically JSPs),
allowing you to change the resource without changing references to it
throughout your application. You use a <forward>
element for each forward definition, which has the following important
attributes:
·
name
: The logical name for this forward. This
is used in your ActionForm's execute
method to forward to the next appropriate
resource. Example: homepage
·
path
: The context relative path to the
resource. Example: /index.jsp or /index.do
·
redirect
: True
or false
(default). Should the ActionServlet
redirect to the resource instead of forward?
<action-mappings>
This section contains your action definitions. You use an
This section contains your action definitions. You use an
<action>
element for each of the mappings you would like to define. Most action elements
will define at least the following attributes:
·
path
: The application context-relative path to
the action.
·
type
: The fully qualified java classname of
your Action class.
·
name
: The name of your <form-bean>
element to use with this action
Other
often-used attributes include:
·
parameter
: A general-purpose attribute often used by
"standard" Actions to pass a required property.
·
roles
: A comma-delimited list of the user
security roles that can access this mapping.
For a complete description of the elements that can be used with the
action
element, see the Struts Configuration DTD
and the ActionMapping
documentation.
Action Mapping Example
Here's
a mapping entry based on the MailReader example application. The MailReader
application now uses DynaActionForms. But in this example, we'll show a
conventinal ActionForm instead, to illustrate the usual workflow. Note that the
entries for all the other actions are left out:
<struts-config>
<form-beans>
<form-bean
name="logonForm"
type="org.apache.struts.webapp.example.LogonForm" />
</form-beans>
<global-forwards
type="org.apache.struts.action.ActionForward">
<forward
name="logon"
path="/logon.jsp"
redirect="false" />
</global-forwards>
<action-mappings>
<action
path ="/logon"
type ="org.apache.struts.webapp.example.LogonAction"
name ="logonForm"
scope ="request"
input ="/logon.jsp"
unknown="false"
validate="true" />
</action-mappings>
</struts-config>
First
the form bean is defined. A basic bean of class "
org.apache.struts.webapp.example.LogonForm
" is mapped to the logical name "logonForm
". This name is used as a request attribute
name for the form bean.
The
"
global-forwards
" section
is used to create logical name mappings for commonly used presentation pages.
Each of these forwards is available through a call to your action mapping
instance, i.e. mapping.findForward("logicalName")
.
As you
can see, this mapping matches the path
/logon
(actually, because the MailReader example application uses extension mapping,
the request URI you specify in a JSP page would end in /logon.do
). When a request that matches this path is
received, an instance of the LogonAction
class will be created (the first time only) and used. The controller servlet
will look for a bean in request scope under key logonForm
, creating and saving a bean of the specified class
if needed.
Optional but very useful are the local "
forward
" elements. In the MailReader example
application, many actions include a local "success" and/or
"failure" forward as part of an action mapping. <!-- Edit mail subscription -->
<action
path="/editSubscription"
type="org.apache.struts.webapp.example.EditSubscriptionAction"
name="subscriptionForm"
scope="request"
validate="false">
<forward
name="failure"
path="/mainMenu.jsp"/>
<forward
name="success"
path="/subscription.jsp"/>
</action>
Using
just these two extra properties, the Action classes are almost totally
independent of the actual names of the presentation pages. The pages can be
renamed (for example) during a redesign, with negligible impact on the Action
classes themselves. If the names of the "next" pages were hard coded
into the Action classes, all of these classes would also need to be modified.
Of course, you can define whatever local
forward
properties makes sense for your own application.
The Struts configuration file includes several
other elements that you can use to customize your application. See "Configuring Applications"
for details.
Using Action Mapping for pages
Fronting your pages with ActionMappings is essential when using modules,
since doing so is the only way you involve the controller in the request -- and
you want to! The controller puts the application configuration in the request,
which makes available all of your module-specific configuration data (including
which message resources you are using, request-processor, datasources, and so
forth).
The simplest way to do this is to use the
forward
property of the ActionMapping: <action path="/view" forward="/view.jsp"/>
Configuring struts-config.xml file
The Building
Controller Components chapter covered writing the form-bean and
action-mapping portions of the Struts configuration file. These elements
usually play an important role in the development of a Struts application. The
other elements in Struts configuration file tend to be static: you set them
once and leave them alone.
These
"static" configuration elements are:
·
controller
·
message-resources
·
plug-in
·
data-sources
Controller configuration
The
<controller>
element allows you to configure the ActionServlet. Many of the controller
parameters were previously defined by servlet initialization parameters in your
web.xml
file but have been moved to this section of struts-config.xml
in order to allow different modules in the same web application to be
configured differently. For full details on available parameters see the struts-config_1_2.dtd
or the list below.
·
bufferSize
- The size (in bytes) of the input buffer used when processing file uploads.
[4096] (optional)
·
className
- Classname of configuration bean. [org.apache.struts.config.ControllerConfig]
(optional)
·
contentType
- Default content type (and optional character encoding) to be set on each
response. May be overridden by the Action, JSP, or other resource to which the
request is forwarded. [text/html] (optional)
·
forwardPattern
- Replacement pattern defining how the "path" attribute of a
<forward>
element is mapped to a context-relative URL
when it starts with a slash (and when the contextRelative
property is false
).
This value may consist of any combination of the following:
o
$M - Replaced by the module prefix of this
module.
o
$P - Replaced by the "path"
attribute of the selected
<forward>
element.
o
$$ - Causes a literal dollar sign to be
rendered.
o
$x - (Where "x" is any character
not defined above) Silently swallowed, reserved for future use.
If not
specified, the default forwardPattern is consistent with the previous behavior
of forwards. [$M$P] (optional)
·
inputForward
- Set to
true
if you want the input
attribute of <action>
elements to be the name of a local or
global ActionForward
, which will then be used to calculate the
ultimate URL. Set to false
to treat the input
parameter of <action>
elements as a module-relative path to the
resource to be used as the input form. [false] (optional)
·
locale
- Set to
true
if you want a Locale
object stored in the user's session if not
already present. [true] (optional)
·
maxFileSize
- The maximum size (in bytes) of a file to be accepted as a file upload. Can be
expressed as a number followed by a "K", "M", or
"G", which are interpreted to mean kilobytes, megabytes, or
gigabytes, respectively. [250M] (optional)
·
multipartClass
- The fully qualified Java class name of the multipart request handler class to
be used with this module.
[org.apache.struts.upload.CommonsMultipartRequestHandler] (optional)
·
nocache
- Set to
true
if you want the controller to add HTTP
headers for defeating caching to every response from this module. [false]
(optional)
·
pagePattern
- Replacement pattern defining how the
page
attribute of custom tags using it is
mapped to a context-relative URL of the corresponding resource. This value may
consist of any combination of the following:
o
$M - Replaced by the module prefix of this
module.
o
$P - Replaced by the "path"
attribute of the selected
<forward>
element.
o
$$ - Causes a literal dollar sign to be
rendered.
o
$x - (Where "x" is any character
not defined above) Silently swallowed, reserved for future use.
If not specified, the default pagePattern
is consistent with the previous behavior of URL calculation. [$M$P] (optional)
·
processorClass
- The fully qualified Java class name of the
RequestProcessor
subclass to be used with this module.
[org.apache.struts.action.RequestProcessor] (optional)
·
tempDir
- Temporary working directory to use when processing file uploads. [{the
directory provided by the servlet container}]
This
example uses the default values for several controller parameters. If you only
want default behavior you can omit the controller section altogether.
<controller
processorClass="org.apache.struts.action.RequestProcessor"
debug="0"
contentType="text/html"/>;
Message Resource configuration
Struts
has built in support for internationalization (I18N). You can define one or
more
<message-resources>
elements for your webapp; modules can define their own resource bundles.
Different bundles can be used simultaneously in your application, the 'key'
attribute is used to specify the desired bundle.
·
className
- Classname of configuration bean.
[org.apache.struts.config.MessageResourcesConfig] (optional)
·
factory
- Classname of MessageResourcesFactory. [org.apache.struts.util.PropertyMessageResourcesFactory]
(optional)
·
key -
ServletContext attribute key to store this bundle.
[org.apache.struts.action.MESSAGE] (optional)
·
null
- Set to
false
to display missing resource keys in your
application like '???keyname???'
instead of null
. [true] (optional)
·
parameter
- Name of the resource bundle. (required)
Example
configuration:
<message-resources
parameter="MyWebAppResources"
null="false" />
This
would set up a message resource bundle provided in the file
MyWebAppResources.properties
under the default key. Missing resource keys would be displayed as '???keyname???'.
PlugIn configuration
Struts
PlugIns are configured using the
<plug-in>
element within the Struts configuration file. This element has only one valid
attribute, 'className', which is the fully qualified name of the Java class
which implements the org.apache.struts.action.PlugIn
interface.
For
PlugIns that require configuration themselves, the nested
<set-property>
element is available.
This
is an example using the Tiles plugin:
<plug-in className="org.apache.struts.tiles.TilesPlugin" >
<set-property
property="definitions-config"
value="/WEB-INF/tiles-defs.xml"/>
</plug-in>
DataSource configuration
Besides the objects related to defining
ActionMappings, the Struts configuration may contain elements that create other
useful objects.
The
<data-sources>
section can be used to specify a collection of
DataSources [javax.sql.DataSource] for the use of your application. Typically,
a DataSource represents a connection pool to a database or other persistent
store. As a convenience, the Struts DataSource manager can be used to
instantiate whatever standard pool your application may need. Of course, if
your persistence layer provides for its own connections, then you do not need
to specify a data-sources
element.
Since DataSource implementations vary in what properties
need to be set, unlike other Struts configuration elements, the
data-source
element does not pre-define a slate of properties.
Instead, the generic set-property
feature is used to set whatever properties your implementation may require.
Typically, these settings would include:
·
A driver class name
·
A url to access the driver
·
A description
And other sundry properties.
<data-source type="org.apache.commons.dbcp.BasicDataSource">
<!-- ... set-property elements ... -->
</data-source>
In
Struts 1.2.0, the GenericDataSource has been removed, and it is recommended
that you use the Commons BasicDataSource or other DataSource implementation
instead. In practice, if you need to use the DataSource manager, you should use
whatever DataSource implementation works best with your container or database.
For examples of specifying a data-sources element
and using the DataSource with an Action,
The Struts configuration file
The Building Controller Components
chapter covered writing the form-bean and action-mapping portions of the Struts
configuration file. These elements usually play an important role in the
development of a Struts application. The other elements in Struts configuration
file tend to be static: you set them once and leave them alone.
These "static" configuration elements
are:
·
controller
·
message-resources
·
plug-in
·
data-sources
Controller
Configuration
The
<controller>
element allows you to configure the ActionServlet.
Many of the controller parameters were previously defined by servlet
initialization parameters in your web.xml
file but have been moved to this section of struts-config.xml
in order to allow different modules in the same
web application to be configured differently. For full details on available
parameters see the struts-config_1_2.dtd or the list below.
·
bufferSize - The size (in bytes) of the input buffer used
when processing file uploads. [4096] (optional)
·
className - Classname of configuration bean.
[org.apache.struts.config.ControllerConfig] (optional)
·
contentType - Default content type (and optional character
encoding) to be set on each response. May be overridden by the Action, JSP, or
other resource to which the request is forwarded. [text/html] (optional)
·
forwardPattern - Replacement pattern defining how the "path"
attribute of a
<forward>
element is mapped to
a context-relative URL when it starts with a slash (and when the contextRelative
property is false
). This value may consist of any combination of the
following:
o
$M - Replaced by the module prefix of this module.
o
$P - Replaced by the "path" attribute of
the selected
<forward>
element.
o
$$ - Causes a literal dollar sign to be rendered.
o
$x - (Where "x" is any character not
defined above) Silently swallowed, reserved for future use.
If not
specified, the default forwardPattern is consistent with the previous behavior
of forwards. [$M$P] (optional)
·
inputForward - Set to
true
if you want the input
attribute of <action>
elements to be the name of a local or
global ActionForward
, which will then be used to calculate the
ultimate URL. Set to false
to treat the input
parameter of <action>
elements as a module-relative path to the
resource to be used as the input form. [false] (optional)
·
locale - Set to
true
if you want a Locale
object stored in the user's session if not already present. [true] (optional)
·
maxFileSize - The maximum size (in bytes) of a file to be
accepted as a file upload. Can be expressed as a number followed by a
"K", "M", or "G", which are interpreted to mean
kilobytes, megabytes, or gigabytes, respectively. [250M] (optional)
·
multipartClass - The fully qualified Java class name of the
multipart request handler class to be used with this module.
[org.apache.struts.upload.CommonsMultipartRequestHandler] (optional)
·
nocache - Set to
true
if you want the controller to
add HTTP headers for defeating caching to every response from this module.
[false] (optional)
·
pagePattern - Replacement pattern defining how the
page
attribute of custom tags using it is mapped to a context-relative URL of the
corresponding resource. This value may consist of any combination of the
following:
o
$M - Replaced by the module prefix of this module.
o
$P - Replaced by the "path" attribute of the
selected
<forward>
element.
o
$$ - Causes a literal dollar sign to be rendered.
o
$x - (Where "x" is any character not
defined above) Silently swallowed, reserved for future use.
If not
specified, the default pagePattern is consistent with the previous behavior of
URL calculation. [$M$P] (optional)
·
processorClass - The fully qualified Java class name of the
RequestProcessor
subclass to be used with this module.
[org.apache.struts.action.RequestProcessor] (optional)
·
tempDir - Temporary working directory to use when
processing file uploads. [{the directory provided by the servlet container}]
This
example uses the default values for several controller parameters. If you only
want default behavior you can omit the controller section altogether.
<controller
processorClass="org.apache.struts.action.RequestProcessor"
debug="0"
contentType="text/html"/>;
Message
Resources Configuration
Struts has built in support for internationalization (I18N). You can
define one or more
<message-resources>
elements for your webapp; modules can define their
own resource bundles. Different bundles can be used simultaneously in your
application, the 'key' attribute is used to specify the desired bundle.
·
className - Classname of configuration bean.
[org.apache.struts.config.MessageResourcesConfig] (optional)
·
factory - Classname of MessageResourcesFactory.
[org.apache.struts.util.PropertyMessageResourcesFactory] (optional)
·
key - ServletContext attribute key to store this
bundle. [org.apache.struts.action.MESSAGE] (optional)
·
null - Set to
false
to display missing resource
keys in your application like '???keyname???' instead of null
.
[true] (optional)
·
parameter - Name of the resource bundle. (required)
Example configuration:
<message-resources parameter="MyWebAppResources" null="false" />
This would set up a message resource bundle
provided in the file
MyWebAppResources.properties
under the default key.
Missing resource keys would be displayed as '???keyname???'.
PlugIn
Configuration
Struts PlugIns are configured using the
<plug-in>
element within the Struts configuration file. This
element has only one valid attribute, 'className', which is the fully qualified
name of the Java class which implements the org.apache.struts.action.PlugIn
interface.
For PlugIns that require configuration themselves,
the nested
<set-property>
element is available.
This is an example using the Tiles plugin:
<plug-in className="org.apache.struts.tiles.TilesPlugin" >
<set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml"/>
</plug-in>
Data Source
Configuration
Besides the objects related to defining
ActionMappings, the Struts configuration may contain elements that create other
useful objects.
The
<data-sources>
section can be used to specify a collection of
DataSources [javax.sql.DataSource] for the use of your application. Typically,
a DataSource represents a connection pool to a database or other persistent
store. As a convenience, the Struts DataSource manager can be used to
instantiate whatever standard pool your application may need. Of course, if
your persistence layer provides for its own connections, then you do not need
to specify a data-sources
element.
Since DataSource implementations vary in what properties
need to be set, unlike other Struts configuration elements, the
data-source
element does not pre-define a slate of properties.
Instead, the generic set-property
feature is used to set whatever properties your implementation may require.
Typically, these settings would include:
·
A driver class name
·
A url to access the driver
·
A description
And other sundry properties.
<data-source type="org.apache.commons.dbcp.BasicDataSource">
<!-- ... set-property elements ... -->
</data-source>
In
Struts 1.2.0, the GenericDataSource has been removed, and it is recommended
that you use the Commons BasicDataSource or other DataSource implementation
instead. In practice, if you need to use the DataSource manager, you should use
whatever DataSource implementation works best with your container or database.
For examples of specifying a data-sources element
and using the DataSource with an Action, see the Accessing a
Database HowTo.
Configuring
your application for modules
Very little is required in order to start taking
advantage of the Struts module feature. Just go through the following steps:
1.
Prepare a config file for each module.
2.
Inform the controller of your module.
3.
Use actions to refer to your pages.
Module
Configuration Files
Back in Struts 1.0, a few "boot-strap"
options were placed in the web.xml file, and the bulk of the configuration was
done in a single struts-config.xml file. Obviously, this wasn't ideal for a
team environment, since multiple users had to share the same configuration
file.
In
Struts 1.1, you have two options: you can list multiple struts-config files
as a comma-delimited list, or you can subdivide a larger application into
modules.
With the advent of modules, a given module has its
own configuration file. This means each team (each module would presumably be
developed by a single team) has their own configuration file, and there should
be a lot less contention when trying to modify it.
Informing the
Controller
In
struts 1.0, you listed your configuration file as an initialization parameter
to the action servlet in web.xml. This is still done in 1.1, but it's augmented
a little. In order to tell the Struts machinery about your different modules,
you specify multiple config initialization parameters, with a slight twist.
You'll still use "config" to tell the action servlet about your
"default" module, however, for each additional module, you will list
an initialization parameter named "config/module", where module is
the name of your module (this gets used when determining which URIs fall under
a given module, so choose something meaningful!). For example:
...
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/conf/struts-default.xml</param-value>
</init-param>
<init-param>
<param-name>config/module1</param-name>
<param-value>/WEB-INF/conf/struts-module1.xml</param-value>
</init-param>
...
This
says I have two modules. One happens to be the "default" module,
which has no "/module" in it's name, and one named
"module1" (config/module1). I've told the controller it can find
their respective configurations under /WEB-INF/conf (which is where I put all
my configuration files). Pretty simple!
(My struts-default.xml would be equivalent to what
most folks call struts-config.xml. I just like the symmetry of having all my
Struts module files being named struts-<module>.xml)
If you'd like to vary where the pages for each
module is stored, see the forwardPattern setting for the
Controller.
Switching
Modules
There
are two basic methods to switching from one module to another. You can either
use a forward (global or local) and specify the contextRelative attribute with
a value of true, or you can use the built-in
org.apache.struts.actions.SwitchAction
.
Here's an example of a global forward:
...
<struts-config>
...
<global-forwards>
<forward name="toModuleB"
contextRelative="true"
path="/moduleB/index.do"
redirect="true"/>
...
</global-forwards>
...
</struts-config>
You could do the same thing with a local forward
declared in an ActionMapping:
...
<struts-config>
...
<action-mappings>
...
<action ... >
<forward name="success"
contextRelative="true"
path="/moduleB/index.do"
redirect="true"/>
</action>
...
</action-mappings>
...
</struts-config>
Finally, you could use
org.apache.struts.actions.SwitchAction
, like so:...
<action-mappings>
<action path="/toModule"
type="org.apache.struts.actions.SwitchAction"/>
...
</action-mappings>
...
Now, to
change to ModuleB, we would use a URI like this:
http://localhost:8080/toModule.do?prefix=/moduleB&page=/index.do
If you are using the "default" module as
well as "named" modules (like "/moduleB"), you can switch
back to the "default" module with a URI like this:
http://localhost:8080/toModule.do?prefix=&page=/index.do
That's all there is to it! Happy module-switching!
The Web
Application Deployment Descriptor
The
final step in setting up the application is to configure the application
deployment descriptor (stored in file
WEB-INF/web.xml
) to include all the Struts components that are
required. Using the deployment descriptor for the example application as a
guide, we see that the following entries need to be created or modified.
Configure the
Action Servlet Instance
Add an
entry defining the action servlet itself, along with the appropriate
initialization parameters. Such an entry might look like this:
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>
org.apache.struts.action.ActionServlet
</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>
/WEB-INF/struts-config.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
The
initialization parameters supported by the controller servlet are described
below. (You can also find these details in the Javadocs for the ActionServlet class.) Square brackets
describe the default values that are assumed if you do not provide a value for
that initialization parameter.
·
config - Context-relative path to the XML resource
containing the configuration information for the default module. This may also
be a comma-delimited list of configuration files. Each file is loaded in turn,
and its objects are appended to the internal
data structure.
[/WEB-INF/struts-config.xml].
WARNING - If you define an object of the same name in more than one configuration file, the last one loaded quietly wins.
WARNING - If you define an object of the same name in more than one configuration file, the last one loaded quietly wins.
·
config/${module} - Context-relative path to the XML resource
containing the configuration information for the application module that will
use the specified prefix (/${module}). This can be repeated as many times as
required for multiple application modules. (Since Struts 1.1)
·
convertNull - Force simulation of the Struts 1.0 behavior when
populating forms. If set to true, the numeric Java wrapper class types (like
java.lang.Integer
)
will default to null (rather than 0). (Since Struts 1.1) [false]
·
rulesets - Comma-delimited list of fully qualified
classnames of additional
org.apache.commons.digester.RuleSet
instances that should be added to the Digester
that will be processing struts-config.xml
files. By default, only the RuleSet
for the standard
configuration elements is loaded. (Since Struts 1.1)
·
validating - Should we use a validating XML parser to process
the configuration file (strongly recommended)? [true]
WARNING - Struts will
not operate correctly if you define more than one
<servlet>
element for a controller servlet, or a subclass of
the standard controller servlet class. The controller servlet MUST be a web
application wide singleton.
Configure the
Action Servlet Mapping
Note: The material in
this section is not specific to Struts. The configuration of servlet mappings
is defined in the Java Servlet Specification. This section describes the most
common means of configuring a Struts application.
There are two common approaches to defining the
URLs that will be processed by the controller servlet -- prefix matching and
extension matching. An appropriate mapping entry for each approach will be
described below.
Prefix matching means that you want all URLs that
start (after the context path part) with a particular value to be passed to
this servlet. Such an entry might look like this:
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>/do/*</url-pattern>
</servlet-mapping>
which means that a request URI to match the
/logon
path described earlier might look like this:
No comments:
Post a Comment