jquery - Wicket 6 - 自定义 JQuery 插件导致 StalePageException
问题描述
我正在将 Wicket 6 用于应用程序,并希望创建一个 JQuery 插件来跟踪用户的活动。
想法是不时刷新 http 会话,如果用户空闲超过 x 分钟,则启动注销/重定向(在服务器端完成)。这一切都得益于 Ajax。
现在,这是我第一次使用 JQuery(或 JS),所以下面是 3 小时的教程点的结果。
idleTimer = null;
idleWait = 12000;
var lastUserInteraction;
var lastServerInteraction;
(function($) {
$(document).ready(function() {
startTimer();
$(document).bind("keypress click", function() {
lastUserInteraction = Date.now();
lastServerInteraction = new Date(document.lastModified).getTime();
if ((lastServerInteraction - lastUserInteraction) < 8000) {
restartTimer();
}
});
});
function startTimer() {
window.console && console.log("TIMER STARTAD, " + idleWait + " millisekunder kvar");
idleTimer = setTimeout(function() {
window.location.reload(true);
}, idleWait);
}
function restartTimer() {
clearTimeout(idleTimer);
window.console && console.log("RESTARTING TIMER");
heartBeat();
startTimer();
}
function heartBeat() {
$.ajax({
url: window.location.href,
type: "HEAD",
timeout: 1000,
statusCode: {
200: function(response) {
console.log('Working!');
},
400: function(response) {
console.log('Not working!');
},
0: function(response) {
console.log('Not working!');
}
}
});
}
})(jQuery)
这段代码“有效”,因为它根据用户活动更新计时器和 http-session(超时在服务器上设置为 10 秒,在客户端设置为 12 秒)。如果会话超时,它还会注销并将用户重定向到登录页面。
但是,每当我尝试通过我的任何组件(文本字段、按钮等)进行任何类型的回调时。它会导致 StalePageException。
有什么建议么?我的皮肤很厚所以不要忍住批评
提前致谢
解决方案
问题在这里:
$.ajax({
url: window.location.href,
...});
StalePageException
当用户尝试使用自当前页面呈现后至少再呈现一次的页面实例时,Wicket 会抛出该实例。
Wicket 生成的 url 看起来像:some/path?11-22.path~to~component.33
.
这11
是页面ID。它是当前 http 会话的页面实例的唯一标识符。
22
是页面渲染计数。它显示了这个特定页面实例被渲染了多少次。
33
是组件行为的索引。这个问题并不有趣。
导致问题的原因也是如此22
。当 Wicket 呈现页面时,renderCount 值为X
。然后,当您对当前页面实例的 url 进行 Ajax 调用时,Wicket 会将服务器端的 renderCount 增加到X+1
. 稍后,当您单击页面中的任何链接/按钮时,Wicket 将发出请求,X
并且它将在服务器端进行比较失败,X+1
并且 Wicket 将抛出 PageStaleException。
您有多种选择可以避免这种情况:
- 挂载资源(请参阅 Application.mountResourceReference)。这类似于普通的 Servlet。好处是资源/servlet 是无状态的,不会有任何类型的响应构造。您只需要发送一个简单的 GET 请求(即使 HEAD 也可以)来刷新 http 会话
- 向
/some/page
(不带查询字符串?11
)发出请求。这将创建此页面的新实例,因此不会影响当前实例。但它将完成呈现此页面所需的所有工作,例如访问数据库等。