首页 > 解决方案 > 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。

有什么建议么?我的皮肤很厚所以不要忍住批评

提前致谢

标签: jqueryjquery-pluginswicketwicket-6

解决方案


问题在这里:

$.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)发出请求。这将创建此页面的新实例,因此不会影响当前实例。但它将完成呈现此页面所需的所有工作,例如访问数据库等。

推荐阅读