2

我正在修改我的表单,以便它们可以在没有启用 javascript 的情况下工作,但也可以通过使用 jquery 和 AJAX 与 javascript 一起工作。我正在使用已被证明既有用又痛苦的 struts。没有 javascript 的表单处理通过基本的 struts 功能进行处理,方法是验证和执行操作并分派回用户所在的页面,但结果(actionMessage 或 actionError)设置在表单 html 中。我有一个隐藏的输入,其中包含将在表单 bean 中设置的页面 url,这就是 struts.xml 中的调度位置

我的问题是我需要能够在一些增强功能(例如 JSON 序列化和 AJAX 请求)下拥有此功能,但我无法找到同时拥有这两种功能的方法。以下是我的无脚本表单的配置和代码,效果很好。

struts.xml 文件

<struts>
    <package name="default" extends="struts-default,json-default">
        <action name="contact" class="org.deadmandungeons.website.action.ContactAction" method="execute">
            <result name="success">%{currentPage}</result>
            <result name="input">%{currentPage}</result>
            <result name="error">%{currentPage}</result>
        </action>
    </package>
</struts>

无脚本 JSP

<%@ tag language="java" pageEncoding="UTF-8"%>
<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
<%@ taglib prefix="t" tagdir="/WEB-INF/tags"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sj" uri="/struts-jquery-tags"%>
<s:form id="contact_form" action="contact" method="post" cssClass="clearfix">
    <label for="contact_user">Username / In-game name:</label>
    <input type="text" id="contact_user" name="contactBean.username"
        class="field" data-enter-click="sendbutton" maxlength="16"
        size="16" />
    <label for="contact_email">Email:</label>
    <input type="text" id="contact_email" name="contactBean.email" class="field" data-enter-click="sendbutton" />
    <label for="contact_message">Message:</label>
    <textarea id="contact_message" name="contactBean.message" rows="5" cols="35"></textarea>
    <input id="no_script" name="contactBean.currentPage" type="hidden" value="${pageContext.request.requestURL}" />
    <div id="contact_response" class="response">
        <s:if test="hasActionErrors()">
            <s:actionerror id="contact_fail" cssClass="fail" />
        </s:if>
        <s:if test="hasActionMessages()">
            <s:actionmessage id="contact_success" cssClass="success" />
        </s:if>
    </div>
    <s:submit type="submit" id="sendbutton" value="Send" />
</s:form>

contactAction 类只是一个基本操作类,它为必要的字段保存一个 ContactBean,并在它不验证时添加 ActionErrors 或在成功时添加 ActionMessages。

现在对于在此之上的 jquery AJAX 方法,我尝试了几件事。我安装了 struts2 jquery 插件,这是一个很棒的插件,我可以使用它在表单上使用 ajax 工作,但不是我的 struts 配置在上面的示例中的方式。对于 struts.xml 中结果的调度位置,我将其设置为如下所示的 jsp 页面:

<%@ taglib prefix="s" uri="/struts-tags"%>
<s:property value="response" escapeHtml="false"/>

并且我向刚刚使用 actionError 或 actionMessage 字符串设置的操作类添加了一个名为 response 的字段。jquery 插件能够从该 jsp 中获取结果,并将其附加到目标位置。但这意味着如果我在打开 javascript 的情况下做同样的事情,一旦提交表单,用户将被分派到只显示结果字符串的 jsp,而不是将它们分派到同一页面并在表单中设置消息。

我也尝试过使用 struts2 json 插件(这也很棒),但这也只适用于 jquery ajax,而不是在没有 javascript 的情况下。

关于如何让表单在两种设置中工作的任何想法?谢谢!

4

1 回答 1

2

我在struts拦截器的帮助下弄清楚了。我制作了一个自定义拦截器,如果存在“noScript”参数,它将检查堆栈参数,如果存在,它将返回“noScript”的结果。noScript 结果是“链”类型,然后会在没有 javascript 时转发到处理表单响应的操作。noScript 参数是通过表单中的隐藏字段设置的,该字段具有当前页面的 url。当页面加载时,jquery 将在页面的任何位置删除此输入。因此,如果禁用了 javascript,则不会删除 noScript 输入。这是我的新 struts.xml 之后:

<struts>
    <package name="default" extends="struts-default,json-default">
        <interceptors>
            <interceptor name="noScriptInterceptor"
                class="org.deadmandungeons.website.NoScriptInterceptor"></interceptor>

            <interceptor-stack name="noScriptStack">
                <interceptor-ref name="noScriptInterceptor" />
                <interceptor-ref name="defaultStack" />
            </interceptor-stack>
        </interceptors>

        <action name="contact" class="org.deadmandungeons.website.action.ContactAction" method="execute">
            <interceptor-ref name="noScriptStack"/>
            <result type="json" name="success" />
            <result type="json" name="input" />
            <result type="json" name="error"/>
            <result type="chain" name="noScript">noScriptContact</result>
        </action>

        <action name="noScriptContact" class="org.deadmandungeons.website.action.ContactAction" method="execute">
            <result name="success">%{noScript}</result>
            <result name="input">%{noScript}</result>
            <result name="error">%{noScript}</result>
        </action>
    </package>
</struts>

这是 NoScriptInterceptor 类:

public class NoScriptInterceptor implements Interceptor {

    private static final long serialVersionUID = -1472114260682759961L;

    @Override
    public void destroy() {
    }

    @Override
    public void init() {
    }

    @SuppressWarnings("unchecked")
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        final ActionContext context = invocation.getInvocationContext();

        String actionName = Utils.toCamelCase(invocation.getAction().getClass().getName());

        Map<String,Object> parameters = (Map<String,Object>)context.get(ActionContext.PARAMETERS);

        Object noScriptParam = parameters.get(actionName + ".noScript");
        if (noScriptParam != null) {
            return Constants.NO_SCRIPT;
        }

        return invocation.invoke();
    }

}
于 2013-09-22T16:46:06.147 回答