相关介绍:

 RMI全称是Remote Method Invocation,即远程方法调用。它是一种计算机之间利用远程对象互相调用,从而实现双方通讯的一种通讯机制。使用这种机制,某一台计算机(虚拟机)上的对象可以调用另外一台计算机(虚拟机)上的对象来获取远程数据。RMI是Enterprise JavaBeans的支柱,是建立分布式Java应用程序的方便途径。在过去,TCP/IP套接字通讯是远程通讯的主要手段,但此开发方式没有使用面向对象的方式实现开发,在开发一个如此的通讯机制时往往令程序员感觉到乏味,对此RPC(Remote Procedure Call)应运而生,它使程序员更容易地调用远程程序,但在面对复杂的信息传讯时,RPC依然未能很好的支持,而且RPC未能做到面向对象调用的开发模式。针对RPC服务遗留的问题,RMI出现在世人面前,它被设计成一种面向对象的通讯方式,允许程序员使用远程对象来实现通信,并且支持多线程的服务。

要想实现基于RMI的应用程序,需要实现如下四个类:

  1. 远程对象接口: 这个接口中包含了所有远程方法的声明。在实际使用中,客户端只需要知道这个接口的存在,并不关心这个接口是如何实现的。它扩展了java.rmi.Remote接口,定义了远程对象执行的输出方法。由于在通过网络调用远程方法的过程中,有很多意想不到的问题可能会引发错误,为此,该接口中的每个方法都必须定义为抛出一个java.rmi.RemoteException异常,它是许多更专门的RMI异常类的父类。

  2. 远程对象接口实现: 这是远程对象接口的具体实现。它包含了实现远程接口的具体代码,可以在这些远程方法的实现代码中加入一些输出语句(或者log4j),以测试其被调用的情况。远程对象接口的实现类必须继承自java.rmi.server.UnicastRemoteObject类。它代表了远程对象或者服务器对象。与声明远程方法来抛出RemoteException对象不同,该远程对象不需要做任何专门的事情来允许它的方法被远程调用。UnicastRemoteObject和RMI其余的基本结构将自动进行处理。

  3. RMI服务器端: RMI服务器端生成远程对象的一个实例,并用一个专用的URL对该对象进行注册。在注册时,首先要提供远程对象所在服务器的地址,同时需要对远程对象进行标识,也就是给远程对象一个名字。这个对象的名字在服务器端和客户端必须一致,这样客户端才能找到服务器端的远程对象。

    服务器地址(serverAddress)+远程对象名字(objectName)构成了RMI的注册URL。

    其具体形式为:

    rmi://serverAddress:port/objectName

    端口号可以自己定义,默认端口是1099。如果使用默认端口,在URL里面可以不用给出。下面是一个URL的例子:

    rmi://192.168.1.123:2222/RemoteMethod

  4. RMI客户端: RMI客户端在远程RMI服务器端上查找服务对象,并将它转换成本地接口类型,然后像对待一个本地对象一样使用它。

 除了上述介绍的4个RMI相关的类之外,还需要有一个相关的安全策略文件,如java.policy。由于Java内置的安全策略对远程方法调用有一定的限制,所以我们必须编写一个安全策略文件(这是一个文本文件,文件名可以随便起)。在启动服务器端时把策略文件加载到虚拟机中,这样服务器端才能正常运行。

一个简单的例子:

 以下相关的代码用于演示一个基于RMI的例子,客户端传入相关的参数,调用服务器端对象的相关方法用来实现在客户端输出一段文字。

远程对象接口:

import java.rmi.Remote;
import java.rmi.RemoteException; /**
* 用于演示远程方法调用的实例
* @author 学徒
*此处定义了一个远程方法调用的接口
*
*/
public interface RMethod extends Remote//该接口需要实现Remote接口
{
public abstract String sayHello(String name) throws RemoteException;//Remote接口下的所有远程调用的方法都必须抛出RemoteException异常
}

远程对象接口实现:


import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject; /**
* 远程对象接口的具体实现对象
* @author 学徒
*该实现对象必须继承UnicastRemoteObject类,且实现定义的远程对象的接口
*
*
*/
public class RMethodImpl extends UnicastRemoteObject implements RMethod
{
private static final long serialVersionUID = 1L; protected RMethodImpl() throws RemoteException
{
super();
} @Override
public synchronized String sayHello(String name) throws RemoteException
{
System.out.println("Client-" + name + ": invoking \" sayHello \"");//以上的执行会发生在服务器端
return "Hello " + name + "\n\t this is a message from Remote Method";//该return的结果会返回给客户端
} }

配置信息文件类:

