• 技术文章 >Java >Java入门

    Java RMI远程调用步骤分析

    VV2021-02-19 09:50:22转载52

    我们先来看看Java RMI的定义:

    RMI(Remote Method Invocation,远程方法调用)是用Java在JDK1.2中实现的,它大大增强了Java开发分布式应用的能力。Java作为一种风靡一时的网络开发语言,其巨大的威力就体现在它强大的开发分布式网络应用的能力上,而RMI就是开发百分之百纯Java的网络分布式应用系统的核心解决方案之一。其实它可以被看作是RPC的Java版本。但是传统RPC并不能很好地应用于分布式对象系统。而Java RMI 则支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用。

    RMI远程调用步骤

    RMI的交互图:

    a4188ba4d37cd14aa24c67f3b060a72.png

    RMI由3个部分构成,第一个是rmiregistry(JDK提供的一个可以独立运行的程序,在bin目录下),第二个是server端的程序,对外提供远程对象,第三个是client端的程序,想要调用远程对象的方法。
    首先,先启动rmiregistry服务,启动时可以指定服务监听的端口,也可以使用默认的端口(1099)。
    其次,server端在本地先实例化一个提供服务的实现类,然后通过RMI提供的Naming/Context/Registry(下面实例用的Registry)等类的bind或rebind方法将刚才实例化好的实现类注册到rmiregistry上并对外暴露一个名称。
    最后,client端通过本地的接口和一个已知的名称(即rmiregistry暴露出的名称)再使用RMI提供的Naming/Context/Registry等类的lookup方法从RMIService那拿到实现类。这样虽然本地没有这个类的实现类,但所有的方法都在接口里了,便可以实现远程调用对象的方法了。

    存根和骨干网的具体通信过程:

    4891d885efd3830ba37642127f64b41.png

    方法调用从客户对象经存根(stub)、远程引用层(Remote Reference Layer)和传输层(Transport Layer)向下,传递给主机,然后再次经传输层,向上穿过远程调用层和骨干网(Skeleton),到达服务器对象。
    存根扮演着远程服务器对象的代理的角色,使该对象可被客户激活。
    远程引用层处理语义、管理单一或多重对象的通信,决定调用是应发往一个服务器还是多个。
    传输层管理实际的连接,并且追踪可以接受方法调用的远程对象。
    骨干网完成对服务器对象实际的方法调用,并获取返回值。
    返回值向下经远程引用层、服务器端的传输层传递回客户端,再向上经传输层和远程调用层返回。最后,存根获得返回值。

    JAVA RMI简单示例

    本示例是client端调用server端远程对象的加减法方法,具体步骤为:
    1. 定义一个远程接口

    import java.rmi.Remote;
    import java.rmi.RemoteException;
    
    /**
     * 必须继承Remote接口。
     * 所有参数和返回类型必须序列化(因为要网络传输)。
     * 任意远程对象都必须实现此接口。
     * 只有远程接口中指定的方法可以被调用。
     */
    public interface IRemoteMath extends Remote {
    
      	// 所有方法必须抛出RemoteException
    	public double add(double a, double b) throws RemoteException;
    	public double subtract(double a, double b) throws RemoteException;
    	
    }

    (学习视频分享:java视频教程

    2. 远程接口实现类

    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject;
    import remote.IRemoteMath;
    
    /**
     * 服务器端实现远程接口。
     * 必须继承UnicastRemoteObject,以允许JVM创建远程的存根/代理。
     */
    public class RemoteMath extends UnicastRemoteObject implements IRemoteMath {
    
    	private int numberOfComputations;
    	
    	protected RemoteMath() throws RemoteException {
    		numberOfComputations = 0;
    	}
    	
    	@Override
    	public double add(double a, double b) throws RemoteException {
    		numberOfComputations++;
    		System.out.println("Number of computations performed so far = " 
    				+ numberOfComputations);
    		return (a+b);
    	}
    
    	@Override
    	public double subtract(double a, double b) throws RemoteException {
    		numberOfComputations++;
    		System.out.println("Number of computations performed so far = " 
    				+ numberOfComputations);
    		return (a-b);
    	}
    
    }

    3. 服务器端

    import java.rmi.registry.LocateRegistry;
    import java.rmi.registry.Registry;
    import remote.IRemoteMath;
    
    /**
     * 创建RemoteMath类的实例并在rmiregistry中注册。
     */
    public class RMIServer {
    
    	public static void main(String[] args)  {
    		
    		try {
    			// 注册远程对象,向客户端提供远程对象服务。
    			// 远程对象是在远程服务上创建的,你无法确切地知道远程服务器上的对象的名称,
    			// 但是,将远程对象注册到RMI Registry之后,
    			// 客户端就可以通过RMI Registry请求到该远程服务对象的stub,
    			// 利用stub代理就可以访问远程服务对象了。
    			IRemoteMath remoteMath = new RemoteMath();  
    			LocateRegistry.createRegistry(1099);    
    			Registry registry = LocateRegistry.getRegistry();
    			registry.bind("Compute", remoteMath);
    			System.out.println("Math server ready");
    			// 如果不想再让该对象被继续调用,使用下面一行
    			// UnicastRemoteObject.unexportObject(remoteMath, false);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}		
    		
    	}
    	
    }

    4. 客户端

    import java.rmi.registry.LocateRegistry;
    import java.rmi.registry.Registry;
    import remote.IRemoteMath;
    
    public class MathClient {
    
    	public static void main(String[] args) {
    		
    		try { 
    			// 如果RMI Registry就在本地机器上,URL就是:rmi://localhost:1099/hello
    			// 否则,URL就是:rmi://RMIService_IP:1099/hello
    			Registry registry = LocateRegistry.getRegistry("localhost");        
    			// 从Registry中检索远程对象的存根/代理
    			IRemoteMath remoteMath = (IRemoteMath)registry.lookup("Compute");
    			// 调用远程对象的方法
    			double addResult = remoteMath.add(5.0, 3.0);
    			System.out.println("5.0 + 3.0 = " + addResult);
    			double subResult = remoteMath.subtract(5.0, 3.0);
    			System.out.println("5.0 - 3.0 = " + subResult);			
    		}catch(Exception e) {
    			e.printStackTrace();
    		}
    				
    	}
    	
    }

    结果如下:

    server端

    33da9335bc61e8425e0a4cbed7f876c.png

    client端

    ae8827ee70db9168dc9e885367b3031.png

    参考:https://blog.csdn.net/xinghun_4/article/details/45787549

    相关推荐:java入门教程

    以上就是Java RMI远程调用步骤分析的详细内容,更多请关注php中文网其它相关文章!

    本文转载于:csdn,如有侵犯,请联系a@php.cn删除
    专题推荐:Java RMI
    上一篇:jar 是什么文件格式 下一篇:java的运行机制是什么
    第15期线上培训班

    相关文章推荐

    • php远程下载类分享 php 远程调试 php 远程调用 php连接远程数据• curl - php 如何禁止远程调用地址的输出• PHP远程调用以及RPC框架的代码详解(图)• ComboBox利用url进行数据的远程调用方法详解

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网