您现在的位置是:主页 > news > 北京建设企业协会网站首页/网站建设网站推广

北京建设企业协会网站首页/网站建设网站推广

admin2025/6/10 1:54:16news

简介北京建设企业协会网站首页,网站建设网站推广,销售管理系统设计,网站建设第一品牌一、Java RMI 概览 Java RMI 指的是远程方法调用 (Remote Method Invocation)。它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。所以,RMI相关对象必须运行在Java虚拟机中。 在Java中,只要一个类exte…

北京建设企业协会网站首页,网站建设网站推广,销售管理系统设计,网站建设第一品牌一、Java RMI 概览 Java RMI 指的是远程方法调用 (Remote Method Invocation)。它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。所以,RMI相关对象必须运行在Java虚拟机中。 在Java中,只要一个类exte…

一、Java RMI 概览

Java RMI 指的是远程方法调用 (Remote Method Invocation)。它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。所以,RMI相关对象必须运行在Java虚拟机中。

在Java中,只要一个类extends了java.rmi.Remote接口,即可成为存在于服务器端的远程对象,供客户端访问并提供一定的服务。JavaDoc描述:Remote 接口用于标识其方法可以从非本地虚拟机上调用的接口。任何远程对象都必须直接或间接实现此接口。只有在“远程接口”(扩展 java.rmi.Remote的接口)中指定的这些方法才可远程使用。

二、关于远程接口、对象和方法

在RMI中,当对象在虚拟机之间传递时,接收端虚拟机并不是复制一个远程对象,而是通过RMI接收一个远程对象的stub。这个stub就是对远程对象的引用,它其实是一个对远程对象的代理。接收端在本地调用了stub的方法,也就相当于调用了远程对象的方法。

接收端持有的远程对象的stub和远程对象实现的必须是同一组接口,这样才能将stub转换成远程对象接口类型,从而实现通过stub调用远程对象的方法。

三、编写一个RMI的步骤

1. 定义一个远程接口,此接口需要继承Remote,接口中的方法需要抛出一个`RemoteException`
2. 开发远程接口的实现类,这个类必须继承`UnicastRemoteObject`
3. 创建一个server并把远程对象注册到端口
4. 创建一个client查找远程对象,调用远程方法

下面我们就按照以上四步写一个分布式的Hello Word的例子来演示一下这个过程

3.1 定义一个远程接口

编写RMI应用的第一步就是先定义远程接口。远程接口必须继承java.rmi.Remote接口,并且声明自己的远程方法。为了处理远程方法发生的各种异常,每一个远程方法必须抛出一个java.rmi.RemoteException异常。

public interface HelloService extends Remote{String sayHello(String name) throws RemoteException;
}

这个远程接口只定义了一个远程方法 sayHello(),远程方法在调用的时候有可能失败比如发生网络问题或者server挂掉,此时远程方法会抛出RemoteException异常。

3.2 开发接口的实现类

开发接口的实现类,即具体的远程对象,在远程对象中实现远程接口中定义的方法。

public class HelloServiceImpl implements HelloService{public String sayHello(String name) {return "hello:"+name;}
}

3.3 创建一个Server并把对象注册到端口

在server端只需要做两件事:

1. 创建并导出远程对象
2. 用Java RMI registry 注册远程对象public class RMIServer {public static void main(String[] args) {try {HelloService helloService= new HelloServiceImpl();HelloService stub=(HelloService) UnicastRemoteObject.exportObject(helloService,0);Registry registry=LocateRegistry.createRegistry(1099);registry.bind( "helloword", stub);System. out.println( "绑定成功!");} catch (RemoteException e) {e.printStackTrace();} catch (AlreadyBoundException e) {e.printStackTrace();}}
}

关于创建和导出远程对象

HelloService helloService= new HelloServiceImpl();
HelloService stub=(HelloService) UnicastRemoteObject.exportObject(helloService,0);

Server端的main方法在创建一个远程对象来提供服务时,此远程对象必须被导出才能被远程调用者调用。静态方法UnicastRemoteObject.exportObject()负责导出我们定义好的远程对象,它的第一个参数就是要到导出的远程对象,第二个参数是接收远程调用的tcp端口,这个值是0,它代表任意tcp端口。

exportObject()还会返回一个导出的远程对象的存根,注意,前面讲过了这个stub的类型必须和远程对象的接口类型一致,因为这个存根是要发送给client端进行调用。同时这个方法还会抛出一个RemoteException检查异常。

exportObject()方法被执行后,运行时会在一个新的Server Socket或共享Server Socket上进行监听,来接收对远程对象的远程调用。返回的存根对象和远程对象继承的是同一套remote接口,并且还它还包含了供client端口访问的主机IP和端口信息。

用Java RMI registry注册远程对象

 Registry registry=LocateRegistry.createRegistry(1099);registry.bind( "helloword", stub);

前面导出了远程对象的stub,它必须还能被client端找到并调用。为此,Java RMI 提供了 Registry API 可以允许应用程序把一个名称和远程对象的存根绑定在一起,这样client就可以通过这个绑定的名称很方便的查找到需要调用的远程对象了。

一旦远程对象在server端导出并注册,client就可以通过绑定的名称获得远程对象的引用,然后调用远程方法。

静态方法Registry registry=LocateRegistry.createRegistry(1099);会返回一个实现了java.rmi.registry.Registry接口的存根,并且在服务器本机的端口(默认是1099)上进行注册,返回的registry存根通过调用bind()方法在registry中把一个字符串名称和远程对象存根绑定在一起。

3.4 创建一个client查找远程对象,调用远程方法

public class RMIClient {public static void main(String[] args) {try {Registry registry = LocateRegistry.getRegistry();HelloService hello = (HelloService) registry.lookup( "helloword");String ret = hello.sayHello("heaven");System. out.println( ret);} catch (RemoteException e) {e.printStackTrace();} catch (NotBoundException e) {e.printStackTrace();}}
}

客户端首先通过LocateRegistry.getRegistry("localhost")方法获得registry的存根,然后再执行registry存根的lookup()方法从服务器registry中获得远程对象的存根,最后客户端在远程对象存根上执行sayHello()方法。整个过程:

  • 客户端通过远程对象存根中的IP和端口打开一个服务器连接,并且序列化请求数据
  • 服务器端接收请求并且转发请求到远程对象调用服务方法,并且序列化运行结果发送给客户端
  • 客户端接收数据反序列化,把最终结果返回给调用者

四、结果测试

启动server,然后再启动client,控制台打印:

Hello: heaven!

五、Java RMI中用到的设计模式

Java RMI中用到了经典的工厂模式,先介绍下Java RMI应用的一些角色:

  • server:生产各种远程对象
  • client:通过命名服务器rmiregistry获取远程对象的存根
  • rmiregistry:具体处理client与server的交流

下面这幅图演示了整个步骤,下图中先做如下假设:

  • 有两个远程服务接口可供client调用,Factory和Product接口
  • FactoryImpl类实现了factory接口,ProductImpl类实现了Product接口

这里写图片描述

1. FactoryImpl被注册到了rmiregistry中
2. client端请求一个Factory的引用
3. rmiregistry返回client端一个FactoryImpl的引用
4. client端调用FactoryImpl的远程方法请求一个ProductImpl的远程引用
5. FactoryImpl返回给client端一个ProductImpl引用
6. client通过ProductImpl引用调用远程方法