How to expand Struts in project practice

xiaoxiao2021-03-06  22

I saw a lot of projects, developers realized their own MVC frameworks, not because they want to do different things with Struts, but because they didn't realize how to extend Struts. Developing your own MVC framework can get all controls, but this also means that many resources are needed to achieve it (human material), in tense schedule, sometimes it is impossible.

Struts is more than just a powerful framework, but it is also scalable. You can extend Struts in three ways.

1, Plugin: If you want to do some business logic during Application Startup or ShutDown, create your own Plugin class.

2, RequestProcessor: If you want to do some business logic in the process of being processed, create your own RequestProcessor class. For example, before each request is executed, you can extend the requestProcessor to check if the user logs in and whether he has permission to perform a particular action.

3, ActionServlet: If you want to do some business logic when you apply when Application Startup and ShutDown, you can also expand an ActionServlet class. However, you should use the ActionServlet when Plugin and RequestProcessor don't solve your needs.

In this article, we will use an example of a Struts application to demonstrate how to use these three ways to expand Struts. The code for the sample program can be downloaded from http://www.onjava.com/onjava/2004/11/examples/sample1.zip. Two extensions Struts successful examples are the Validation and Tiles frameworks of Struts themselves.

We assume that you are more familiar with the struts framework and know how to use it to create a simple application. If you want to know more about Struts, please refer to the official homepage.

Plugin

Plugin is an interface that you can create a class that implements the interface, when Application Startup or Shutdown is something.

For example, I created a web application using Hibernate as a persistent layer. I want to initialize Hibernate when I am started. So when I am a first request, Hibernate is already configured and usable. At the same time, we want to close hibernate when Application is closed. We can use a hibernate plugin to achieve this demand, through the following two steps:

1. Create a class to implement the Plugin interface:

Public class hibernatePlugin implements plugin {

PRIVATE STRING CONFIGFILE;

// this Method Will Be Called At Application SHUTDOWN TIME

Public void destroy () {

System.out.println ("Entering HibernatePlugin.DESTROY ()");

// Put Hibernate Cleanup Code Here

System.out.println ("exiting hibernateplugin.destroy ()");

}

// this Method Will Be Called AT Application Startup Time

Public void init (ActionServlet ActionServlet, ModuleConfig Config)

Throws servletexception {

System.out.println ("Entering HibernatePlugin.init ()"); System.out.Println ("Value of Init Parameter"

GetConfigfile ());

System.out.println ("EXITING HibernatePlugin.init ()");

}

Public string getconfigfile () {

Return Name;

}

Public void setconfigfile (String String) {

Configfile = String;

}

}

Two methods must be completed by implementing the class of the PLUGIN interface: init () and destroy (). When the application startup is called, the destroy () method is called when Shutdown is called. Struts also allows you to transfer initialization parameters to your PLUGIN class. In order to pass parameters, you must create a JavaBean setter method for each parameter in the Plugin class. In our hibernatePlugin class, I will pass the CONFIGFILE's Name as the parameters, not the hardcoded to the program.

2, add the following code to Struts-Config.xml to advertise Struts has new Plugin:

...

Attribute classname is a list of fully qualified names that implement the Plugin interface. For each initialization parameter, you can transfer parameters using the element. In our example, I want to pass the name of the config file, so use a with the configuration file path.

The Struts Tiles and Validator frameworks use Plugin to read the configuration file for initialization. The other two Plugin can help you do what you do is:

· If your Application relies on some configuration files, you can check if they are available in the plugin class, if you are not available, throw an ActionServlet to be unavailable.

• The init () method of the Plugin interface is that you can change the last chance of ModuleConfig, and ModuleConfig is a set of static configuration information to describe the Struts module. Struts will release ModuleConfig after all PLUGIN processing.

How is processed

The ActionServlet is the only servlet in the Struts framework, which is responsible for processing all request. Whenever you receive a request, it will try to find a sub-application for the current request. Once a Sub-Application is found, the ActionServlet creates a requestProcessor object for that sub-application, calls the Process () method of this object and incorporates the HttpServletRequest and HttpservletResponse objects. RequestProcessor.Process () is where most Request is processed. The Process () method uses the Template Method mode implementation, where there are many independent methods to perform each step of request processing, which will be called in turn in the Process method. For example, there will be an independent method to find the ActionForm class corresponding to the current Request, one way to check if the current user has permission to perform an action mapping. These give us great flexibility. A RequestProcessor class is provided in the release Struts package provides the request to process the default implementation of each step. This means you can only rewrite the way you are interested in, others use the default implementation. For example, by default Struts calls request.isuserinrole () to check if the user has permission to execute current actionMApping; if you want to implement the database, you have to do it is to rewrite the processroles () method, by querying The user has a must-have necessary permissions to return True or False.

