【问题标题】:How to use multiple forms / actions in a single view in Struts 2如何在 Struts 2 的单个视图中使用多个表单/动作
【发布时间】:2015-10-08 07:09:54
【问题描述】:

我有一个搜索框,它显示在每一页上。搜索框的 JSP 代码通过图块插入到每个页面中。

搜索框有一个表单和一个动作类SearchAction,它需要为下拉框预加载一些属性。 SearchAction 类有一个 input() 方法,它执行此初始化。

有些页面在主区域也有自己的表单。也有自己的动作课。他们还有一个input() 方法,可以进行一些预加载。

  1. 是否可以在同一个视图中使用两个操作?
  2. 每个表单如何访问自己的操作属性。
  3. 如何才能在呈现 JSP 之前调用两个操作类的输入法?

更新:

我正在添加一个精简的示例,因为可能不清楚我要做什么。这是一个注册页面register.jspRegisterAction。该页面还包含搜索表单。 (顺便说一句:我在动作类中省略了 getter/setter 和其他东西以保持简短)

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;
    }
    
    ...
}

假设我将操作称为inputRegister.action。然后RegisterAction.input() 被调用。属性已设置。结果SUCCESS 导致register.jsp 被渲染。

但是我的搜索表单呢?如何访问搜索操作及其模型。当然,这些都不在ValueStack 上。而且我也没有看到调用SearchAction 的任何方法来初始化它的模型的方法。我特意选择age 参加两个行动班。在呈现的页面中,您可以看到搜索表单还访问了RegisterAction-*.properties(因为它位于ValueStack 之上)。但它需要访问SearchAction。它必须显示 20 而不是 10。

我显然做错了。但即使经过大量的谷歌搜索,我仍然没有找到正确的方法。

【问题讨论】:

  • 不要使用input 预加载值。如果需要,您可以使用preparable。您可以通过一项操作导航到 form-s 页面,而其他操作则用于从表单提交。

标签: java jsp struts2 ognl valuestack


【解决方案1】:

好的。我正在回答我自己的问题。经过更多的 Google 时间后,我发现在 JSP 中使用 &lt;s:action /&gt; 初始化辅助操作可以满足我的需要。此标记还可以在变量中返回操作对象,我们可以将其推送到表单的ValueStack。一个示例如下所示:

<!-- 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>

这很好用。但是有两个问题需要考虑:

  • 在许多页面中都使用了搜索操作。如果搜索表单的验证失败,我们需要找回原来的页面。我通过使用“原点”参数解决了这个问题。这设置为主要输入操作的名称。如果验证失败,搜索操作会链接到此操作。
  • 搜索动作的初始化很晚,此时 JSP 的呈现已经在全部进行中。此时的异常可能是有问题的。我必须自己小心捕捉所有异常。

【讨论】:

  • 针对非常简单的需求的非常hacky的解决方案。
  • 是的。我仍在努力寻找解决此问题的好方法。我希望这些动作完全解耦。但仍然需要他们是相同的看法。我愿意接受更好的建议。 (Alireza 的解决方案很好,但不幸的是不可能)。
  • 我希望动作完全解耦 - 为什么?您可以使用一项操作来填充表单和从表单提交的单独操作。
  • 没错,为什么我需要另一个动作来填充另一个表单?我将一次性完成。
  • 你可以创建一些你的其他动作扩展的基本动作。如果您需要将搜索添加到不同的页面,那么您不应该从操作范围填充它。
【解决方案2】:

视图的概念用于执行任意数量的动作,任何动作都可以有任意数量的结果。结果用于返回视图。返回视图的操作放置在ValueStack 的顶部,以便通过评估 OGNL 表达式轻松访问。结果视图可以映射到任何动作类中的任何动作。它对调用它的动作一无所知,但它可以再次使用 OGNL 来确定它。您可以将操作映射到同一操作类的不同方法,因此您不需要有很多 input() 方法。

编辑:

您的问题是您的有界表单字段错误。每个表单都应该有一个单独的存储来正确显示它。字段受名称限制,您最好有一个用于搜索条件变量的表单 bean,并将其放在操作上下文中的某个位置。

<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> 

注意:key 属性生成namelabelvalue

每个动作都需要初始化一个searchBean,除非它有一个会话范围。如果将 bean 放入会话,则应使用 #session. 前缀。有关OGNL 的更多信息,您可以在文档页面上找到。

【讨论】:

  • 感谢罗马,您的回答。但是,我仍然对如何实现这一目标一无所知。如果我有一个单一的动作没有问题。我知道该操作可以有很多方法,例如可以映射到表单中的多个提交按钮。但在我的情况下,我有两个完全独立的表单、模型和它们的动作类,它们执行初始化、验证等。而且我需要将两者放在同一页面上。我添加了一个示例,我正在尝试这样做。也许你可以引导我朝着正确的方向前进?
  • 在大多数情况下,Struts 用于准备值堆栈以保持视图显示的组件,并且每个组件都应该有一个唯一的 OGNL 路径来访问它。
  • 非常感谢。这引导我朝着正确的方向前进。我在另一个答案中写下了我的解决方案。
【解决方案3】:

我发现(请纠正我):在向用户显示之前,需要在自己的操作中启动两个表单,当您要求注册表单时,搜索表单不会启动,因为它的操作从未被调用。

这是一个常见问题,可以使用 Ajax 轻松处理,请勿加载所有页面数据。请查看http://struts.jgeppert.com/struts2-jquery-showcase/index.action。有一个主题选择选择框,已经启动过一次。加载页面的其他部分将通过 Ajax 完成,因此不需要重新运行主题选择、启动选择框的操作。您可以轻松地使用 struts 2 jquery 插件来实现它。

如果您不能使用 Ajax(出于任何原因),那么没有简单的方法。您应该在每个操作中手动启动搜索表单项,以确保您的 struts 标签可以读取搜索表单启动的数据。您可以根据需要想出一些方法,在所有操作中剪切和粘贴搜索操作的正文!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    • 1970-01-01
    相关资源
    最近更新 更多