java rmi 使用教程及原理

什么是rmi

RMI,是Remote Method Invocation(远程方法调用)的缩写,即在一个JVM中java程序调用在另外一个远程JVM中运行的java程序,这个远程JVM既能够在同一台实体机上,也能够在不一样的实体机上,二者之间经过网络进行通讯。java RMI封装了远程调用的实现细节,进行简单的配置以后,就能够如同调用本地方法同样,比较透明地调用远端方法。java

RMI包括如下三个部分:网络

  • Registry: 提供服务注册与服务获取。即Server端向Registry注册服务,好比地址、端口等一些信息,Client端从Registry获取远程对象的一些信息,如地址、端口等,而后进行远程调用。
  • Server: 远程方法的提供者,并向Registry注册自身提供的服务
  • Client: 远程方法的消费者,从Registry获取远程方法的相关信息而且调用

jdk中java.rmi包简介

Remote

一个interface,这个interface中没有声明任何方法。只有定义在“remote interface",即继承了Remote的接口中的方法,才能够被远程调用。线程

RemoteException

RemoteException是全部在远程调用中所抛出异常的超类,全部可以被远程调用的方法声明,都须要抛出此异常code

Naming

提供向注册中心保存远程对象引用或者从注册中心获取远程对象引用的方法。这个类中的方法都是静态方法,每个方法都包含了一个类型为String的name参数, 这个参数是URL格式,形如://host:port/nameorm

Registry

一个interface, 其功能和Naming相似,每一个方法都有一个String类型的name参数,可是这个name不是URL格式,是远程对象的一个命名。Registry的实例能够经过方法LocateRegistry.getRegistry()得到server

LocateRegistry

用于获取到注册中心的一个链接,这个链接能够用于获取一个远程对象的引用。也能够建立一个注册中心。对象

RemoteObject

从新覆写了Object对象中的equals,hashCode,toString方法,从而能够用于远程调用继承

UnicastRemoteObject

用于RMI Server中导出一个远程对象并得到一个stub。这个stub封装了底层细节,用于和远程对象进行通讯。接口

Unreferenced

一个interface, 声明了方法:void unreferenced()若是一个远程队形实现了此接口,则这个远程对象在没有任何客户端引用的时候,这个方法会被调用。开发

rmi使用

在这一节,咱们将从头开始写一个简单的RMI示例,实现输入名字,返回“Hello, XXX"的工程。建立一个完整的远程调用,咱们分为如下几步:

  1. 定义一个远程接口,这个接口须要继承Remote,而且接口中的每个方法都须要抛出RemoteException异常
  2. 开发远程接口的实现类
  3. Registry的建立
  4. RMI Server的建立
  5. RMI Client的建立

定义一个远程接口

package com.luckyqiao.rmi;

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

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

开发远程接口的实现类

package com.luckyqiao.rmi;

import java.rmi.RemoteException;

public class RemoteHelloImpl  implements RemoteHello {
    public String sayHello(String name) throws RemoteException {
        return String.format("Hello, %s!", name);
    }
}

Registry 的建立

package com.luckyqiao.rmi;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.util.concurrent.CountDownLatch;

public class RegistryServer {
    public static void main(String[] args) throws InterruptedException{
        try {
            LocateRegistry.createRegistry(8000); //Registry使用8000端口
        } catch (RemoteException e) {
            e.printStackTrace();
        }

        CountDownLatch latch=new CountDownLatch(1);
        latch.await();  //挂起主线程,不然应用会退出
    }
}

RMI Server 的建立

package com.luckyqiao.rmi;

import java.io.IOException;
import java.rmi.AlreadyBoundException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class RMIServer {

    public static void main(String[] args) {

        RemoteHello remoteHello = new RemoteHelloImpl();
        try {
            RemoteHello stub = (RemoteHello) UnicastRemoteObject.exportObject(remoteHello, 4000); //导出服务,使用4000端口
            Registry registry = LocateRegistry.getRegistry("127.0.0.1", 8000); //获取Registry
            registry.bind("hello", stub); //使用名字hello,将服务注册到Registry
        } catch (AlreadyBoundException | IOException e) {
            e.printStackTrace();
        }

    }
}

RMI Client的建立

package com.luckyqiao.study.rmi;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class RMIClient {
    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.getRegistry("127.0.0.1", 8000);  //获取注册中心引用
            RemoteHello remoteHello = (RemoteHello) registry.lookup("hello"); //获取RemoteHello服务
            System.out.println(remoteHello.sayHello("World"));  //调用远程方法
        } catch (RemoteException | NotBoundException e) {
            e.printStackTrace();
        }
    }
}

原理

未完待续

相关文章
相关标签/搜索