使用 Java 可以访问 Domino 中的对象,如数据库、视图、文档等。本文简述了用 Java 访问 Domino 对象的基本编程方法。本文中的内容主要是根据 Lotus Domino/Notes 6 编写的,使用 R5 时会略有不同。
Java 对 Domino 对象的访问是通过调用 lotus.domino 包来进行的。在运行环境中,lotus.domino 包中的接口是通过两个包来实现的:
对于本地连接,Java 程序将在Notes客户端或Domino服务器所在的计算机运行,使用JNI 对Notes/Domino的代码进行访问。
对于远程连接,Java 程序通过 CORBA 访问 Domino 所提供的服务。远程访问包括两个过程:
在 lotus.domino 中,NotesFactory 类提供了 createSession 以及其他方法,可以用来开始 Java 应用程序或 servlet 对 Domino 对象的访问。不同的调用方式决定了访问是本地的还是远程的。
要使用 lotus.domino 包来编译 Java 程序,类路径(classpath)中必须包含 Notes.jar (本地)或 NCSO.jar (远程)。例如:
set classpath=%classpath%;c:\lotus\domino\Notes.jar
或者
set classpath=%classpath%;c:\lotus\domino\data\domino\java\NCSO.jar
其中Notes.jar可以在Notes/Domino安装的程序目录中找到。NCSO.jar 在Domino服务器或Domino Designer的数据目录下,domino\java 子目录中。
本地调用
使用 createSession 时,没有参数、第一个参数为 null、或第一个参数为空字符串都表示本地调用。以下代码是等价的:
Session s = NotesFactory.createSession() Session s = NotesFactory.createSession((String)null) Session s = NotesFactory.createSession("")
要从应用程序和 servlet 中执行本地调用,路径(path)中必须包含 Notes/Domino 的程序目录,类路径(classpath)中必须包含 Notes.jar。例如,当 Domino 安装在"c:\lotus\domino"中时:
set path := %path%;c:\lotus\domino
set classpath := %classpath%;c:\lotus\domino\Notes.jar
Notes.jar中包含 lotus.domino 和 lotus.domino.local 包。
本地调用要求使用 NotesThread 类来管理线程。NotesThread 类扩展了 java.lang.Thread,包含了专门针对 Domino 的的初始化和终止代码。您可以有三种不同方式来使用它:
通过继承来执行线程
要通过继承来执行线程,需要扩展 NotesThread(而不是 Thread),包含 runNotes 方法(而不是 run 方法)。NotesThread 线程可以和其他线程一样通过 start 方法来启动。这种方式较为易用,也比较不容易出错。
import lotus.domino.*;
public class myClass extends NotesThread
{
public static void main(String argv[])
{
myClass t = new myClass();
t.start();
}
public void runNotes() // entry point for Notes thread
{
Try
{
Session s = NotesFactory.createSession();
// Operational code goes here
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
通过 Runnable 接口来执行线程
要通过 Runnable 接口来执行线程,需要实现 Runnable 并包含 run 方法,这和其他使用线程的类完全一样。当您需要扩展其他类,不能扩展 NotesThread 类时可以使用这种方式。
import lotus.domino.*;
public class myClass implements Runnable
{
public static void main(String argv[])
{
myClass t = new myClass();
NotesThread nt = new NotesThread((Runnable)t);
nt.start();
}
public void run() // entry point for thread
{
try
{
Session s = NotesFactory.createSession();
// Operational code goes here
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
通过静态方法来执行线程
要通过静态方法来执行线程,需要调用 sinitThread() 来初始化线程,调用 stermThread() 来结束线程。stermThread() 的调用必须与 sinitThread() 的调用严格一一对应。推荐将 stermThread() 放在"finally"程序块里。静态方法适用于不可能进行继承,或需要控制事件驱动的线程时。
import lotus.domino.*;
public class myClass
{
public static void main(String argv[])
{
try
{
NotesThread.sinitThread(); // start thread
Session s = NotesFactory.createSession();
// Operational code goes here
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
NotesThread.stermThread(); // must terminate every thread
}
}
}
进行本地调用的每个线程都必须初始化一个 NotesThread 对象。它包含了访问 Domino 对象的 AWT 线程。侦听线程必须使用静态方法,因为它们不可能从 NotesThread 继承。
既进行本地调用又进行远程调用的应用程序可以动态地决定何时使用静态方法 sinitThread 和 stermThread。当一个本地线程运行时,也可以进行远程调用。但不要将一个会话中得到的对象用于其他会话的调用。
应该尽量避免多线程的使用,除非有非常充分的理由。要遵循以下原则:
远程调用
调用createSession时,第一个参数使用非空的字符串,就表示所进行的是远程调用。第一个参数表示的是 Domino 服务器所在的计算机。例如:
Session s = NotesFactory.createSession("myhost.east.acme.com")
或者
Session s = NotesFactory.createSession("myhost.east.acme.com:63148")
后边的例子中指定了端口号,这样Domino服务器上就不需要启动 Web 服务了。详细信息见本文后面的"获取IOR"部分。
要从应用程序或 servlet 中执行远程调用,运行程序的计算机的类路径里必须包括 NCSO.jar。 NCSO.jar 中包含 lotus.domino 包,lotus.domino.cso 包,lotus.domino.corba 包,以及 ORB 类。对于已安装的 Domino Designer 和 Domino 服务器,NCSO.jar 在 Domino 数据目录下的 domino\java 子目录中。如果计算机上没有安装 Domino 软件,必须手工将此文件从其他计算机上复制过来。 类路径中必须包含NCSO.jar,例如:
set classpath := %classpath%;c:\lotus\domino\data\domino\java\NCSO.jar
编程
远程调用时不使用 NotesThread,只需要在 createSession 中指定主机名和端口号(可选)。
不使用线程时,程序大致上是以下格式:
import lotus.domino.*;
public class myClass
{
public static void main(String argv[])
{
try
{
String host = "myhost.east.acme.com:63148";
Session s = NotesFactory.createSession(host);
// Operational code goes here
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
使用线程时,程序为:
import lotus.domino.*;
public class myClass implements Runnable
{
public static void main(String argv[])
{
myClass t = new myClass();
Thread nt = new Thread((Runnable)t);
nt.start();
}
public void run()
{
try
{
String host = "myhost.east.acme.com:63148";
Session s = NotesFactory.createSession(host);
// Operational code goes here
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
管理
远程访问 Domino 时还需要对服务器进行一些配置。运行 Domino 的计算机必须可以通过 TCP/IP 协议进行访问。在计算机的网络设置中,需要检查 TCP/IP 属性中主机名和域名的设置。必须能够从客户端的计算机 ping 到 Domino 服务器的 Internet 名称。例如,服务器的主机名是 myhost,域名是 east.acme.com,则服务器的 Internet 名称是 myhost.east.acme.com。以下命令必须能够得到有效的回应:
> ping myhost.east.acme.com
在 Domino 目录(names.nsf)中,服务器文档的"全限定的 Internet 主机名"域中必须输入上述 Internet 名称。
如图:
在本文前面的编程的例子中,服务器的 Internet 名称被用于 createSession 的第一个参数。这里也可以使用服务器的 IP 地址。
要进行远程访问,在 Domino 服务器上,DIIOP 任务必须启动。HTTP 任务也可能需要启动,这取决于程序获取 IOR 的方式。要确认HTTP和DIIOP所使用的端口号,可以打开 Domino 目录中的服务器文档,进入"端口"下面的"Internet 端口",在 Web 标签和 DIIOP 标签下可以看到当前使用的端口号。缺省情况下,HTTP 的端口号是 80,DIIOP 的端口号是 63148。
如果不知道要访问的数据库的名称,(例如要使用 .getFirstDatabase),必须有浏览数据库的权限。可以在"Internet 协议"-"HTTP"标签下设置这个权限,将"允许HTTP客户浏览数据库"设为"是"。
要确保服务器上启动了 HTTP 和 DIIOP 任务,可以将它们加到 Notes.ini 文件中 ServerTasks 参数里。例如,Notes.ini 中应该有类似这样的一行:
ServerTasks=Update,Replica,Router,AMgr,AdminP,CalConn,Sched,DIIOP,HTTP,
LDAP
如果服务器已启动,可以用以下控制台命令启动这两个任务:
> load http
> load diiop
也可以用以下控制台命令停止这两个任务:
> tell http quit
> tell diiop quit
用此命令可以更新 DIIOP 任务的设置:
> tell diiop refresh
用此命令可以重新启动 HTTP 任务:
> tell http restart
获取 IOR
在 Domino 服务器上,IOR 是一个名为 diiop_ior.txt 的文件,它位于 Domino 数据目录下的 domino\html 子目录中。IOR 是一个编码的字符串,包含对服务器的 CORBA 访问的识别信息。客户端会将 IOR 字符串解码,并用它来建立远程连接。
缺省情况下,远程客户端通过 Web 服务来请求 IOR ,然后通过 DIIOP 端口进行会话请求。这两个请求可以分开进行。 例如:
String ior = NotesFactory.getIOR("myhost.east.acme.com"); // Get IOR using Web server port
Session s = NotesFactory.createSessionWithIOR(ior); // Create session using DIIOP port
等价于:
Session s = NotesFactory.createSession("myhost.east.acme.com");
在 NotesFactory 的调用中,可以在主机名后面加上冒号和端口号来指定用于获取 IOR 的端口。通过这样的机制,可以通过 DIIOP 端口来获取 IOR ,而不通过 HTTP 端口。例如:
String ior = NotesFactory.getIOR("myhost.east.acme.com:63148"); // Get IOR using DIIOP port
Session s = NotesFactory.createSessionWithIOR(ior); // Create session using DIIOP port
也可以简化为:
Session s = NotesFactory.createSession("myhost.east.acme.com:63148");
注意不可以使用 DIIOP 端口来获取除 diiop_ior.txt 以外的的其他文件。
如果通过 Web 服务端口来获取 IOR,Web 服务必须允许匿名访问。打开服务器文档,在"端口"-"Internet 端口"-"Web"标签下,"匿名"的验证选项要设置为"是"。
通过 DIIOP 端口获取 IOR 是 Notes/Domino 6 的新功能。这样可以不必允许对 HTTP 服务的匿名访问,甚至不必启动 HTTP 服务。
也可以通过其他方法获取 IOR,然后使用 createSessoinWithIOR。例如,可以直接将 diiop_ior.txt 文件从服务器的计算机上拷贝到客户端的计算机上。如果客户端上已经有了有效的 diiop_ior.txt,可以用以下代码与服务器建立远程连接:
import lotus.domino.*;
import java.io.*;
public class platformior
{
public static void main(String argv[])
{
try
{
FileInputStream fin = new FileInputStream("c:\\Lotus\\NotesR6\\diiop_ior.txt");
InputStreamReader fisr = new InputStreamReader(fin);
BufferedReader br = new BufferedReader(fisr);
String ior = br.readLine();
fin.close();
Session s = NotesFactory.createSessionWithIOR(ior);
//Operational code goes here
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
注意 IOR 可能会改变。以下动作都会使原来的 diiop_ior.txt 无效:
最后一项可以通过以下方法避免:打开服务器文档,在"Internet 协议"-"DIIOP"标签下,在"主机名称/地址"域中指定服务器的 Internet 主机名。
这强制了diiop_ior.txt使用主机名而不是 IP 地址。这样,只要主机名不改变,IOR 就不会改变。也可以通过 Notes.ini 参数 DIIOPIORHost 来强制使用主机名。
访问控制
客户端的程序可以得到什么存取级别取决于createSession 的使用方式和服务器/客户端的设置。访问控制是通过以下两种方式之一实现的:
这种方式只在进行本地调用时可以使用。程序所在的计算机上有 Notes 客户端或 Domino 服务器都可以。 通过 Domino 目录访问
通过 Domino
目录访问时,所使用的代码将决定是作为匿名用户还是 Domino 目录中已有的用户来访问。NotesFactory调用中,如果只指定了主机名,或使用空字符串作为用户名和口令,将以匿名用户的身份访问服务器。例如:
Session s = NotesFactory.createSession("myhost.east.acme.com:63148");
或者:
Session s = NotesFactory.createSession("myhost.east.acme.com:63148", "", "");
要以某个 Domino 用户的身份访问服务器,需要在参数2和参数3中分别指定用户名和 Internet 口令。用户名和口令必须与 Domino 目录中的某个个人文档匹配。例如:
Session s = NotesFactory.createSession("myhost.east.acme.com:63148", "Jane Smith/East/Acme",
"topS3cr3t");
对 Domino 服务器进行本地调用时,主机名应为空: Session s = NotesFactory.createSession("", "Jane Smith/East/Acme", "topS3cr3t") 要进行匿名的本地调用,三个参数都应为空:
Session s = NotesFactory.createSession("", "", "")
进行本地调用时,服务器不一定要运行。 服务器文档中的设置决定了是否可以进行匿名或用户名/口令的访问。在服务器文档中,"端口"-"Internet 端口"-"DIIOP"标签下,验证选项与代码的关系如下表:
|
对于名称和口令验证,名称必须是 Domino 目录中某个个人文档中的用户名,口令必须是此个人文档中的 Internet 口令。管理员还可以将"强制使用服务器访问设置"选项设为"是",以强制 DIIOP 的访问遵循服务器文档的安全性标签下的"服务器访问"设置。
服务器文档中的以下域可以用来控制 Internet 会话的安全性。从本质上来说,本地或远程 Java 类创建的Internet 会话的访问权限等同于 Web 用户。
|
* 哪些方法是受限制的请参考 Domino 6 Designer Help 中的"Restricted LotusScript and Java agent operations" 。
服务器文档中"端口"-"Internet 端口"下,DIIOP 标签中的域的说明如下表:
|
以下notes.ini参数也会影响远程或本地Java 类建立的Internet会话的安全性:
|
注意在数据库的存取控制表中,"Internet 用户的最大权限"设置也会对 Internet 会话的权限产生影响,DIIOP 的登录用户的权限不能超过此项设置。
服务器大约每一个半小时刷新一次安全性的缓存。修改了安全性设置后,可以使用控制台命令"tell diiop refresh"来强制刷新。
通过 Notes ID 访问
要通过当前 Notes ID 访问服务器,在调用时应不指定任何参数:
Session s = NotesFactory.createSession()
在这种情况下,如果需要验证(如打开数据库时),会弹出一个对话框,提示输入Notes ID的口令。所使用的Notes ID是在搜索路径中能找到的第一个Notes.ini文件中,KeyFileName变量指定的。例如,Notes.ini 中有以下参数时,程序将使用 admin.id 来访问服务器:
KeyFileName=admin.id
必须输入该ID的口令,或按"取消",程序才能继续执行。 也可以将第二个参数指定为"(String)null",在第三个参数中指定该Notes ID的口令:
Session s = NotesFactory.createSession((String)null, (String)null, "tops3cr3t")
在服务器上,以上方法会按读者域限制访问,要进行完全的访问,可以用以下方法:
Session s = NotesFactory.createSessionWithFullAccess()
或者
Session s = NotesFactory.createSessionWithFullAccess("tops3cr3t")
结论
您现在了解了用Java应用程序对Domino对象进行本地调用和远程调用的基本方法。关于较复杂的访问方式,如SSL加密,servlet,连接池,单一登录,防火墙,超时控制,资源回收及问题诊断,请参考以下文章:
http://www-10.lotus.com/ldd/today.nsf/lookup/Java_access_2 (美国)