处理xPages中文档锁定的最佳方法?

处理xPages中文档锁定的最佳方法?,xpages,Xpages,在xPages中处理文档锁定的最佳方法是什么?目前我们使用标准的软锁定,它在Notes客户机中似乎工作得相当好 在xPages中,我考虑过使用“允许文档锁定”功能,但我担心人们会在不使用“关闭”或“保存”按钮的情况下关闭浏览器,那么锁定将永远不会被清除 当用户关闭会话时,是否有方法清除锁定?我没有看到这样的事件 还是有更简单的方法来锁定文档 我意识到我可以使用代理清除锁,但何时运行它?我会想一个晚上的某个时候,然后我相当肯定锁应该不再真正有效 您可以从webDAV的工作方式中选择一个页面。在这里

在xPages中处理文档锁定的最佳方法是什么?目前我们使用标准的软锁定,它在Notes客户机中似乎工作得相当好

在xPages中,我考虑过使用“允许文档锁定”功能,但我担心人们会在不使用“关闭”或“保存”按钮的情况下关闭浏览器,那么锁定将永远不会被清除

当用户关闭会话时,是否有方法清除锁定?我没有看到这样的事件

还是有更简单的方法来锁定文档


我意识到我可以使用代理清除锁,但何时运行它?我会想一个晚上的某个时候,然后我相当肯定锁应该不再真正有效

您可以从webDAV的工作方式中选择一个页面。在这里,servlet管理一个锁定文档的“锁定列表”。锁在10分钟后自动过期。锁可以通过调用续订或终止。因此,当您编辑文档时,您会请求锁定,然后启动一个CSJS计时器,该计时器每8分钟调用一次重新锁定功能(这样您就有一定的错误余地),postSave会调用解锁(除非您保持在编辑模式)。 如果用户在10分钟后关闭浏览器,文档将自动解锁。由于您可以自由地实现锁定功能,因此您可以捕获用户/位置,并在“锁定失败”显示中使用该信息(您可以进一步推动该事件,并让原始作者知道它,或者执行一些“重试”选项)。
它的实现并不简单,但一旦实现了易用性,ApplicationScope可能是捕获“锁定”文档的好地方。毕竟,要使ApplicationScope过期,所有用户的会话都必须过期,因此任何打开页面的人都无法保存


可能会在有人编辑文档时捕获UNID、用户和时间。保存文档时清除值。请记住,用户可能会关闭浏览器等。我已经在内部讨论过这种方法,如果我们最终构建它,我希望将其添加到OpenNTF中。但我们不太可能在下个月内完成此操作。

我更愿意使用与威瑟斯先生的答案类似的解决方案。主要问题是如何处理不需要的和可怕的后退按钮。打开文档时很容易锁定,但关闭XPage的方法有很多,用户不仅限于您提供的导航,而且如他所说,还可以完全关闭浏览器,使用后退按钮所以,我能想到的最好的方法是创建一些java对象,我们将在应用程序和会话范围中使用这些对象

第一步是创建一个“LockedDocument”类。正如我们所知,文档是不可序列化的,我们不想将文档本身保存在此对象中,我们想保存UNID及其保存的时间。我们想这样做,以便能够在给定的时间(如三十分钟到一小时)后清除对象。此类还应实现可比较接口,以便在此时对集合进行排序,以便最早的文档排在第一位,最新的文档排在最后

接下来,我们创建另一个类,该类包含一个列表或一个带有这些锁定文档的映射。该类还必须有一个线程(实现可运行),该线程将每隔五分钟左右检查所有文档,我还没有对此进行测试,但它应该可以工作)。三十到六十分钟前(预定义)锁定的任何文档都将被解锁(从列表中删除)。必须如上所述对列表进行排序,并且当达到小于锁定时间的时间时,循环“中断”,以防止不必要的处理

下一步是在sessionScope中包含特定于用户的列表。此列表是当前用户拥有的锁定文档。当用户将文档状态更改为“可编辑”时设置该选项,并在文档设置为“可编辑”之前选中该选项,以防止同一用户在多个选项卡中打开一个文档。在QuerySave()上再次检查锁。一旦打开主页面,锁就会自动释放。onquerysave()还必须检查文档UNID是否在sessionScope列表中,或者在允许保存之前,文档是否是新的

快速回顾
保存在applicationScope LockedDocumentList中的任何UNID都不能被任何人编辑,除非它存在于他们自己的会话范围列表中。
可以警告用户锁定时间即将到来,并重置计时器。
包含带有锁定文档的列表的类必须是单例
也许有一些方法可以改进这个答案,我确信我遗漏了一些东西。这只是一个想法


