How to avoid repeated submission of forms

用户在表单中填写完信息,点击“提交”按钮后,可能会因为没有看到成功信息而再次点击“提交按钮”,从而导致在服务端接收到两条同样的信息,如果这个信用是要保存到数据跌,那么就会出再现两条重复的信息,或者出现数据库操作异常(如果字段设置了唯一性约束)。在实际应用中,由于用户没有及时看到响应信息而导致的重复提交时有发生,响应不及时有可能是因为在这个时段服务器的负载比较大,或者服务上的某个应用占用了较多资源,导致对用户提交数据处理时间过长,又或者这个处理本身就是比较耗时的操作。

有时即使响应及时,也可能出现表单重复提交的情况。服务器端的程序在处理完用户提交的信息后,调用RequestDispatcher.forward()方法将用户请求导向到成功页面,用户看到成功信息后,点击了“刷新”按钮,此时浏览器将再次提交用户先前输入的数据。这是因为调用RequestDispatcher.forward()返回的成功页面,浏览器所保留的URL是先前表单提交的URL,如果是采用HttpServletResponse.sendRedirect()方法将客户端重定向到成功页面,就不会出现重复提交的问题了。

避免表单重复提交可以在客户端通过JavaScript脚本实现,也可以在服务器端编写代码实现。

在客户端通过JavaScript实现的时候,可以借助遮罩功能阻止用户在表单成功返回前重复提交数据。

在服务端实现的话,方法比较多,不过使用最多的还是基于会话令牌来实现。其基本原理如下:

(1)用户访问包含表单的页面,服务端在这次会话中,创建一个Session对象,并产生一个令牌,将这个令牌值作为隐藏域的值,随表单一起发送到客户端,同时将令牌值保存到Session中。

(2)用户提交页面,服务端首先决断语法参数中的令牌值和Session中保存的令牌值是否相同,如果相同,则清除Session中的令牌值,然后执行数据处理操作,不相同,则提示用户已经提交过表单了。同时产生一个新的令牌值,保存到Session中当用户重新访问数据提交页面时,将新产生的令牌的值作为隐藏输入域的值。

参考文献

  • 《Struts2深入详解》/ 孙鑫著;北京:电子工业出版社,2008.7;ISBN 987-7-121-06812-6

你可能感兴趣的:(Programming,repeated,submission,forms,avoid)