chain,redirect,dispatcher of ResultType of struts 2

Posted by asgsoft on Sat, 25 Sep 2021 13:30:58 +0200

1 Result and ResultType in struts 2

In short, result is a string returned after the Action is executed. It indicates where the next page is after the Action is executed. Result is just a string, which is only used to indicate the next page. How can we get to the next page? How can the next page correctly display the results? This should lead to a new concept - ResultType. The so-called ResultType refers to the class that specifically executes the result. It determines which view technology to adopt and presents the execution results to the user.

Many times, we do not distinguish between Result and ResultType, but call it Result in general. Therefore, in addition to being understood as the string described above, Result can also be regarded as a technology and as a technology to implement the View view in the MVC model, that is, ResultType.
In struts 2, you can use a variety of view technologies, such as jsp, freemaker, velocity, jfreechart, etc. at the same time, struts 2 also supports users to customize the ResultType to create their own view technology.

1.1 predefined ResultType

In struts 2, many resulttypes are predefined. In fact, many techniques for displaying results are defined. Struts 2 puts the built-in < result type > in the struts default package. The struts default package is the parent package of the package we configured. This package is defined in the file struts-default.xml under the root directory of the struts-2.3.16.3.jar package. In this package, you can find the relevant definition of < result type >, < result types > element is the direct child element of < package > element. Struts 2 is predefined as follows:

<result-types>
            <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
            <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
            <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
            <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
            <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
            <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
            <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
            <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
            <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
            <result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
            <result-type name="postback" class="org.apache.struts2.dispatcher.PostbackResult" />
        </result-types>

Each of the < result type > elements above is an encapsulation of view technology or jump mode. The name attribute is how to reference this view technology or jump method in the < result > element, corresponding to the value of the type attribute of the < result > element
Some friends may say that we did not configure the type attribute when configuring the < result > element. Yes, you haven't configured it. The reason is that the default type is set in struts 2. If you don't configure it, the default is dispatcher. The dispatcher technology is equivalent to the RequestDispatcher technology in the Servlet, that is, a page Jump technology. The class attribute is the specific implementation class of this view technology or jump mode. These implementation classes have been implemented by struts 2. We only need to reference them.

1.2 Result configuration

1.2.1 configure the name attribute

The name attribute is used to correspond to the string returned by the execute method of the Action and to indicate the next page to jump to after the Action runs. Therefore, the value of the name attribute can be any string. For example, there are the following execute methods:

public String execute() throws Exception {  
        return "toWelcome";  
}  

Then, the toWelcome returned here has the following configuration in struts.xml:

<action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction">  
            <result name="toWelcome">/s2impl/welcome.jsp</result>  
</action>  

If it is not set, the default value is success, which exactly corresponds to the constant success in Action. In that case, the execute method should return success, as follows:

public String execute() throws Exception {  
        return this.SUCCESS;  
}  

At this time, struts.xml has the following configuration:

<action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction">  
            <result>/s2impl/welcome.jsp</result>  
<!-- Or the following configuration 
            <result name="success">/s2impl/welcome.jsp</result>
            -->
</action>

1.2.2 configuring the type attribute

The type attribute of the < result > element can also be any string, but it must be the name attribute of a < result type > element. If there is no custom ResultType, the value of the type attribute is the value of the < result type > name attribute defined in struts-default.xml. For example:

<action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction">  
            <result name="toWelcome" type="dispatcher">/s2impl/welcome.jsp</result>  
</action>  

The dispatcher here is the default < result type > name attribute value defined in struts-default.xml. Since it is the default, you can not configure it. In other words, the above configuration is equivalent to the following configuration. An example is as follows:

<action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction">  
            <result name="toWelcome">/s2impl/welcome.jsp</result>  
</action>  

1.2.3 global Result

The global Result itself has no special features. It also configures the name attribute and type attribute, including how to specify the location of the jsp. It is the same as an ordinary Result, but its < Result > element is not a child element of the < action > element, but a child element of the < Global results > element, and the < global results > element is a child element of the < package > element, as shown in the following example:

<package name="helloworld"  extends="struts-default">  
    <global-results>  
        <result name="toLogin">/login.jsp</result>  
    </global-results>  
  
    <action ......>  
       ......  
    </action>  
</package>  

1.2.4 sequence of searching results

After having the global Result, we need to discuss the order of finding the Result according to the return value of the execute method after the Action runs

  • First, find out whether the < Result > element in your < action > element matches. If so, execute the Result. If not, go to the next step.
  • Secondly, find the global Result of the package where your < action > is located to see if there is a match. If so, execute the Result. If not, go to the next step.
  • Thirdly, recursively find out whether the global results in the parent package and grandfather package of your package match. If so, execute the Result. If not, go to the next step.
  • Finally, if there is no matching Result in the above three cases, an Exception is thrown.
      
    Note: if a Result with the same name appears, the above order is also the priority among results. That is, if the string returned by the execute method of the Action has a matching configuration in both the local Result and the global Result, the local Result shall prevail.

