你只想允许one打开浏览器窗口/选项卡user and database.
对于在浏览器中打开的每个 XPage,您必须测试是否已在另一个浏览器窗口/选项卡中打开相同的数据库。如果是这样,请拒绝使用以下命令打开 XPage:重定向到错误 XPage。
仅在服务器端不可能执行此操作,因为服务器不知道 Xpage 在哪个浏览器选项卡中打开。
因此,服务器需要客户端的帮助。客户端必须给服务器一个unique浏览器窗口/选项卡 ID.
浏览器窗口/选项卡没有唯一的 ID。但是,打开一个新窗口/选项卡我们可以创建一个随机编号并将其存储在浏览器中会话存储 http://www.nczonline.net/blog/2009/07/21/introduction-to-sessionstorage/。这是一个独特的存储空间every窗口/选项卡。
This 窗口/选项卡 ID可以通过部分刷新 GET 发送到服务器,并以应用程序范围变量的形式存储在服务器上供用户使用。
此外,服务器必须知道窗口/选项卡何时关闭,以便可以在另一个窗口/选项卡中打开相同的数据库。为此,客户端必须每隔 X 秒告诉服务器“我还活着”。
这是完整的解决方案:
创建自定义控件“UniqueBrowserTab”
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:eventHandler
event="onClientLoad"
submit="false">
<xp:this.script><![CDATA[
var secondsIamAliveInterval = 5;
var tabId = sessionStorage.getItem("tabId");
if (!tabId) {
tabId = Math.random();
sessionStorage.setItem("tabId", tabId);
}
function sendTabIdToServer() {
XSP.partialRefreshGet("#{id:browserTabControl}", {
params: {'tabId': tabId}
});
}
sendTabIdToServer();
setInterval(function() {
sendTabIdToServer();
}, secondsIamAliveInterval * 1000);
]]></xp:this.script>
</xp:eventHandler>
<xp:panel id="browserTabControl">
<xp:this.rendered><![CDATA[#{javascript:
var secondsIgnoreOtherSession = 7;
if (param.tabId) {
var userName = session.getEffectiveUserName();
var userData = applicationScope.get(userName);
var now = new Date().getTime();
if (userData) {
if (userData.tabId !== param.tabId) {
if (userData.time + secondsIgnoreOtherSession*1000 > now) {
context.redirectToPage("Error.xsp");
}
}
}
applicationScope.put(userName, {tabId : param.tabId, time: now});
}
return true
}]]></xp:this.rendered>
</xp:panel>
</xp:view>
将自定义控件“UniqueBrowserTab”包含到每个 XPage 中,或者例如进入应用程序布局的自定义控件。
<?xml version="1.0" encoding="UTF-8"?>
<xp:view
xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xc:UniqueBrowserTab />
...
</xp:view>
创建一个 Page Error.xsp,其中包含not包括自定义控件“UniqueBrowserTab”。
这将只允许用户在所有浏览器上为每个数据库使用一个浏览器窗口/选项卡。