/**
* 该接口用于实现服务器端和客户端的共同配置,当远程调用的某些信息发生改变时,只需要修改该接口的信息,而不需要去更改
* 代码
* @author 学徒
*
*由于服务器端需要注册远程对象调用的实例的URL,而且其格式为
*rmi://serverAddress:port/objectName
*
*为此在下面配置相关的信息
*/
public interface Config
{
//对象实例的名字
String OBJECT_NAME = "RemoteMethod";
//对象服务器的IP地址
String SERVER_IP = "192.168.199.241";
//对象服务器进行监听的端口号
int PORT = 1234;
}

RMI服务器端:


import java.rmi.RMISecurityManager;
import java.rmi.registry.LocateRegistry; /**
* 远程对象调用的服务器,该服务器的作用是创建远程对象实现的实例,并按照公用配置文件制定的对象名将这个实例注册到服务器端上。
* 当注册成功之后,服务器端程序就处于阻塞状态,等待客户端的远程对象访问请求。
*
* @author 学徒
*
*/
public class Server
{
public static void main(String[] args)
{
new Server();
} public Server()
{
if (null == System.getSecurityManager())
{
System.setSecurityManager(new RMISecurityManager());
}
try
{
try
{
//用于注册远程对象调用的监听端口
LocateRegistry.createRegistry(Config.PORT);
}
catch (java.rmi.server.ExportException ex)
{
System.out.println("Register the port failed:\n"+ ex.getMessage());
}
RMethod rm = new RMethodImpl();
String objAddr = "rmi://" + Config.SERVER_IP + ":" + Config.PORT+ "/" + Config.OBJECT_NAME;
//用于将该URL绑定到该对象实例上
java.rmi.Naming.rebind(objAddr, rm);
System.out.println("Server is running...");
}
catch (Exception e)
{
System.out.println("Server startup failed!");
e.printStackTrace();
}
}
}

RMI客户端:

/**
* 在客户端,其需要有和服务器端同样的两个文件,一个是Config配置文件,因为其定义了RMI的配置信息,一个是
* Remote接口类,该类在客户端可以通过远程方法调用的方式生成一个使用的实例。 该类用于实现远程对象调用的客户端程序
* 客户端通过调用服务器端提供的远程方法,来实现与服务器的通信。这样就不需要考虑具体的通信细节。
* 只要像使用本地方法一样调用服务器端的远程方法,完成需要的功能。 要调用远程方法,客户端必须先构造一个RMI
* URL来找到远程对象(注意在客户端我们只使用远程对象接口), 然后通过远程对象来调用远程方法。
*
* @author 学徒
*
*/
public class Client
{
private String name;
private String hostURL;
private String obj; public Client(String name)
{
this.name = name;
hostURL = "rmi://" + Config.SERVER_IP + ":" + Config.PORT + "/";
this.obj = Config.OBJECT_NAME;
} public void callRMethod()
{
try
{
RMethod rm = (RMethod) java.rmi.Naming.lookup(hostURL + obj);
String result = rm.sayHello(name);
System.out.println(result);
}
catch (Exception e)
{
e.printStackTrace();
}
} public static void main(String[] args)
{
Client c1 = new Client("Monica");
c1.callRMethod();
Client c2 = new Client("Joy");
c2.callRMethod();
Client c3 = new Client("Ross");
c3.callRMethod();
Client c4 = new Client("Chandler");
c4.callRMethod();
} }

安全策略文件:

grant {
permission java.security.AllPermission;
}; ps:为方便说明该示例,文件的文件名取为java.policy

执行过程:

 编写了相关的java类之后,按照如下的方式创建访问过程:

命令行模式

编译:

$ javac *.java

运行服务器端:

$ rmic RMethodImpl

$ java -Djava.security.policy=java.policy Server

Server is running...//此处是服务器端启动后的输出

运行客户端:

$ java Client

Hello Monica

 this is a message from Remote Method

Hello Joy

 this is a message from Remote Method

Hello Ross

 this is a message from Remote Method

Hello Chandler

 this is a message from Remote Method

服务器端对应的输出为:

$ java -Djava.security.policy=java.policy Server

Server is running...

Client-Monica: invoking " sayHello "

Client-Joy: invoking " sayHello "

Client-Ross: invoking " sayHello "

Client-Chandler: invoking " sayHello "

从输出结果中可以看出,远程方法的调用将其相关的方法的执行放在了服务器端,而客户端只需要传递相关的参数,以及接收相应的结果即可

服务器相关的文件:

客户端相关的文件:

回到目录|·(工)·)

参考博文: 学习笔记:JAVA RMI远程方法调用简单实例

推荐文章:深入理解rmi原理。在看这篇文章前,先了解如下两个概念:1. stub和Skeleton:这两个的身份是一致的,都是作为代理的存在。客户端的称作Stub,服务端的称作Skeleton。要做到对程序员屏蔽远程方法调用的细节,这两个代理是必不可少的,包括网络连接等细节。2. Registry:顾名思义,可以认为Registry是一个“注册所”,提供了服务名到服务的映射。