可能有更好的方法来处理此问题,但这是我找到的最好的方法。

您可以在
窗口中删除Domino锁。onunload
事件:

window.onunload = function(){
    dojo.xhrGet(...
}

无需重新发明轮子。

以下是我正在使用的代码:

/* DOCUMENT LOCKING */
/*

    use the global object "documentLocking" with:
    .lock(doc) -> locks a document
    .unlock(doc) -> unlocks a document
    .isLocked(doc) -> returns true/false
    .lockedBy(doc) -> returns name of lock holder
    .lockedDT(doc) -> returns datetime stamp of lock

*/ 
function ynDocumentLocking() {

    /*

        a lock is an entry in the application scope

        with key = "$ynlock_"+UNID

        containing an array with
        (0) = username of lock holder
        (1) = timestamp of lock


    */

    var lockMaxAge = 60 * 120; // in seconds, default 120 min

    this.getUNID = function(v) {
        if (!v) return null;
        if (typeof v == "NotesXspDocument") return v.getDocument().getUniversalID();
        if (typeof v == "string") return v;
        return v.getUniversalID();
    }

    /* puts a lock into application scope */
    this.lock = function(doc:NotesDocument) {
        var a = new Array(1);
        a[0] = @UserName();
        a[1] = @Now();
        applicationScope.put("$ynlock_"+this.getUNID(doc), a);  
        // print("SET LOCK "+"$ynlock_"+doc.getUniversalID()+" / "+a[0]+" / "+a[1]);
    }   

    /* removes a lock from the application scope */
    this.unlock = function(doc:NotesDocument) {
        applicationScope.put("$ynlock_"+this.getUNID(doc), null);
        //print("REMOVED LOCK for "+"$ynlock_"+doc.getUniversalID());
    }

    this.isLocked = function(doc:NotesDocument) {
        try {
            //print("ISLOCKED for "+"$ynlock_"+doc.getUniversalID());       

            // check how old the lock is
            var v = applicationScope.get("$ynlock_"+this.getUNID(doc));
            if (!v) {
                //print("no lock found -> return false");
                return false;   
            }

            // if lock holder is the current user, treat as not locked
            if (v[0] == @UserName()) {
                //print("lock holder = user -> not locked");
                return false;
            }


            var dLock:NotesDateTime = session.createDateTime(v[1]);
            var dNow:NotesDateTime = session.createDateTime(@Now());
            // diff is in seconds
            //print("time diff="+dNow.timeDifference(dLock)+" dLock="+v[1]+" now="+@Now());
            // if diff > x seconds then remove lock, it not locked
            if (dNow.timeDifference(dLock) > lockMaxAge) {
                // print("LOCK is older than maxAge "+lockMaxAge+" -> returning false");
                return false;
            }
            //print("return true");
            return true;
        // TODO: check how old the lock is
        } catch (e) {
            print("ynDocumentLocking.isLocked: "+e);
        }

    }

    this.lockedBy = function(doc:NotesDocument) {
        try {
        var v = applicationScope.get("$ynlock_"+this.getUNID(doc));
        if (!v) return "";
        //print("ISLOCKEDBY "+"$ynlock_"+doc.getUniversalID()+" = "+v[0]);
        return v[0];

        } catch (e) {
            print("ynDocumentLocking.isLockedBy: "+e);
        }
    }

    this.lockedDT = function(doc:NotesDocument) {
        try {
        var v = applicationScope.get("$ynlock_"+this.getUNID(doc));
        if (!v) return "";
        return v[1];

        } catch (e) {
            print("ynDocumentLocking.isLockedBy: "+e);
        }
    }

}

var documentLocking = new ynDocumentLocking();

最好使用notes文档锁定来实际锁定文档,或者使用文档字段来提供伪文档锁定机制。如果浏览器过早关闭,CSJS计时器会发生什么情况?有两个计时器在工作。“自动过期”意味着servlet上也有一个。因此servlet将使锁过期。如果XPages是您唯一的访问权限,那么实际上您不需要任何字段或锁定机制。如果你的应用程序是混合的,使用文档锁定机制你说“你实际上不需要任何字段或锁定机制”,但我怎么知道有人在编辑文档?它是通过计时器实现的吗?servlet管理一个锁列表。锁列表中的每个条目都有一个由Java线程检查的到期时间。如果要编辑文档,请发送锁定请求。如果文档已被锁定,请求将失败,您可以显示“对不起,乔是第一个”消息。计时器仅在