RMI-阿里云开发者社区

开发者社区> 开发与运维> 正文

RMI

简介: 1、制作远程接口:(1)扩展java.rmi.Remote接口,Remote和Serializable一样,没有具体的方法需要实现(2)声明所有的方法都会抛出RemoteException  使用远程接口调用服务。


1、制作远程接口:
(1)扩展java.rmi.Remote接口,Remote和Serializable一样,没有具体的方法需要实现
(2)声明所有的方法都会抛出RemoteException
  使用远程接口调用服务。调用 实现远程接口的Stub上的方法,而Stub底层用到了网络和I/O,所以各种坏事都可能会发生。这种风险,通过处理或声明远程异常来解决。如果接口中的方法声明了异常,任何在接口类型的引用上调用方法的代码也必须处理或声明异常。
(3)确定变量和返回值是属于原语(primitive)类型或者可序列化(Serializable)类型
  远程方法的变量和返回值,必须属于原语类型或Serializable类型。因为远程方法的变量必须被打包并通过网络运送,这要靠序列化来完成。
  如果使用原语类型、字符串和许多API中内定的类型(包括数组和集合),都不会有问题。如果传送自己定义的类,就必须保证类实现了Serializable

package rmi;

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

/*2015-8-25*/
public interface MyRemote extends Remote {
    String sayHello() throws RemoteException;
}

2、制作远程实现
(1)实现远程接口
  服务必须实现远程接口,也就是客户将要调用的方法和接口
(2)扩展UnicastRemoteObject
  为了要成为远程服务对象,对象需要实现某些“远程的”功能。最简单的方式是扩展java.rmi.server.UnicastRemoteObject,让超类帮做这些工作
(3)设计一个不带变量的构造器,并声明RemoteException
  超类UnicastRemoteObject带来一个小问题:它的构造函数抛出RemoteException。当类被实例化的时候,超类的构造器总是会被调用。如果超类的构造器抛出异常,子类也需要有一个相同结构的构造函数
(4)用RMI Registry注册此服务
  将此服务实例化,然后放进RMI registry中(提供服务时,RMI Registry窗口需要一直运行)
  当注册这个实现对象时,RMI系统其它注册的是stub,因为这是Client真正需要的。注册服务使用了java.rmi.Naming类的静态rebind()方法。

package rmi;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/*2015-8-25*/
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {

    private static final long serialVersionUID = 5403377671501315102L;

    protected MyRemoteImpl() throws RemoteException {
        super();
    }


    @Override
    public String sayHello() throws RemoteException {
        return "Server says,' Hello RMI!'";
    }

}

 

3、产生Stub和Skeleton
在远程实现类(是编译后生成的class文件)上执行rmic
rmic是JDK内的一个工具,用来为一个服务类产生stub和skeleton。命名习惯是在远程实现的名字后面加上_Stub和_Skel

4、执行rmiregistry
  开启一个终端,启动rmiregistry
  cd到classes目录,执行rmiregistry

5、启动服务
 开启另一个终端,启动服务
 从哪里启动?可能是从你的远程实现类的main()方法,也可能是从一个独立的启动类。
 譬如:从实现类中的main()方法启动的,先实例化一个服务对象,然后到RMI registry中注册

package rmi;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/*2015-8-25*/
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {

    private static final long serialVersionUID = 5403377671501315102L;

    protected MyRemoteImpl() throws RemoteException {
        super();
    }

    /**
     * @param args
     * @throws RemoteException
     * @throws MalformedURLException
     */
    public static void main(String[] args) {
        try {
            MyRemote service = new MyRemoteImpl();
            Naming.rebind("RemoteHello", service);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public String sayHello() throws RemoteException {
        return "Server says,' Hello RMI!'";
    }

}


或在IDE中run也可

6、客户端代码及访问服务

package rmi;

import java.rmi.Naming;

/*2015-8-25*/
public class MyRemoteClient {
    public static void main(String[] args) {
        new MyRemoteClient().go();
    }

    public void go() {
        try {
            MyRemote service = (MyRemote) Naming.lookup("rmi://127.0.0.1/RemoteHello");
            String s = service.sayHello();
            System.out.println("Result:" + s);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

结果:

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章