为 HTTP 服务器上的每个文件设定正确的 content-type 头是很重要的,因为很多情况下区分文件类型正是靠它(而不是文件后缀)。

Domino 环境下默认带了常见文件的 content-type 配置,但总是有不全的。可以通过编辑 <domino data>/httpd.cnf 文件来实现,比如我们添加 json 文件类型就可以添加以下一行:

AddType .json application/json

参考链接:http://www-01.ibm.com/support/docview.wss?uid=swg21289700

我们知道所有的浏览器都有怪癖模式(Quirks Mode)和标准模式(Standards Mode)。怪癖模式是为了兼容老旧的网页,去模拟早期浏览器(如 IE5.5)的非标准实现;而标准模式会尽可能的按照标准去执行。而激活不同模式的关键正是 HTML 页面的 DOCTYPE。

现在已经是 2010 年了,可是 Domino 生成的默认的 DOCTYPE 还是:

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”>

在目前所有流行的浏览器下它都会触发怪癖模式。所以我们需要以下 Notes.ini 参数来改掉它:

DominoCompleteDoctype = 0 或 1 或 2

0 = !DOCTYPE HTML PUBLIC “W3CDTD HTML 4.01 TransitionaEN”
1 = !DOCTYPE HTML PUBLIC “-W3DTD HTML 4.01 TransitionalEN” “http://www.w3.org/TR/html4/loose.dtd
2 = !DOCTYPE HTML PUBLIC “W3CDTD HTML 4.0EN” “http://www.w3.org/TR/html4/strict.dtd

我们只是想要触发标准模式,那么用 1 就可以了。不过由于是通过 Notes.ini 修改的,肯定会影响到所有的表单,想要更改个别的表单可以使用 $$HTMLFrontMatter 域。

参考链接:Working with the DOCTYPEHTMLOptions and HTMLTagAttribute fields用doctype激活浏览器模式

从 8.0 版开始,出于对旧版本兼容性的考虑,在 Designer 中编写 Java 代理时,编译器会生成与 Domino 6(JVM 1.2) 兼容的 class 文件。我们可以通过以下 Notes.ini 参数来修改它(以 1.5 为例,重启客户端生效):

JavaCompilerTarget=1.5

对于兼容版本的设定,这里有个权衡需要把握:版本设定的越高可用的新特性越多,但同时能够兼容的 Domino 版本越少。大家可以按照实际需要,参考下表来选择。

JavaCompilerTarget=
等同的 javac 参数
兼容的 Notes/Domino 版本
1.1
-source 1.3 -target 1.1
N/D 5.0 及以上
1.2
-source 1.3 -target 1.2
N/D 6.0 及以上
1.3
-source 1.3 -target 1.3
N/D 6.0 及以上
1.4
-source 1.4 -target 1.4
N/D 7.0 及以上
1.5
-source 1.5 -target 1.5
N/D 8.0 及以上
1.6
-source 1.6 -target 1.6
N/D 8.5 及以上
CurrentJavaVersion
(取当前版本 Notes 附带的 Java版本,以 N/D 8.5 为例,此值等同于 1.6)
-source 1.6 -target 1.6
N/D 8.5 及以上

参考链接:JavaCompilerTarget

在最近客户提交的一份安全检查报告中,有一条是检测到 Domino HTTP 服务器启用了 Trace 方法,可能存在安全漏洞。虽然在 IBM 技术支持文档中宣称此处不存在安全漏洞,但也提供了禁用它的方法:

  • 使用了 Internet 站点配置:在站点配置文档的配置标签页中,禁止 Trace 方法
  • 未使用 Internet 站点配置:在 Notes.ini 中加入一行 HTTPDisableMethods=TRACE

请参考:How to enable or disable HTTP methods

Domino 8.5 版引入了新的设计元素:xPage。我承认这是个很强大的东西,但在很多生产服务器我们还没有用到它。而我向来有关闭这种不使用的功能的洁癖,所以通过以下参数可以将其禁用:

