文档

Java™教程
隐藏目录
设计远程接口
路径: RMI
部分: 编写一个RMI服务器

设计一个远程接口

计算引擎的核心是一种协议,它使得任务可以提交给计算引擎,计算引擎可以运行这些任务,并将任务的结果返回给客户端。这个协议通过计算引擎支持的接口来表达。下图显示了该协议的远程通信。

客户端和计算引擎之间的远程通信

每个接口包含一个方法。计算引擎的远程接口Compute允许将任务提交到引擎。客户端接口Task定义了计算引擎执行提交任务的方式。

compute.Compute接口定义了远程可访问的部分,即计算引擎本身。下面是Compute接口的源代码:

package compute;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Compute extends Remote {
    <T> T executeTask(Task<T> t) throws RemoteException;
}

通过扩展java.rmi.Remote接口,Compute接口将自身标识为可以从另一个Java虚拟机调用方法的接口。实现这个接口的任何对象都可以是远程对象。

作为远程接口的成员,executeTask方法是一个远程方法。因此,该方法必须被定义为能够抛出java.rmi.RemoteException异常。这个异常在远程方法调用时由RMI系统抛出,表示发生了通信故障或协议错误。RemoteException是一个受检异常,因此调用远程方法的任何代码都需要通过捕获或在throws子句中声明来处理这个异常。

计算引擎所需的第二个接口是Task接口,它是Compute接口中executeTask方法的参数类型。compute.Task接口定义了计算引擎和需要执行的工作之间的接口,提供了启动工作的方式。下面是Task接口的源代码:

package compute;

public interface Task<T> {
    T execute();
}

Task接口定义了一个名为execute的方法,该方法没有参数,也不抛出任何异常。因为该接口没有扩展Remote接口,所以该接口中的方法不需要在其throws子句中列出java.rmi.RemoteException

Task接口有一个类型参数T,代表任务计算的结果类型。这个接口的execute方法返回计算的结果,因此它的返回类型是T

Compute接口的executeTask方法返回传递给它的Task实例的执行结果。因此,executeTask方法有它自己的类型参数T,将自己的返回类型与传递的Task实例的结果类型关联起来。

RMI使用Java对象序列化机制在Java虚拟机之间传输对象。要使一个对象可序列化,它的类必须实现java.io.Serializable标记接口。因此,实现Task接口的类也必须实现Serializable接口,任务结果的类也必须实现Serializable接口。

Compute对象可以运行不同种类的任务,只要它们是Task类型的实现。实现这个接口的类可以包含计算任务所需的任何数据,以及计算所需的其他方法。

这就是RMI使这个简单的计算引擎成为可能的方式。因为RMI可以假设Task对象是用Java编程语言编写的,之前对计算引擎未知的Task对象的实现会在需要时由RMI下载到计算引擎的Java虚拟机中。这种能力使计算引擎的客户端能够定义在服务器上运行的新类型的任务,而不需要将代码显式安装在该机器上。

计算引擎由ComputeEngine类实现,它实现了Compute接口,通过调用其executeTask方法可以提交不同的任务给它。这些任务使用任务的execute方法来运行,并将结果返回给远程客户端。


上一页:编写一个RMI服务器
下一页:实现一个远程接口