| This Chapter | |
| - | Chapter 22: How Struts Works |
| - | The Action Servlet |
| - | Creating A ModuleConfig Object |
| - | The Request Processor |
| - | Summary |
The action servlet is represented by the org.apache.struts.action.ActionServlet class, a subclass of javax.servlet.http.HttpServlet. A servlet has three lifecycle methods that get called by the servlet container.
In handling an action, the action servlet may create an action form and an action object, forward control to a JSP, etc. The information about the type of the action form, the type of the action object, and the forward destination can be found in the Struts configuration file (by default, the struts-config.xml file). Therefore, the action servlet needs to read this XML document.
However, parsing this file for each action invocation would be inefficient. Therefore, the Struts designer created a ModuleConfig object (of type org.apache.struts.action.ModuleConfig interface) that encapsulates configuration information. The ModuleConfig object is created when the action servlet is initialized and is stored in the ServletContext object. As such, a ModuleConfig object lives until the action servlet is destroyed and is available from inside the servlet’s service method. This strategy results in a more efficient system because a Struts configuration file is only parsed once. Most Struts applications have one configuration file, hence one ModuleConfig object. However, larger applications may have many configuration files, in which case each file has a corresponding ModuleConfig instance. When storing a ModuleConfig object in the ServletContext object, the action servlet uses the following attribute key:
Globals.MODULE_KEY + prefix
Where Globals.MODULE_KEY is the value of the MODULE_KEY field of the org.apache.struts.Globals class and prefix is the module’s prefix. Consequently, you can store as many ModuleConfig objects as you wish as long as each ModuleConfig object has a unique prefix.
Each Struts action handling starts by obtaining the appropriate ModuleConfig object from a factory object and passing it to the RequestProcessor object that handles the processing. Figure 22.1 depicts the relationship between the three very important types in Struts, ActionServlet, RequestProcessor, and ModuleConfig.
Figure 22.1: The relationship between ActionServlet, RequestProcessor, and ModuleConfig
For each request processing, that is when the servlet’s service method is invoked, the servlet does the following:
The three operations are depicted in the doGet and doPost method of the action servlet in Listing 22.1:
Listing 22.1: The action servlet’s doGet and doPost methods
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
process(request, response);
}
public void doPost(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
process(request, response);
}
protected void process(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
//1. Looks up the correct ModuleConfig object
ModuleUtils.getInstance().selectModule(request,
getServletContext());
ModuleConfig config = getModuleConfig(request);
//2. Get a RequestProcessor, passing the ModuleConfig
RequestProcessor processor = getProcessorForModule(config);
if (processor == null) {
processor = getRequestProcessor(config);
}
//3. Invoke the request processor’s process method.
processor.process(request, response);
}
The ModuleConfig interface provides methods for obtaining the action form type, the fully qualified name of the action class, the forward destination, and other configuration settings for completing the handling of any Struts action. Since the request processor has a reference to the ModuleConfig object, the request processor knows how to correctly create the action form and the action object for a Struts action invocation.
The ModuleConfig interface is given discussed in the following section.