INOTESDISABLEXPAGECMD=1

设置参数后重启 HTTP 服务即可生效。

在开发过程中我们经常使用 msgbox 语句来调试代理,由于种种原因有时这些调试语句会被带入测试/生产环境。这种问题一旦发生,一般来说很难定位它究竟来自哪个代理。

此时我们可以在 notes.ini 中添加

Debug_Agent_Thread=1

参数来打开 Web 代理调试功能,在代理开始和结束时,控制台会打印出代理的名称、所在数据库以及 thread id。有了这些信息,我们就很容易定位调试语句的来源了。

请参考:Lotus Notes.ini Entry – Debug_Agent_Thread

前些天在讨论 Domino 环境中各种 ID 时,提到了一些关于如何处理复制冲突的内容,由于其原理比较复杂,当时就没有展开讨论。今天有读者询问其中的细节,所以在这篇文章中我们就仔细研究一下这个话题。

上一次说到在复制过程中如果发现两个副本关系的文档其 OID 不同,那么说明这两个文档处于不同步的状态。首先分析两个文档的 $Revisions 域(此域记录了文档历次修改的时间),判断是否存在冲突:

  • 如果两个域值除了某一个文档多出来一些值以外,其余部分完全相同,如:

    A:时间1,时间2,时间3
    B:时间1,时间2,时间3,时间4,时间5

    则表示 B 文档在 A 文档的基础上额外多修改了两次,不存在冲突

  • 如果两个域值最初相同,然后各自出现了不同的部分,如:

    A:时间1,时间2,时间3,时间4
    B:时间1,时间2,时间3,时间5

    则表示两个文档在不同的时间分别修改过,存在冲突

如果存在冲突,下一步检查目标文档(就是这次复制过程中会被修改的那个)的 $ConflictAction 域,如果其值为“1”表示允许合并复制冲突,开始分析两个文档各个域值,以判断能否进行合并:

  • 首先通过 $Revisions 域和 Sequence Number 找出两个文档最后一致的版本,以下面数据为例:

    A $Revisions:时间1,时间2,时间3,时间4
    A SN:5
    B $Revisions:时间1,时间2,时间3,时间5
    B SN:5

    两个文档在时间3这一版本是一致的,从 SN = 5 往回反推可以得到一致版本为 4

  • 每个文档域也有一个 SN 属性,它记录了此域最后一次修改时文档的 SN。用文档域的 SN 与之前得到的一致版本号 4 进行比对,就可以得到在一致版本之后修改的域。
  • 如果两个文档修改过的域有重合的部分,说明在不同的副本中对相同的域同时做了修改,无法合并冲突;反之则可以合并

如果 $ConflictAction 域值不是“1”或者属于上一段所述无法合并冲突的情况,则必须创建冲突文档。下一步就是通过 Sequence Number 和 Sequence Datetime 来分析哪个文档作为主文档(winner),哪个文档作为冲突文档(loser):

  • SN 比较大的(在一致版本之后编辑次数较多的)文档是 winner
  • 如果 SN 相同,SD 比较大的(最后编辑的)文档是 winner

至此,一个崭新的复制冲突文档诞生了。

在 Domino 应用开发中,有很多方法可以对数据进行查询。@dblookup 和 NotesView.getAllDocumentsByKey 利用了预先建好的视图索引,所以在各种查询数据的方法中,它们的性能是最出色的,也是我们最常用的。

最近在工作中遇到了一个于此相关的问题,请大家也注意:如果查询的视图具有多层分类,那么 @dblookup 和 getAllDocumentsByKey 只能返回第一个子分类下的结果。以如下数据为例:

分类1
  分类1.1
    文档1.1.1
  分类2.2
    文档1.1.2
分类2

如果以“分类1”作为查询条件,则只有“文档1.1.1”会返回,同样符合条件的“文档1.1.2”则丢失。

请参考:Troubleshooting @DbLookup, @DbColumn, GetAllDocumentsByKey