ResultType in struts 2

2.1 dispatcher

2.1.1 basic use of dispatcher

The ResultType named dispatcher is configured in struts-default.xml as follows:

<result-type name="dispatcher" 
class="org.apache.struts2.dispatcher.ServletDispatcherResult" 
default="true"/>

It can be seen from the configuration that its corresponding implementation class is ServletDispatcherResult
If JSP is used as the implementation technology of view, this resulttype is the most commonly used. In this ResultType implementation, we call the javax.servlet.RequestDispatcher class forward method, that is to say, it is equivalent to a re wrapping of RequestDispatcher.

In this case, the feature of using RequestDispatcher for page Jump in Servlet is naturally inherited by the ResultType of dispatcher. So what are the characteristics of RequestDispatcher in Servlet? That is to jump the page through the RequestDispatcher, which will remain the same request object. What are the benefits? Because it is the same object, it means that there is the same data, and there are many data in the request object. In the request object of Servlet, there are typically the following data:

  • The parameter area is the data filled in and submitted by the user on the page
  • Head area, which is automatically added to the data of the request package when the browser sends a request
  • The Attribute area is the value stored in the Attribute area by developers. It is usually accessed through request.setAttribute method and request.getAttribute method
  • Cookie area: when the browser sends a request, it automatically transmits the relevant cookie data to the server through request

2.1.2 dispatcher special usage

In the definition of < result > element, you can use the execute method of Action to run the data. How? Let's take a look at the example. Perhaps we are all used to the following simple < result > configuration:
<result name="toWelcome">/s2impl/welcome.jsp</result>
The strings used to specify the jsp location are fixed. If we want this string to be active and can be changed according to some parameter values, how can we do it? If we define a folder string in Action and assign a value to it in execute or validate, we put it in validate here. The code is as follows:

package cn.javass.hello.struts2impl.action;  

import com.opensymphony.xwork2.ActionSupport;
  
public class HelloWorldAction extends ActionSupport {  
    private String account;  
    private String password;  
    private String submitFlag;  
    private String folder; 
    
    public String execute() throws Exception {  
        this.businessExecute();  
        return "toWelcome";  
    }  
    public void validate(){  
        this.folder = "s2impl"; //The reason for this is: validate is executed with execute first. If there is a value in fieldError, execute will not be executed
        if(account==null || account.trim().length()==0){  
            this.addFieldError("account", this.getText("k1"));  
        }  
        if(password==null || password.trim().length()==0){  
            this.addFieldError("password", this.getText("k2"));  
        }
        if(password!=null && !"".equals(password.trim()) && password.trim().length()<6){  
            this.addFieldError("password", this.getText("k3"));  
        }  
    }  
    /** 
     * An example method that represents a method that can perform business logic processing, 
     */  
    public void businessExecute(){  
        System.out.println("The parameters entered by the user are==="+"account="+account+",password="+password+",submitFlag="+submitFlag);  
    }
    public String getAccount() {
        return account;
    }
    public void setAccount(String account) {
        this.account = account;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getSubmitFlag() {
        return submitFlag;
    }
    public void setSubmitFlag(String submitFlag) {
        this.submitFlag = submitFlag;
    }
    public String getFolder() {
        return folder;
    }
    public void setFolder(String folder) {
        this.folder = folder;
    }  
    
}  

Then, the variable folder can be referenced in the definition of < result >, for example:

<package name="helloworld"  extends="struts-default">  
   <action name="helloworldAction" class="cn.javass.hello.struts2impl.action.HelloWorldAction">  
       <result name="toWelcome" type="dispatcher">/${folder}/welcome.jsp</result> 
       <result name="input">/${folder}/login.jsp</result>   
   </action>  
</package>

The result of this configuration is exactly the same as the path effect written before. If you take a closer look, you will find that the writing of ${folder} is similar to the previous el expression written on jsp, and the folder in it corresponds to the attribute of Action.

2.1.3 more complete configuration mode of dispatcher

Normally, we configure the path of the jsp corresponding to the result directly as the text in the < result > element. This is a simplified writing method. In fact, there are two parameters that can be configured for the dispatcher, as shown in the following example:

<result name="toWelcome" type="dispatcher">  
    <param name="location">/s2impl/welcome.jsp</param>  
    <param name="parse">true</param>  
</result>  

The location parameter is the location of the next jsp we usually write, and the parse parameter determines whether the location parameter can be referenced by using OGNL, which is true by default. In fact, the previous example of using ${folder} to reference the value of the folder attribute of Action is to use OGNL to reference parameters

2.2 chain

2.2.1 basic use of chain

The ResultType named chain is configured in struts-default.xml as follows:

<result-type name="chain" 
class="com.opensymphony.xwork2.ActionChainResult"/>

chain is a special view result, which is used to link an Action to another Action after execution. The new Action uses the context of the previous Action, and the data will also be passed
This is also a frequently used ResultType in actual development. For example, in Servlet development, after a request is processed by a Servlet, it does not directly generate a corresponding response, but passes the request to the next Servlet for further processing, and does not generate a response return until the required multiple servlets are processed. Similarly, in the development of struts 2, there will be such a need. After a request is processed by an Action, it will not generate a response immediately, but pass it to the next Action for further processing. At this time, you need to use the ResultType of chain.
  
For example, let's take a look at the first Action. Let's use HelloWorldAction to simplify it a little. The example is as follows:

public class HelloWorldAction extends ActionSupport {  
    private String account;  
    private String password;  
    private String submitFlag;  
      
