struts2防止表单重复提交(s:token)

来源:互联网 发布:淘宝联盟订单失效 编辑:程序博客网 时间:2024/05/18 18:20

    • 说明
    • 小例子
      • jsp页面
      • successjsp
      • strutsxml
      • UserAction类
      • 运行结果
    • 解决方法
      • 方法1使用重定向
      • 方法2使用stoken生成令牌配合token拦截器
        • jsp页面
        • strutsxml
        • UserAction动作类
      • 方法3使用stoken生成令牌配合tokensession拦截器

说明

防止表单的重复提交在我们的日常生活中有很大的重要性。
例如,如果在我们使用支付宝支付时,有时由于网速太慢等缘故会导致用户多次点击支付按钮,如果未防止表单重复提交,那么将会产生严重的后果。
表单重复提交有两种情况:

1.提交表单后按下刷新按钮
2.多次点击提交按钮
那么如何防止表单的提交呢?
首先举个表单重复提交的小例子


小例子

jsp页面

一个输入框和一个提交按钮,提交后进入login.action动作

  <body>    <s:form action="login">        <s:textfield name="username" label="用户名"/>        <s:submit label="提交"/>    </s:form>  </body>

success.jsp

仅仅一个提交成功提示。

  <body>   提交成功!  </body>

struts.xml

动作类成功执行后通过转发的方式跳转到success.jsp页面。

    <action name="login" class="com.scx.web.action.UserAction" method="login">            <result >/success.jsp</result>        </action>

UserAction类

每次用户提交表单后,输出表单提交的提示。

public class UserAction extends ActionSupport {    private String username;    public String login(){        System.out.println(username+"表单提交啦");        return SUCCESS;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }}

运行结果

这里写图片描述
手速太慢 无法进行多次点击提交按钮。就点击后退按钮 进行重复提交。
在控制台我们看到输出了多次的表单提交。
基于此,我们应该如何解决呢?


解决方法

方法1:使用重定向

        <action name="login" class="com.scx.web.action.UserAction" method="login">            <result >/success.jsp</result>        </action>

在用户表单提交后我们使用的是转发的方式跳转到success.jsp页面。我们可以通过重定向的方式来解决页面重复刷新的问题。
通过设置type=”redirect”来实现重定向。

        <action name="login" class="com.scx.web.action.UserAction" method="login">        <!--使用重定向的方式 -->            <result type="redirect">/success.jsp</result>        </action>

使用方法1后运行结果
这里写图片描述
通过结果我们可以发现

表单重复提交的第一种情况,页面刷新成功解决了。但是后退时再重新提交还是会表单重复提交。

遗留的问题:防不住后退,再提交。


方法2使用s:token生成令牌配合token拦截器

在struts2中有一个<s:token/> 标签。该标签通过生成一个独一无二令牌,它会同时放在session和表单的隐藏域中。在进行表单提交时,token拦截器会进行令牌的验证,如果两次的令牌匹配,那么本次表单提交成功,否则提交失败。提交失败后会出现一个 invalid.token 无效的结果视图,配置相关的结果即可。有想了解token拦截器的请看在struts-default.xml(struts2的核心jar包里面有)文件中查看。
这里写图片描述
使用<s:token/> 标签的要求是,把此标签放到form表单中,并且在动作类中生成相应的get,set方法。

jsp页面

在form中添加<s:token/> 标签

  <body>    <s:form action="login">        <s:token/>        <s:textfield name="username" label="用户名"/>        <s:submit label="提交"/>    </s:form>  </body>

struts.xml

添加token拦截器,由于token拦截器不再默认的拦截器栈中,使用token拦截器后默认的拦截器栈不起作用,所以还需要添加默认的拦截器栈。

        <action name="login" class="com.scx.web.action.UserAction" method="login">            <interceptor-ref name="defaultStack"/>            <interceptor-ref name="token"/>            <result >/success.jsp</result>            <result name="invalid.token">/message.jsp</result>        </action>

UserAction动作类

添加token变量 生成相应的get,set方法。

public class UserAction extends ActionSupport {    private String username;    private String token;    public String login(){        System.out.println(username+"表单提交啦");        return SUCCESS;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getToken() {        return token;    }    public void setToken(String token) {        this.token = token;    }}

运行结果:
这里写图片描述

方法3使用s:token生成令牌配合tokensession拦截器

tokensession拦截器同样也能够首先token拦截器的效果,只不过tokensession在接到非法令牌时将提交的数据保存在session中;只会处理第一次请求,当重复提交时,不会再处理。
配置和token一样。
只是把struts.xml中的token拦截器换成tokenSession拦截器

        <action name="login" class="com.scx.web.action.UserAction" method="login">            <interceptor-ref name="tokenSession"/>            <interceptor-ref name="defaultStack"/>            <result >/success.jsp</result>            <result name="invalid.token">/message.jsp</result>        </action>

运行结果:
这里写图片描述
从结果中,虽然没有跳转到请勿重复提交页面,但是表单也没有重复提交。建议大家使用tokenSession这种方式。

1 0
原创粉丝点击