strut2防止表单重复提交的两种方式

说明
小例子
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>
1
2
3
4
5
6
success.jsp
仅仅一个提交成功提示。

  <body>
   提交成功!
  </body>
1
2
3
struts.xml
动作类成功执行后通过转发的方式跳转到success.jsp页面。

    <action name="login" class="com.scx.web.action.UserAction" method="login">
            <result >/success.jsp</result>
        </action>
1
2
3
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>
1
2
3
在用户表单提交后我们使用的是转发的方式跳转到success.jsp页面。我们可以通过重定向的方式来解决页面重复刷新的问题。 
通过设置type=”redirect”来实现重定向。

        <action name="login" class="com.scx.web.action.UserAction" method="login">
        <!--使用重定向的方式 -->
            <result type="redirect">/success.jsp</result>
        </action>
1
2
3
4
使用方法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这种方式
--------------------- 
作者:甄情 
来源:CSDN 
原文:https://blog.csdn.net/su20145104009/article/details/69942517 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/F13253524870/article/details/89301846