发表于: 2020-06-13 23:53:10

1 1783


今天完成的事情:


MI:远程方法调用(Remote Method Invocation)。能够让在某个Java虚拟机上的对象像调用本地对象一样调用另一个java 虚拟机中的对象上的方法并且屏蔽其中关于远程通信的内容

RMI远程调用步骤:

1,客户对象调用客户端辅助对象上的方法

2,客户端辅助对象打包调用信息(变量,方法名),通过网络发送给服务端辅助对象

3,服务端辅助对象将客户端辅助对象发送来的信息解包,找出真正被调用的方法以及该方法所在对象

4,调用真正服务对象上的真正方法,并将结果返回给服务端辅助对象

5,服务端辅助对象将结果打包,发送给客户端辅助对象

6,客户端辅助对象将返回值解包,返回给客户对象

7,客户对象获得返回值

RMI的代码实现:

实现RMI所需的API几乎都在:

java.rmi:提供客户端需要的类、接口和异常; 

java.rmi.server:提供服务端需要的类、接口和异常;

java.rmi.registry:提供注册表的创建以及查找和命名远程对象的类、接口和异常;

基本步骤

(1)创建远程接口,继承java.rmi.Remote接口;

(2)创建远程类,实现远程接口;

(3)创建服务器程序,在rmiregistry注册表中注册远程对象;

(4)创建客户端程序,负责定位远程对象,并且调用远程方法。




Java  rmi


package com.ptteng.dao;

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

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

public interface IHello extends Remote {

   /**extendsRemote接口的类或者其他接口中的方法若是声明抛出了RemoteException异常,
   * 则表明该方法可被客户端远程访问调用。
    */

   public String sayHelloToSomeBody(String someBodyName) throws RemoteException;

}


实现类

package com.ptteng.dao.Impl;

import com.ptteng.dao.IHello;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

// 这个实现必须有一个显式的构造函数,并且要抛出一个RemoteException异常

/*
* 远程对象必须实现java.rmi.server.UniCastRemoteObject类,这样才能保证客户端访问获得远程对象时,
* 该远程对象将会把自身的一个拷贝以Socket的形式传输给客户端,此时客户端所获得的这个拷贝称为存根
* 而服务器端本身已存在的远程对象则称之为骨架。其实此时的存根是客户端的一个代理,用于与服务器端的通信,
* 而骨架也可认为是服务器端的一个代理,用于接收客户端的请求之后调用远程方法来响应客户端的请求。
*/

// java.rmi.server.UnicastRemoteObject构造函数中将生成stubskeleton
public class HelloImpl extends UnicastRemoteObject implements IHello {

   // 这个实现必须有一个显式的构造函数,并且要抛出一个RemoteException异常
   public HelloImpl () throws RemoteException {
       super();
   }

   @Override
   public String sayHelloToSomeBody(String someBodyName) throws RemoteException {
       System.out.println("你好啊");
       return someBodyName+"这是传入的参数";
   }
}


服务层

package com.ptteng.Server;

import com.ptteng.dao.IHello;
import com.ptteng.dao.Impl.HelloImpl;

import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

/**注册远程对象,向客户端提供远程对象服务
* 远程对象是在远程服务上创建的,你无法确切地知道远程服务器上的对象的名称
* 但是,将远程对象注册到RMI Service之后,客户端就可以通过RMI Service请求
* 到该远程服务对象的stub了,利用stub代理就可以访问远程服务对象了
*/

public class HelloServer {

   public static void main(String args[]) {
       try {
           /* 生成stubskeleton,并返回stub代理引用 */
           IHello hello = new HelloImpl();


           //加上此程序,就可以不要在控制台上开启RMI的注册程序,1099RMI服务监视的默认端口
           LocateRegistry.createRegistry(8888);
           // 如果配置在远程服务器,把地址换成你的ip
           System.setProperty("java.rmi.server.hostname","127.0.0.1");
           Naming.bind("rmi://localhost:8888/Hello", hello);
           System.out.println(">>>>>INFO:远程IHello对象绑定成功!");
       } catch (RemoteException e) {
           System.out.println("创建远程对象发生异常!");
           e.printStackTrace();
       } catch (AlreadyBoundException e) {
           System.out.println("发生重复绑定对象异常!");
           e.printStackTrace();
       } catch (MalformedURLException e) {
           System.out.println("发生URL畸形异常!");
           e.printStackTrace();
       }
   }
}


客户端

public class Client {

   public static void main(String args[]) {
       try {
           // 填写服务器ip
           IHello hello = (IHello) Naming.lookup("rmi://127.0.0.1:8888/Hello");
           System.out.println(hello.sayHelloToSomeBody("大王大王"));
       } catch (NotBoundException e) {
       } catch (MalformedURLException e) {
           e.printStackTrace();
           e.printStackTrace();
       } catch (RemoteException e) {
           e.printStackTrace();
       }
   }
}


里面的东西都是java自带的


开启服务段


客户端




返回列表 返回列表
评论

    分享到