开支报告的例子表示了客户机如何从服务器得到属性属性可沿两个方向传递客户机也可将新的类型传递给用户最简单的例子就是如图所示的计算服务器该服务程序可执行任意任务这样整个企业内的客户机都能利用高端或专用计算机
任务由一个简单的本地(非远程)接口定义
public interface Task {
Object run();
}
运行时它就会进行一些计算并返回一个包含结果的对象这完全是一般性的任务几乎所有计算任务都可在这个接口下实现远程接口ComputeServer也同样简单
import javarmi*;
public interface ComputeServer extends Remote {
Object compute(Task task) throws RemoteException;
}
这个远程接口的唯一目的就是使客户机创建一个Task (任务)对象并把它发送给服务器执行最后返回结果该服务器的基本实现如下
import javarmi*;
import javarmiserver*;
public class ComputeServerImpl
extends UnicastRemoteObject
implements ComputeServer
{
public ComputeServerImpl() throws RemoteException { }
public Object compute(Task task) {
return taskrun();
}
public static void main(String[] args) throws Exception {
// use the default restrictive security manager
SystemsetSecurityManager(new RMISecurityManager());
ComputeServerImpl server = new ComputeServerImpl();
Namingrebind(ComputeServer server);
Systemoutprintln(Ready to receive tasks);
return;
}
}
如果您看一看compute方法就会发现它非常简单它只是接受传递给它的对象并返回计算的结果main方法包括服务器的启动代码它安装了RMI的缺省安全管理程序以防止他人存取本地系统并创建可处理进入的请求的ComputeServerImpl对象并将其与名字ComputeServer关联这时服务器已经准备好接收要执行的任务而main 也完成了其设置
如上所述这实际上是一种全面和实用的服务系统可以得到改进比如可添加要计算的参数从而对使用服务程序的部门进行计费但在很多情况下上述接口和及其实现允许使用高端计算机进行远程计算这又?明了RMI的简单性如果您键入上述类对其进行编译并启动服务程序您就拥有了能执行任意任务的运行计算服务器
下面介绍一个使用这种计算服务的例子假定您购买了一个能运行大量计算操作应用程序的非常高端的系统管理员可在该系统上启动一个Java虚拟机运行ComputeServerImpl对象该对象现在就可接受要运行的任务
现在假定一个小组准备通过一组数据培训一个神经网络以帮助制订采购策略他们可以采用的步骤如下
定义一个类暂且称之为PurchaseNet它能接受一组数据并运行培训数据返回一个经过培训的神经网络PurchaseNet 将实现Task (任务)接口并在其run方法中执行其工作他们可能还需要一个Neuron类来描述所返回的网络中的节点而且很可能需要其它类来描述处理过程run方法将返回一个由一组经过培训的Neuron对象组成的NeuralNet对象
当这些类被编写好并进行小规模测试时用一个PurchaseNet 对象调用ComputeServer的compute方法
当ComputeServerImpl对象中的RMI系统接收到作为进入参数的 PurchaseNet对象时它就下载PurchaseNet的实现并调用该服务器的compute方法并把该对象作为Task (任务)参数
Task也就是PurchaseNet对象将开始执行其执行程序当执行程序需要诸如Neuron和NeuralNet等新的类时它们可根据需要下载
所有计算都将在计算服务器上执行而客户机线程则等待结果(客户机系统上的另一个线程则会显示正在等待光标或使用Java的内置并行机制执行另一个任务 )当运行返回其NeuralNet对象时这个对象将作为compute 方法的结果被传递回客户机
这不需要在服务器上安装其它软件所有必须完成的任务都由各部门在其自己的计算机上完成随后再根据需要传递给计算服务器主机
这个简单的计算服务器体系结构为系统的分布式功能提供了功能强大的转换能力一项任务的计算可以被转移到一个能为其提供最好支持的系统上完成这样的系统可以被用来
在ComputeServerImpl对象运行于有数据挖掘需要的主机上支持数据挖掘应用程序这样可使您轻松地把任何计算移动到数据所在的地方
在从当前股票价格发货信息或其它实时信息等外部资源获得直接数据的服务器上运行计算任务
通过运行ComputeServer (接受进入的请求并将其转送到运行 ComputeServerImpl的负担最小的服务器上)的不同实现而将任务分布在多个服务器上
代理
因为RMI允许使用Java实现下载属性所以您可使用RMI 编写代理系统代理的最简单格式如下
import javarmi*;
public interface AgentServer extends Remote {
void accept(Agent agent)
throws RemoteException InvalidAgentException;
}
public interface Agent extends javaioSerializable {
void run();
}
启动一个代理也就创建了实现Agent (代理)接口找到服务器激活接受该代理对象的类该代理的执行程序将被下载到服务器上运行accept方法将启动一个该代理的新线程激活其run方法然后返回从而使该代理一直执行到run方法返回为止代理可通过激活在另一台主机上运行的服务程序的accept方法而移植到该主机而其本身则作为将被接受的代理来传递并结束其在原来主机上的线程
面向对象的代码重用与设计模式
面向对象的编程是一项允许代码重用的强大技术很多企业组织都使用面向对象的编程来减轻创建程序的负担和提高系统的灵活性RMI是完全面向对象的信息被发送给远程对象而且对象可以被传递和返回
Design Patterns (设计模式)目前在描述面向对象设计的实践活动中获得了相当大的成功首先是因为Design Patterns 的创新工作而使之大受欢迎这些编程方式是一种正式描述解决某类特定问题的完整方法的途径所有这些设计模式都依赖于创建一个或多个抽象概念这些抽象概念允许不同的实现从而允许和增强软件重用软件重用是面向对象技术的主要优势而设计模式则是促进重用的最受欢迎的技术之一
所有设计模式都依赖面向对象的多态性这是对象( 如Task )拥有多个实现的能力算法的普通部分(如compute 方法)不必知道使用了哪个实现它只需知道得到一个对象后应该对该对象采取什么操作特别地计算服务器就是Command (指令)模式的一个例子它可使您将请求 (任务)表示为对象并对其进行调度
只有当包括执行程序在内的完整对象能在客户机和服务器之间传递时才会存在这样的多态性DCE和DCOM等传统的RPC系统以及CORBA等基于对象的RPC系统不能下载并执行程序因为它们不能把真实对象作为参数传递而只能传递数据
RMI可传递包括执行程序在内的所有类型所以您可以在分布式计算解决方案中而不仅仅是本地计算中使用面向对象的编程包括设计方式如果没有RMI这样完全面向对象的系统那么您就必须放弃很多分布式计算系统中的设计方式以及面向对象的软件重用的其它形式