    public String execute() throws Exception {  
        this.businessExecute();  
        return "toSecond";  
    }  
    public void businessExecute(){  
        System.out.println("The parameters entered by the user are==="+"account="+account+",password="+password+",submitFlag="+submitFlag);  
    }  
//The getter/setter method corresponding to the property is omitted  
}  

The second Action, the example code is as follows:

public class SecondAction extends ActionSupport {     
    public String execute() throws Exception {  
        System.out.println("Now? SecondAction Process");  
        return "toWelcome";  
    }  
}  

Then, configure these two actions in struts.xml. Pay attention to the configuration of the first Action. When configuring the result of toSecond, the ResultType of chain is used. An example is as follows:

<package name="helloworld"  extends="struts-default">  
        <action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction">  
            <result name="toSecond" type="chain">  
                <param name="actionName">secondAction</param>  
            </result> 
            <!--The following configuration is also possible
            <result name="toSecond" type="chain">secondAction</result>
             --> 
        </action>  
        <action name="secondAction" class="cn.javass.action.action.SecondAction">  
            <result name="toWelcome">/s2impl/welcome.jsp</result>  
        </action>  
    </package>  

2.2.2 chain remarks

chain cannot pass parameters during result configuration, that is, it cannot be configured like the following:

<result name="toSecond" type="chain">  
   <param name="actionName">secondAction?account=5</param>  
</result>  

This configuration method is not feasible, because the name of the Action to be linked is required to be configured here, and parameters cannot be passed. What should I do to pass parameters? Then you need to use ActionContext or ServletActionContext in the Action
Using the Chinese method, the following actions will share the same ActionContext as the previous actions
When configuring the ResultType named chain, in addition to the actionName in the previous example, there is also a parameter named namespace, which indicates the namespace of the package where the linked Action is located. If it is not set, the default is the current namespace. Configuration examples are as follows:

<result name="toSecond" type="chain">  
   <param name="actionName">secondAction</param>  
   <param name="namespace">other Package of namespace</param>  
</result>  

2.3 redirect

2.3.1 basic use of redirect

The ResultType named redirect is configured in struts-default.xml as follows:

<result-type name="redirect" 
class="org.apache.struts2.dispatcher.ServletRedirectResult"/>

It can be seen from the configuration that the corresponding implementation class is ServletRedirectResult.
This Result also uses JSP as the view technology. It wraps the sendRedirect method of javax.servlet.http.HttpServletResponse class. This ResultType is also used to jump to the next page. However, its function is different from the dispatcher above. redirect is characterized by new requests, which means that this request and the request to jump to the next page are different objects, so their values are different.

2.3.2 redirect special usage

Compare the ResultType of dispatcher to see its characteristics. Similarly, in the definition of < result > element, you can use the execute method of Action to run the data. Similarly, define a folder string in the Action and assign a value to it in the execute or validate method. Then, the variable folder can be referenced in the definition of < result >, for example:

<result name="toWelcome" 
type="redirect">/${folder}/welcome.jsp</result>  

Because redirect takes the redirection method, the next page will not get the value in the previous request object. If you want to pass the value, you can pass the parameter in the get method. Examples are as follows:

<result name="toWelcome" type="redirect">
/${folder}/welcome.jsp?account=${account}
</result>  

The above configuration will pass in the parameter of account to the new request, so that the value of account can be obtained on the welcome page. However, the previous welcome page can't get the value of this ` ` account. Why? Let's take a look at the sentence on the welcome page, as follows:
Welcome friends with < s: property value = "account" / > account to visit

In the previous welcome page, the value of account was obtained by using the tag of struts 2. The tag of struts 2 will get the value in the value stack of struts 2. Here, when the Result is executed, the parameter of account is added to the request, and then directly return to the page. There will be no running process of struts 2 at all, that is, The parameter passed here will not enter the value stack corresponding to the request at all, so the writing method here cannot get the value.
So how can I get the value of the account parameter? There are two simple methods: one is to directly use the method of the HttpServletRequest object of the Servlet to obtain the parameters, and the other is to directly use the EL expression. Examples are as follows:

Welcome to ${param.account}My friends are visiting  
<br/>
Welcome to<%=request.getParameter("account") %>My friends are visiting  

2.3.3 more complete configuration mode

Like dispatcher, redirect can also be configured with < param >, as well as location and parse, as follows:

<result name="toWelcome" type="redirect">  
    <param name="location">/s2impl/welcome.jsp</param>  
    <param name="parse">true</param>  
</result>

Topics: Struts struts2