Java Web防止表单重复提交

转载请注明出处:http://blog.csdn.net/qq_15002323/article/details/51253303

注:本章内容基于struts2框架,action就相当于servlet

哎,今天遇到这个问题快把我搞崩溃了咯,但是,注意只是快,并没有- -,感觉自己就像卡卡罗特一样啊,只要不把我拍死,我只会变得更强噢。

场景重现

上网最痛苦的事莫过于网速慢了,这个玩lol的自然懂~~~。打个粗糙的比方吧,一个登陆页面,你很急,但是网很卡,登了半天没卵用,你连点了几次登录①。你登录进去了,刷新了浏览器页面②。登陆成功后,你后退,再次点击登录③。

上述三种情况都会导致表单数据的重复提交,这样直接的后果便是服务器的多次响应,这当然不是我们程序猿想看到的。好了,我要开始装X模式了,先搭建相关开发环境,一个登陆页面login.jsp,一个login.action,一个跳转的main.jsp,配置好相关映射关系:

login.jsp:

<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>登陆</title>
</head>
<body>
    <form action="login.action" method="post">
        <input type="text" name="name"/>
        <br/>
        <input type="password" name="age"/>
        <br/>
        <input type="submit" />
    </form>
</body>
</html>

login.action:

import com.opensymphony.xwork2.ActionSupport;

public class Login extends ActionSupport {

    /** * */
    private static final long serialVersionUID = 1L;

    private String name;

    private String age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    @Override
    public String execute() throws Exception {
        // 休眠三秒,模拟网速很慢
        Thread.sleep(1500);
        System.out.println("姓名:" + name + "年龄:" + age);
        return "success";
    }
}

main.jsp 这个是个空的页面

网速较慢重复提交

Java Web防止表单重复提交_第1张图片

提交完成再次刷新

后退页面再次提交

解决之道

其实文章开头就说了本文是基于Struts2的,这里就说说理由吧,不吹牛。解决上述问题的根本方法就是在服务器做处理,只对用户响应一次,最好的办法就是采取token的方式。

token,其实就是用户自定义的字符串,可以保存在session里面,在Struts2中加上<s:token /> 当该页面渲染就会生成一个token(令牌),会随着form参数一起提交到服务器,生成机制可以自己编写。

那Struts2就可真是方便的不要不要的,内部已经封装好了token机制,调用起来也非常简单。首先引入struts2标签,然后在form内部加上<s:token />,再修改struts.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
    <package name="default" extends="struts-default">
        <action name="login" class="com.cjt.test.Login">
            <result name="success">/main.jsp</result>

            <interceptor-ref name="tokenSession"></interceptor-ref>
            <interceptor-ref name="defaultStack"></interceptor-ref>
        </action>
    </package>
</struts> 

这样就可以了,是不是很神奇。我们看看效果图:

只有第一次打印了表单数据,后面都是提示“form中的token与session中的token->null不匹配”,这个是struts2做的,在第一次提交表单成功后,会删掉session中的token值,这样只有在第一次提交表单的时候session中的token没有被删除,与form传来的token一致,才会执行打印。具体实现可以在struts2的源码中找到,我这种小白就说说而已~(~ ̄▽ ̄)~

上面只是演示了那三种情况中的一种,其他都是一样的,就不做重复了。贴点有意思的吧,看看加了<s:token />后提交表单的请求数据:
Java Web防止表单重复提交_第2张图片
这样就很清楚了吧,有兴趣的大牛想钻研更深可以去看看源码,顺便贴一个参考的大牛水文:JavaWeb学习总结

又到了说再见的时候,拜了个拜。

你可能感兴趣的:(java,java,Web,struts,表单)