zoukankan      html  css  js  c++  java
  • Java RMI-远程方法调用

     

        最近在看《Head First设计模式》一书的代理模式时,提到了Java RMI,即Java远程方法调用这个概念。于是上网找了一些关于Java RMI的资料加以学习。

    一、Java RMI概观

         RMI英文全称为:Remote Method Invocation,中文意思为:远程方法调用。它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。可以用此方法调用的任何对象必须实现该远程接口。

         RMI提供了客户辅助对象和服务辅助对象,为客户辅助对象创建和服务对象相同的方法。RMI的好处在于你不必亲自写如何网络代码和I/O代码。客户程序远程调用(即真正的服务所在)就和运行客户自己的本地机JVM上对对象进行正常方法调用一样。

        RMI将客户辅助对象成为stub(桩),服务辅助对象成为skeleton(骨架)。

        RMI结构图如下:

    二、Java中如何利用RMI进行远程方法调用呢?

    步骤如下:

    1、制作远程接口

    2、制作远程的实现

    3、利用rmic产生stub和skeleton

    4、启动RMI registry(rmiregistry)

    5、开始远程服务

     

    三、例子程序

    MyRemote.java

    /**
     * 服务器端   远程接口
     */
    
    package RMIDemo;
    
    /*
     * RemoteException和远程接口在java.rmi包中
     * */
    import java.rmi.*;
    
    /*
     * 定义一个远程接口,它必须扩展自java.rmi.Remote接口。
     * */
    public interface MyRemote extends Remote {
    	/**
    	 * 所有的远程方法都必须抛出RemoteException异常。
    	 * @return
    	 * @throws RemoteException
    	 */
    	public String sayHello() throws RemoteException;
    }
    


    MyRemoteImpl.java

    /**
     * 远程服务(实现)
     */
    package RMIDemo;
    
    import java.rmi.Naming;
    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject;
    
    /**
     * 
     * @author ccf
     *
     */
    
    /**
     * 要想创建一个远程对象,扩展UnicastRemoteObject是最容易的方法。
     * 其中,MyRemote接口是你必须实现的远程接口
     */
    public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
    	/**
    	 * 你必须实现远程接口。当然你必须实现所有的接口方法,但请注意:可以不需要声明RemoteException。
    	 */
    	@Override
    	public String sayHello() throws RemoteException {
    		// TODO Auto-generated method stub
    		return "Server says: 'Hey' ";
    	}
    	/**
    	 * 你的超类(UnicastRemoteObject)构造器声明了异常,所以你必须写一个构造器,
    	 * 因为这意味着你的构造器正在调用不安全的代码(它的超构造器)。
    	 * @throws RemoteException
    	 */
    	public MyRemoteImpl() throws RemoteException{}
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		try{
    			/**
    			 * 先产生远程对象,再使用Naming.rebind()绑定到rmiregistry。
    			 * 客户将使用你所注册的名称在RMI Registry中寻找它。
    			 */
    			MyRemote service = new MyRemoteImpl();
    			Naming.rebind("RemoteHello", service);
    		}catch(Exception ex){
    			ex.printStackTrace();
    		}
    	}
    
    }
    

    MyRemoteClient.java

    package RMIDemo;
    
    /**
     * 用来做rmiregister lookup的Naming类在java.rmi包中。
     * 客户端测试,在客户端调用远程对象的远程方法,并返回结果。
     */
    import java.rmi.*;
    
    public class MyRemoteClient {
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		
    	}
    	public void go(){
    		try{
    			/*
    			 * 返回值是Object类型,所以别忘记转换类型。
    			 * 其次,在lookup函数中你需要IP地址或主机名,还有服务器被绑定/重绑定时用的名称。
    			 */
    			MyRemote service = (MyRemote)Naming.lookup("rmi://127.0.0.1/RemoteHello");
    			
    			String s = service.sayHello();
    			
    			System.out.println(s);
    		}catch(Exception ex){
    			ex.printStackTrace();
    		}
    	}
    }
    


    博客园博主ninahan的博客Java RMI之HelloWorld篇的例子和我从《Head First设计模式》中的摘抄的例子差不多,他讲解得比较清晰!

    总结:
    RMI对服务器的IP地址和端口依赖很紧密,但是在开发的时候不知道将来的服务器IP和端口如何,但是客户端程序依赖这个IP和端口。这也是RMI的局限性之一。
    这个问题有两种解决途径:一是通过DNS来解决,二是通过封装将IP暴露到程序代码之外。
    RMI的局限性之二是RMI是Java语言的远程调用,两端的程序语言必须是Java实现,对于不同语言间的通讯可以考虑用Web Service或者公用对象请求代理体系(CORBA)来实现。
     

    四、 参考资料:

    1、《Head First设计模式》第440-450页。

     2、Java RMI 服务器框架:使用异步进程管理器来包含 RMI 服务器应用程序

     3、Java RMI之HelloWorld篇:Java RMI之HelloWorld篇

     4、JAVA RMI线程模型及内部实现机制 :JAVA RMI线程模型及内部实现机制

     5、JDK_API_1_6_zh_CN.CHM参考手册

  • 相关阅读:
    日期类和包装类
    集合——list
    数组
    多态小结
    一些概念性的知识点
    简单的图书管理系统
    一个小总结
    python-web自动化:上传操作
    python-web自动化:日期框操作
    python-web自动化:滚动条
  • 原文地址:https://www.cnblogs.com/ccf19881030/p/12004874.html
Copyright © 2011-2022 走看看