K:java中的RMI(Remote Method Invocation)的更多相关文章

  1. JAVA 中的RMI是什么

    RMI的概念 RMI(Remote Method Invocation)远程方法调用是一种计算机之间利用远程对象互相调用实现双方通讯的一种通讯机制.使用这种机制,某一台计算机上的对象可以调用另外 一台 ...

  2. java的RMI(Remote Method Invocation)

    RMI 相关知识RMI全称是Remote Method Invocation-远程方法调用,Java RMI在JDK1.1中实现的,其威力就体现在它强大的开发分布式网络应用的能力上,是纯Java的网络 ...

  3. Spring之RMI 远程方法调用 (Remote Method Invocation)

    RMI 指的是远程方法调用 (Remote Method Invocation) 1. RMI的原理: RMI系统结构,在客户端和服务器端都有几层结构. 方法调用从客户对象经占位程序(Stub).远程 ...

  4. Spring Remoting: Remote Method Invocation (RMI)--转

    原文地址:http://www.studytrails.com/frameworks/spring/spring-remoting-rmi.jsp Concept Overview Spring pr ...

  5. java中什么是bridge method(桥接方法)

    java中什么是bridge method(桥接方法) https://blog.csdn.net/z69183787/article/details/81115524

  6. Java远程方法调用(Remote Method Invocation,RMI)

    Java RMI简介: 它是Java的一个核心API和类库,允许一个Java虚拟机上运行的Java程序调用不同虚拟机上运行的对象中的方法,即使这两个虚拟机运行于物理隔离的不同主机上. Java RMI ...

  7. RMI(Remote Method Invocation ) 概念恢复

    1.RMI是远程方法调用的简称,像其名称暗示的那样,它能够帮助我们查找并执行远程对象,通俗的说,远程调用就像一个class放在A机器上,然后在B机器中调用这个class的方法. 2.EMI术语 在研究 ...

  8. 【java编程】java中什么是bridge method(桥接方法)

    https://blog.csdn.net/mhmyqn/article/details/47342577 https://www.cnblogs.com/strinkbug/p/5019453.ht ...

  9. java中的方法(method)到底怎么用?给个例子

    7.方法(method)   被调例子, int add(int x, int y){ return x+y; } 主调例子, for example: int result = add(5,3); ...

随机推荐

  1. lamp-linux3

    LAMP编程之Linux(3) 一.权限管理 1.权限介绍(重点) 在Linux中分别有读.写.执行权限: 读权限: 对于文件夹来说,读权限影响用户是否能够列出目录结构 对于文件来说,读权限影响用户是 ...

  2. JavaScript求数组Array的并集(javascript面试常见题目)

    var Utils = { joinArray:function(source,target){ for(var i = 0;i<source.length;i++){ var oa = sou ...

  3. AngularJS源码解析1:angular自启动过程

    angularJS加载进来后,会有一个立即执行函数调用,在源代码的最下面是angular初始化的地方.代码展示: bindJQuery(); publishExternalAPI(angular); ...

  4. Security-OAuth2.0 密码模式之客户端实现

    我的OAuth2.0 客户端项目目录 pom 的配置 <?xml version="1.0" encoding="UTF-8"?> <proj ...

  5. MySQL , MHA , Haproxy 配置

    1. 基本架构 2. 读端口影射 3. 写端口影射 进行一个Health Check MHA Manager对Master节点MySQL 进行存活监控 读FailOver 1 读FailOver 2 ...

  6. 使用python 模仿mybinlog 命令 二进制分析mysql binlog

    出处:黑洞中的奇点 的博客 http://www.cnblogs.com/kelvin19840813/ 您的支持是对博主最大的鼓励,感谢您的认真阅读.本文版权归作者所有,欢迎转载,但请保留该声明. ...

  7. C#-输入输出,类型,运算符,语句的练习——★判断年份是否是闰年★

    //输入一个年份,判断是否是闰年 //(能被4整除却不能被100整除的,年份世纪年份能被400整除的是闰年) Console.Write("请输入一个年份:"); int year ...

  8. L08-Linux解决Device eth0 does not seem to be present,delaying initialization问题

    问题前提: 在VirtualBox中克隆Linux服务器,如下,由Centos6.5_Base克隆得到node01服务器,采用的是完全克隆的方式,克隆时重新初始化MAC地址. 原服务器Centos6. ...

  9. 【old】Python学习笔记

    上学期看视频记得,也没学到多少,目前打算一边通过<Python学习手册 第四版>提高核心语法(太厚了 噗),一边学习Python Web开发 然后这里的多任务编程和网络编程是暑假学的 5. ...

  10. OPENERP 中自定义模块 找不到的问题

    问题的前提是你写的模块本身没有问题,我自己碰到的情况是在本机运行可以,但是上传到服务器上以后却无论怎么重启服务都找不到模块. 问题的根源在上传的文件权限设置不对: 假设自定义模块为rainsoft_p ...