搜索
首页JavaJava入门Java RMI远程调用步骤分析

Java RMI远程调用步骤分析

我们先来看看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。如有侵权,请联系admin@php.cn删除

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具