我正在努力掌握Java RMI的基础知识。
这个想法是让两个独立的进程运行,每个进程都由两个类中的一个单独的main启动:
-
Client
作为客户端运行 -
Server
作为服务器运行
第三个类Document
作为共享对象(它是Strings
的一个简单收集器),其方法addTimestamp()
保存当前的Timestamp
以便在控制台中进一步打印。此方法也可以作为远程方法使用,如DocumentInterface
中所定义的。
在两个不同的cmd
窗口上执行两个main会产生一个完美的系统:
-
Server
:java -cp rmi.jar Server
-
Client
:java -cp rmi.jar Client
CLIENT -查看日期:2016.09.30 01.53.01
SERVER -查看日期:2016.09.30 01.53.01
当我在不同的时区启动服务器时:
Server
:java -Duser.timezone=PST -cp rmi.jar Server
Client
:java -cp rmi.jar Client
我仍然得到原始的客户端输出:
CLIENT -查看日期:2016.09.30 01.53.01
SERVER -查看日期:2016.09.30 01.53.01
我希望第二行具有服务器的基于pst的Timestamp
。我检查了这个标志是正确设置的,让它直接由服务器的主程序打印,它确实是不同的:
2016.09.29 16.55.57
从我所理解的到目前为止,当远程调用远程对象上的addTimestamp()
方法:
- 当前
Document
通过复制传递到服务器 -
Timezone
由服务器添加,使用Document
类的实例 - 返回的
Document
通过复制传递回客户端 - 客户端显示
Document
Timezone
基于服务器的设置,而不是客户端的设置。为什么不是这样呢?下面是这四个类的一些代码片段:
Document.java :
public Document addTimestamp(Document document) throws RemoteException
{
String timestamp = new SimpleDateFormat("yyyy.MM.dd HH.mm.ss").format(new Date());
document.strings.add("Viewed on: "+timestamp);
return document;
}
DocumentInterface.java :
public interface DocumentInterface extends Remote
{
public Document addTimestamp(Document document) throws RemoteException;
}
Server.java - main
:
Registry registry = LocateRegistry.createRegistry(1099);
Document document = new Document();
Naming.bind("rmi:///Document", document);
Client.java - main
:
Document document = new Document();
DocumentInterface remoteDocument;
try
{
remoteDocument = (DocumentInterface) Naming.lookup("rmi:///Document");
document.addString("USER - ");
document.addTimestamp(document);
document.addString("n");
document.addString("SERVER - ");
document = remoteDocument.addTimestamp(document);
System.out.println(document.toString());
}
catch (Exception except)
{
}
因为Document
是一个导出的远程对象,所以它在客户端作为回调运行。而不是在服务器上复制。
删除远程接口和extends UnicastRemoteObject
,并使其可序列化