How to use multiple forms / actions in a single view in Struts 2

我是研究僧i 提交于 2019-12-12 12:08:15

问题


I have a search box which is displayed on every page. The JSP code for the search box is inserted into every page via tiles.

The search box has a form and an action class SearchAction which needs to preload some properties for drop down boxes. The SearchAction class has an input() method, which does this initialization.

Some pages also have their own form in the main area. Also with their own action class. They also have an input() method which does some preloading.

  1. Is it possible to use two actions in the same view?
  2. How can each form have access to it's own actions's properties.
  3. And how could I manage to have the input method of both action classes be called before the JSP is rendered?

Update:

I am adding a trimmed down example, since it's probably not clear what I am trying to do. It's a register page register.jsp with an RegisterAction. And the page also contains the search form. (BTW: I left out the getter/setter and other stuff in the action classes to keep it short):

register.jsp:

<s:form action="executeSearch">
    <s:textfield key="name" label="Name"/>
    <s:textfield key="age"  label="Age"/>
    <s:submit/>
</s:form>

<s:form action="executeRegister">
    <s:textfield key="firstName" label="First Name"/>
    <s:textfield key="lastName" label="Last Name"/>
    <s:textfield key="age" label="Age"/>
    <s:submit/>
</s:form>

struts.xml:

<action name="*Search" class="action.SearchAction" method="{1}">
    <result name="success">/searchresult.jsp</result>
</action>

<action name="*Register" class="action.RegisterAction" method="{1}">
    <result name="input">/register.jsp</result>
    <result name="success">/registerOk.jsp</result>
</action>

SearchAction.java:

public class SearchAction extends ActionSupport {

    private String name;
    private int age;

    @Override
    public String input() throws Exception {
        // preload the search form with some demo data
        name = "test";
        age = 20;
        return INPUT;
    }

    @Override
    public String execute() throws Exception {
        return SUCCESS;
    }

    ...
}

RegisterAction.java:

public class RegisterAction extends ActionSupport {

    private String firstName;
    private String lastName;
    private int age;

    @Override
    public String input() throws Exception {
        // preload the register form with some demo data
        firstName = "John";
        lastName = "Rambo";
        age = 10;
        return INPUT;
    }

    @Override
    public String execute() throws Exception {
        return SUCCESS;
    }

    ...
}

Let's say I call the action inputRegister.action. Then RegisterAction.input() is called. The properties are set. And result SUCCESS causes register.jsp to be rendered.

But what about my search form. How do I get access to the search action and it's model. Neither of those are on the ValueStack of course. And neither do I see a way to call any methods of SearchAction in order to initialize it's model. I deliberately choose age to be in both action classes. In the rendered page you can see that the search form also accesses the RegisterAction-properties (because that's on top of the ValueStack). But it needs to access SearchAction. It must display 20 and not 10.

I am clearly doing it wrong. But even after a lot of googling, I still did't find out the right way to do it.


回答1:


As I found (please correct me): Two forms need to be initiated in their own actions before be show to user, when you ask for Registration form, the search form does not get initiated, as its action is never called.

This is a common problem which can be easily handled with Ajax, DO NOT LOAD ALL YOUR PAGE DATA. Please have a look at http://struts.jgeppert.com/struts2-jquery-showcase/index.action. There is a Theme selection select box, which has been initiated once. Loading other part of the page, will be done via Ajax and thus the theme selection, action which initiates the select box, does not need to be re-run. You can easily use the struts 2 jquery plugin to achieve it.

If you can not use Ajax (with any reason), then there is no simple way. You should manually initiate the you search form items, in EACH action, to make sure that your struts tag can read search form initiated data. You can think of it as you need to some how, cut and paste the body of your search action in all your actions !!




回答2:


The concept of the view is used to perform any number of actions, and any action can have any number of results. A result is used to return a view. The action that returns a view is placed on top of the ValueStack to be easy accessible via evaluating OGNL expressions. The result view could be mapped to any action in any action class. It knows nothing about action which calls it, but it can determine it, again using OGNL. You can map actions to different method of the same action class, so you don't need to have many input() methods.

EDIT:

You problem is you bounded form fields wrong. Each form should have a separate storage to display it correctly. Fields are bounded by name, and you'd better have a form bean for the search condition variables and put it somewhere in the action context.

<s:form action="executeSearch">
    <s:textfield key="searchBean.name" label="Name"/>
    <s:textfield key="searchbean.age"  label="Age"/>
    <s:submit/>
</s:form>

<s:form action="executeRegister">
    <s:textfield key="firstName" label="First Name"/>
    <s:textfield key="lastName" label="Last Name"/>
    <s:textfield key="age" label="Age"/>
    <s:submit/>
</s:form> 

Note: the key attribute generates name, label, and value.

Each action needs to initialize a searchBean, unless it has a session scope. If you put a bean to a session, then you should use #session. prefix. More about OGNL you can find on the docs page.




回答3:


Ok. I am giving an answer to my own question. After a lot more of Google time, I found that initializing the secondary action with <s:action /> inside the JSP does what I need. This tag can also return the action object in a variable, which we can push on the ValueStack for the form. An example looks like this:

<!-- Initializes search model (preloading and stuff). -->
<s:action var="searchAction" name="inputSearch" >
    <s:param name="origin" value="inputRegister"/>
</s:action>

<!-- Pushing search action on ValueStack for the search form. -->
<s:push value="#searchAction">
    <s:form action="executeSearch">
        <s:hidden name="origin"/>
        <s:textfield key="name" label="Name"/>
        <s:textfield key="age"  label="Age"/>
        <s:submit/>
    </s:form>
</s:push>

<!-- This is the main form. It knows nothing about the search action. -->
<s:form action="executeRegister">
    <s:textfield key="firstName" label="First Name"/>
    <s:textfield key="lastName" label="Last Name"/>
    <s:textfield key="age" label="Age"/>
    <s:submit/>
</s:form>

This works nice. However there are two issues which need to be considered:

  • The search action is used in many pages. If the validation of the search form fails, we need to find back to the original page. I solved this by having an "origin" parameter. This is set to the main input action`s name. The search action chains to this action if validation fails.
  • The search action is initialized very late, when the rendering of the JSP is already in full progress. Exceptions at this point can be problematic. I had to take care to catch all Exceptions myself.


来源:https://stackoverflow.com/questions/31494860/how-to-use-multiple-forms-actions-in-a-single-view-in-struts-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!