First we will see how the process () method is implemented by default, then I will explain every method in the default RequestProcessor class so that you can decide which part is what you want to change.

Public Void Process (httpservletRequest Request, HttpservletResponse Response)

THROWS IOException, servletexception {

// Wrap Multipart Requests with a special wrapper

Request = processmultiple (request);

// Identify The Path Component We Will

// use to select a mapping

String path = processpath (request, response);

IF (PATH == NULL) {

Return;

}

IF (log.Indebugeload ()) {

Log.debug ("Processing A '" Request.getMethod () "' for Path '" PATH "");

}

// select a logale for the current user if requested

ProcessLocale (Request, Response);

// set the content type and no-caching headers

// if Requester

ProcessContent (Request, Response);

Processnocache (Request, Response);

// General Purpose Preprocessing Hook

IF (! ProcessPreProcess (Request, Response)) {

Return;

}

// Identify the mapping for this Request

ActionMApping mapping =

Processmapping (Request, Response, Path);

IF (mapping == NULL) {

Return;

}

// Check for any role Required to Perform this Action

IF (! ProcessRoles (Request, Response, Mapping) {

Return;

}

// process Any Actionform Bean Related to this request

Actionform Form = ProcessActionform (Request, Response, Mapping);

ProcessPopulate (Request, Response, Form, Mapping);

IF (! ProcessValidate (Request, Response, Form, Mapping) {

Return;

}

// process a forward or include specified by this mapping

IF (! ProcessForward (Request, Response, Mapping) {

Return;

}

IF (! process, response (mapping) {

Return;

}

// Create or acquire the action instance to

// Process this Request

Action action =

ProcessActionCreate (Request, Response, Mapping);

IF (action == null) {

Return;

}

// Call the action instance itself

ActionForward Forward = ProcessActionPerform (Request, Response, Action, Form, Mapping);

// process the returned actionforward instance

ProcessForwardConfig (Request, Response, Forward);

}

1, ProcessMutipart (): In this method, Struts will read the request to check if the recuestType is Multipart / Form-Data. If so, the request will be parsed and packaged into the httpservletRequest. When you create an HTML Form to submit the data, the Request's ContentType default is Application / X-WWW-form-Urlencoded. But if your Form uses the file type INPUT control allows the user to upload files, you must change ContentType to Multipart / Form-Data. If this is the case, you cannot get the data submitted by getParameter (); you must read the request as an InputStream and parsing it to get the parameter value.

2, ProcessPath (): In this method, Struts will read the REQUEST URI to determine the path element, which is used to get the actionMAppint element.

3, ProcessLocale (): In this method, Struts will get Locale for the current REQUEST. If you are configured, you can save this object as the value of the org.apache.struts.Action.Locale property in httpsession. As the side effects of this method, httpsession will be created. If you don't want to create, you can set the locale property to false in ControllerConfig, as follows: in struts-config.xml:

4. ProcessContent (): Sets ContentType for response by calling response.setContentType (). This method first attempts to get ContentType from the struts-config.xml configuration. Text / html is used by default. If you want to override it, you can like this:

5, processnocache (): If the configuration is no-cache, Struts will set the following three headers for each response:

Requested in struts config.xml

Response.setHeader ("Pragma", "NO-Cache");

Response.setHeader ("cache-control", "no-cache");

Response.SetDateHeader ("Expires", 1);

If you want to set up no-cache header, add the following information in Struts-Config.xml:

6, ProcessPreProcess (): This method provides a hook to preprocess, which can overwrite it in the subclass. Its default implementation does not make anything, always returns True. Returns False will terminate the process of current request.

7, ProcessMapping (): This method will get an actionMApping object with the path information. That is, the element in the struts-config.xml file:

The ActionMapping element contains the name of the Action class and the ActionForm such as processing requests. It also contains the ActionForWards information that current ActionMapping configuration.

8, ProcessRoles (): Struts web application provides an authorization scheme. That is, once a user logs into the container, the struts's processroles () method will check if he has a necessary role to run a given actionMApping by calling request.isuserinrole ().

Suppose you have an addUseraction and you just want administrator to add new User. What you have to do is adding a role property to your addUseraction element, the value of this property is Administrator. This way, this method ensures that the user has an Administraotr role before running addUseraction.

9, Processctionform (): Each ActionMApping is a corresponding ActionForm class. When Struts processes an actionMApping, it will find the name of the corresponding Actionform class from the Name property of the element.

In our example, it will check if there is an ORG.APache.Struts.Action.DynaActionform class in the Request Scope exists. If it will use this object, if it doesn't have a new object and set it in the Request Scope.

10, ProcessPopulate (): In this method, Struts will be equipped with instance variables of ActionForm with matching request parameters.

11, ProcessValidate (): Struts will call the Validate method for your ActionForm class. If you return ActionerRRORS from validate (), it will redirect the user to the page specified by the INPUT property of the element.

12, ProcessForward () and Process (): In these methods, Struts will check the Forward or Include properties of the element. If it is found, the Forward or Include request is placed into the configuration page.

You can guess their differences from these methods: ProcessForward () finally calls RequestDispatcher.Forward (), and processInclude () calls RequestDispatcher.includ (). If you configure the Forward and Include properties simultaneously, it will always call forward because forward is first processed.

13, ProcessActionCreate (): This method gets the name of the Action class from the type of element and creates an instance that returns it. In our example, it will create an instance of a COM.SAMPLE.NEWContActAction class.

14, ProcessActionPerform (): This method calls your Action class Excute () method, your business logic is also in the Excute method.

15, ProcessForwardConfig (): The Excute () method of your Action class will return an ActionForward object, which will point out which page is displayed to the user. Therefore, Struts will create a RequestDispatcher for that page and call RequestDispatcher.Forward ().

The above list illustrates the default RequestProcessor implementation every step in processing the request, as well as the order of execution. As you can see, RequestProcessor is very flexible, allowing you to configure it by setting the properties of the element. For example, if your application is ready to generate XML content instead of HTML, you can notify Struts by setting the properties of the Controller element.

Create your own requestProcessor

By the above, we learned how the default implementation of RequestProcessor works. Now we have to demonstrate an example to explain how to customize your own requestProcessor. To showcase Create User-Customized RequestProcessor, we will make our examples implement the following two business needs:

· We want to create a ContactImageAction class that will generate a picture instead of the normal HTML page.

· Before each request is handled, we want to determine if the user has already logged in by checking the username attribute in the session. If that property is not found, we will redirect the user to the landing page.

We will implement these business needs in two steps.

1. Create your CustomRequestProcessor class, which will inherit from the RequestProcessor class, as follows:

Public Class CustomRequestProcessor

Extends RequestProcessor {

Protected Boolean ProcessPreprocess

HttpservletRequest Request, httpservletResponse response) {

Httpsession session = request.getations (false);

// if User is trying to access login page

// Then Don't Check

IF (Request.getServletPath (). Equals ("/ logininput.do") || request.getServletPath (). Equals ("/ login.do")))

Return True;

// Check if username attribute is there is session.

// if So, IT means User Has Allready Logged in

IF (session! = null && session.getattribute ("username")! = NULL)

Return True;

Else {

Try {

// if no redirect user to login page

Request.getRequestDispatcher ("/ login.jsp"). Forward (Request, Response);

} catch (exception ex) {

}

}

Return False;

}

Protected Void ProcessContent (httpservletRequest Request,

HttpservletResponse response) {

// Check if User is Requesting ContactImageAction

// if Yes Then Set Image / GIF as Content Type

IF (Request.getServletPath (). Equals ("/ contactimage.do")) {

Response.setContentType ("image / gif");

Return;

}

Super.ProcessContent (Request, Response);

}

}

In the ProcessPreprocess method of the CustomRequestProcessor class, we check the session username properties. If not found, redirect the user to the landing page.

For the demand for generating pictures as output, we must override the ProcessContent method, first check whether the request is / contactimage path. If so, we will set the contentType to Image / GIF; otherwise set to Text / HTML.

2, add the following text after your Struts-Config.xml file, tell the struts CustomRequestProcessor to be used as the RequestProcessor class:

Note that when you only have few Action classes to generate an output of non-Text / HTML type, you overwrite the processContent () method is OK. If you are not like this, you should create a Struts sub-application to process the request to generate an action, and set contentType to Image / GIF for them.

The TILES framework for Struts is to use its own requestProcessor to decorate the output of Struts.

ACTIONSERVLET

If you look at the web.xml of your struts web app, you will see such text:

Action =

org.apache.struts.Action.ActionServlet

Action

*. Do

This means that the ActionServlet is responsible for handling all the Struts requests. You can create an ActionServlet subclass, do some specific things when applying start, close, do some specific things when requesting. But before inheriting the ActionServlet class, you should try to create a plugin or requestProcessor to solve your problem. Before servlet1.1, the TILES framework is based on ActionServlet to modify the generated response. But after 1.1, it starts using the TileSRequestProcessor class.

to sum up

Deciding to develop your own MVC framework is a very big decision, you have to consider the time and resources spending the development and maintenance of the frame code. Struts is a very powerful and stable framework that you can modify it to meet the most of your business needs.

But on the other hand, it is not necessary to make an expansion of Struts. If you write some performance relatively low code in RequestProcessor, it will execute each time, thus reducing your efficiency of your entire application. And there are still some situations that develop your own MVC framework is better than extended Struts.

转载请注明原文地址:https://www.9cbs.com/read-45413.html

New Post(0)