一次刷新重复提交问题及其引入的新问题的解决过程记录
1. 问题描述
用户登陆后,刷新页面,IE提示重复提交,需要用户做出选择,影响用户体验.
2. 问题分析.
登陆页面是一个jsp,form中使用一个loginAction.action提交登陆.提交后在struts中
dispatch到主页面,即index.jsp,此时浏览器地址栏显示地址是用于登陆的action,
即: http://ip:port/loginAction.action这样的格式.
这个action地址就是上面登陆页面form的action,这样一按F5刷新,
造成重复提交(即,重复登陆).
3. 问题解决
登陆成功,将用户ID压入session后,让struts的action dispatch到一个临时的jsp,
这个jsp打开后,配置header的META,自动刷新到index.jsp页面.
<META HTTP-EQUIV="Refresh" CONTENT="0;URL=<%=request.getContextPath()%>/index.jsp">
这样登陆后,浏览器中显示http://ip:port/index.jsp.
这样刷新时,就不会产生重复提交问题.
4. 引入新问题
上面的http://ip:port/index.jsp页面刷新后,发现又跳到登陆界面了.
跟踪发现,页面一刷新,登陆时压入session的用户id变成null,
导致用户重复处于未登陆状态. 就是刷新导致session丢失.
google发现,IE7中,当刷新一个带有iframe的页面时(index.jsp确实有一个frameset,包括leftFrame和mainFrame),
会导致session丢失.
很不幸,虽然测试使用的浏览器是IE8,当时也以为是这个刷新问题,折腾了不少时间,无果.
后来,无意跟踪过滤器代码发现,每次刷新或者关闭页面时,都会请求一个logout.action.
logout.action这个logout专门注销session.坑爹啊.....
检查index.jsp代码,发现注册了window.onbeforeunload事件,在这个事件中,请求logout.action.
于是导致,页面一刷新或者关闭页面所在的浏览器选项卡,或者直接关闭浏览器,
都会触发这个onbeforeunload事件,然后用户就logout了.
配置这个onbeforeunload事件,是因为,一个用户不能在不同的地方同时登陆系统.
这样,当一个用户用一个账号登陆时,这个账号就不能在别处登陆.这样就要求一旦用户从一个地方退出登陆,
或者关闭浏览器就要实现自动注销.否则,一个用户已经关闭浏览器退出登陆了,
该账号在session过期时间之内还是不能在别的地方登陆.于是注册onbeforeunload事件,当用了关闭浏览器,
就会自动登出.
但是注册onbeforeunload事件,在刷新时也会触发.
于是,产生了新问题,不能在onbeforeunload事件中让用户退出登陆,而且当用户长时间不操作,或者关闭
浏览器后,用户能自动退出登陆.因为注销session后,用户就失效,这跟让session过期是一样的.
于是想到了解决方案.
5. 引入问题解决
在index.jsp页面设置一个session超时时间sessionTimeOut,设置为10分钟.
然后启动一个定时器(setInterval),每10秒钟执行一次,让sessionTimeOut减10.
同时,在这个定时器(setInterval)中,检查sessionTimeOut,假如sessionTimeOut>0,
就发送ajax请求(心跳),每次将当前session过期时间设置为15秒以后.
另外,在index.jsp的主页面和两个frame页面都注册document的mousemove事件,只要一检测
到鼠标移动(说明在操作),就把sessionTimeOut重新设置为初始值10分钟.
因为,两个frame中的页面随时都可能变化,这里就需要在设置一个定时器,每隔一秒钟给两个frame
中的页面的document注册mousemove事件,以重设sessionTimeOut.
这样,当长期不操作系统,sessionTimeOut减小为0后,停止发送ajax请求(心跳),则15秒后,session过期,
导致用户退出登陆.
index.jsp中js代码(使用jquery)
var SESSION_TIME = 10 * 60 * 1000; //十分钟
var setChangeIterval = 1000;
var setHeartBeatInterval = 10 * 1000; // 不能配置大于15秒,后台写死了
var sessionTimeOut = SESSION_TIME; //页面没有做操作时间的 超过10分钟 + 15秒(最多),则session过期,需要重新登陆
//鼠标移动事件
function docMouseMoveFunc()
{
//鼠标不动时,该变量每隔10秒钟减少10,当该变量变成0后,页面不发送心跳,这样当前session最多在15秒后过期.
//同时,给页面绑定mouse事件,鼠标移动,改变量值恢复为初始值.
sessionTimeOut = SESSION_TIME;
}
//心跳函数,每10秒钟执行一次,
function hearBeat()
{
if(sessionTimeOut > 0)
{
var url = "<%=request.getContextPath()%>/heartBeat.action";
$.ajax({
url:url,
cache: false,
success:function(data, textStatus)
{
if(data.heartBeatDone != 1) //说明后台报错,则不再发送心跳请求
{
sessionTimeOut = 0;
}
},
type:'post',
async:true,
dataType:'json',
error:function(XMLHttpRequest, textStatus, errorThrown)
{
}
});
sessionTimeOut = sessionTimeOut - 10 * 1000;
}
}
//给框架页面绑定事件,为防止框架中页面改变,该函数每隔一秒执行一次
function frameDocChange()
{
$(frames.leftFrame.document).mousemove(docMouseMoveFunc);
$(frames.mainFrame.document).mousemove(docMouseMoveFunc);
}
//给框架页面绑定事件,为防止框架中页面改变,该函数每隔一秒执行一次
setInterval('frameDocChange()',setChangeIterval);
//每隔10秒钟执行一次心跳,将当前session过期时间设置为15秒之后
setInterval('hearBeat()',setHeartBeatInterval);
//
$( document ).mousemove(docMouseMoveFunc);
//页面加载完成后执行一次心跳
$(document).ready(
function()
{
hearBeat();
sessionTimeOut = SESSION_TIME; //恢复超时计时
});
-------------------------------
action配置:
<action name="heartBeat" class="xxx.HeartBeatAction" method="heartBeat">
<result name="sucess">/heartBeatResult.jsp</result>
</action>
heartBeat方法:
public String heartBeat()
{
heartBeatDone = "1";
try
{
ctx = ActionContext.getContext();
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession httpSession = request.getSession();
httpSession.setMaxInactiveInterval(15); //前台每隔10秒将当前session过期时间设置为15秒以后
System.out.println(new Date());
}
catch (Exception e)
{
heartBeatDone = "0";
}
return "sucess";
}
heartBeatResult.jsp代码:
<%@page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
{ heartBeatDone:${heartBeatDone}}
相关推荐
在ASP.NET web应用程序中,"刷新重复提交"是一个常见的问题,它发生在用户点击浏览器的刷新按钮或者使用前进/后退导航时。这可能导致数据的不一致性和错误,因为服务器可能会收到相同请求的多次处理,而这些请求原本...
防止页面刷新重复提交是 Web 开发中常见的问题,多次提交表单可能会导致不必要的数据重复录入、服务器压力增大等问题。下面我们将详细介绍防止页面刷新重复提交的方法。 一、验证码方法 验证码方法是防止页面刷新...
页面提交后,后退,刷新会重复提交,导致很多麻烦,.net里可以这样来解决一下,一个类文件,省去每个页面都写的麻烦
在Web应用程序开发中,特别是在使用ASP.NET进行网站构建时,一个常见的问题是表单重复提交。这通常发生在用户通过按下浏览器的F5键来刷新页面的情况下,此时之前的表单数据会被再次提交到服务器端。这不仅可能导致...
其中,“防止页面的重复提交和刷新”这一问题尤为关键,它不仅关系到系统的稳定性,还直接影响用户体验。本文旨在深入探讨如何有效地预防页面的重复提交与刷新现象,通过具体实例和详细的分析来帮助开发者更好地理解...
在Web开发中,用户在提交表单后可能会意外地点击浏览器的刷新或后退按钮,导致数据重复提交,这在数据库操作中可能引起严重问题,比如财务交易的重复扣款或者用户信息的重复录入。针对这个问题,我们可以采取多种...
在Web开发中,防止用户刷新页面而导致重复提交数据是一个重要的问题。这通常涉及到表单提交、支付确认等关键操作,确保这些操作仅执行一次是非常必要的。本资源提供了一个解决方案,通过使用“Token”机制来避免这种...
在J2EE框架中,开发过程中常常会遇到一些与用户交互相关的技术问题,如重复提交、重复刷新以及防止用户后退导致的数据不一致。这些问题在实际应用中可能会对系统的稳定性和数据完整性造成影响,因此需要采取相应的...
防止提交 在用struts2.0标签开发...在点击"提交"后,我们通常会弹出一个提示信息的页面,用户此时有可能会按f5刷新当前提交的action,从而将多个相同的数据保存到了后台数据库,并且造成了潜在的安全危险! 避免重复提交呢?
下面将详细讲解Struts2令牌解决重复提交问题的过程: 1. **生成令牌**:在Action中,使用`TokenAwareActionSupport`作为基类,这个类实现了`TokenSessionStore`接口,可以方便地获取和验证令牌。在表单展示之前,...
### JSP重复提交问题及其解决方法 #### 一、引言 在Web应用程序开发中,尤其是在使用Java Server Pages (JSP)技术时,一个常见的问题是重复提交数据。当用户不小心刷新了页面或按下了浏览器的“后退”按钮时,可能...
防卡页面刷新重复提交源代码,根据msdn上提供方法进行改造,解决了诸多bug,实用性很强
在ASP.NET开发中,页面重复提交是一个常见的问题,它可能导致数据冗余或一致性错误。防止重复提交对于确保数据的准确性和应用的稳定性至关重要。本文将深入探讨如何在ASP.NET环境中解决这个问题。 首先,理解问题的...
Token机制是一种常见的防止重复提交的方法,其核心思想是为每一次表单提交生成一个唯一的Token值,并将这个Token值存储在客户端(通常是在表单中作为一个隐藏字段),同时也在服务器端记录该Token值。当表单被提交时...
重复提交的分类: 1.由于网速原因而重复点击提交按钮 2.已经提交成功,然后又刷新页面重复提交 3.已经提交成功,然后点击后退,然后又重复提交。...如果不是重复提交,在控制台中只是输出一次,hello:XXXX
为了解决这个问题,开发者需要确保表单只提交一次,防止不必要的数据重复处理或者服务器的重复计算。下面详细解释几种防止Layui表单重复提交的方法。 首先,在HTML表单中,为了避免在提交时页面刷新导致的重复提交...
在Web开发中,表单重复提交是一个常见的问题,它可能会导致数据冗余或者不一致,尤其是在处理关键操作如交易、订单或用户注册时。这里我们深入探讨这个问题,并提供解决方案。 标题"表单重复提交问题1"所涉及的核心...
重复提交问题的产生原因有很多,例如点击提交按钮两次、点击刷新按钮、使用浏览器后退按钮重复之前的操作、使用浏览器历史记录重复提交表单、浏览器重复的HTTP请求、nginx重发等情况。 3. 解决方案 ### 1. 前端JS...
在Web开发中,尤其是使用Struts2框架时,防止重复提交是一个重要的问题,因为它可能导致数据的不一致性或者服务器资源的浪费。Struts2提供了一种通过拦截器来解决这个问题的方法,即`token`拦截器。本文将深入探讨...