远程方法调用(Remote Method Invocation,RMI)从JDK1.1就已经实现,它大大增强了Java开发分布式应用的能力。可以实现通过网络完成不同JVM间的通信,不仅可以传递基本的数据类型,对象也是可以传递的。RMI是JVM间的通信,如果服务器或客户端不是Java语言开发的,可以考虑web service或者corba。

RMI可以实现调用的透明性及安全性,客户端本身不关心功能是怎么实现的,只需要调用服务器端代码并关心结果即可。功能只限制于服务器端,客户端无法任意进行操作,也提供了安全性。

RMI利用JNDI在服务器端注册客户端需要调用的类。具体的调用是存根和骨架之间完成的,可以看做是客户端和服务器端的代理。

IHello定义了服务器和客户端间通信的接口,客户端只需要调用IHello中的方法即可。IHello需要集成Remote接口,所有方法需要抛出

RemoteException。

/** * 定义一个远程接口,必须继承Remote接口,其中需要远程调用的方法必须抛出RemoteException异常 */ public interface IHello extends Remote { public User user = new User(); public User getUser() throws RemoteException;; public void setUser(User user) throws RemoteException;; /** * 简单的返回“Hello World!"字样 * @return 返回“Hello World!"字样 * @throws java.rmi.RemoteException */ public String helloWorld() throws RemoteException; /** * 一个简单的业务方法,根据传入的人名返回相应的问候语 * @param someBodyName 人名 * @return 返回相应的问候语 * @throws java.rmi.RemoteException */ public String sayHelloToSomeBody() throws RemoteException; } 

HelloImpl是服务器端实际实现的方法,客户端通过RMI实际调用的就是HelloImpl。

/** * 远程的接口的实现 */ public class HelloImpl extends UnicastRemoteObject implements IHello { private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } private static final long serialVersionUID = -8403069777370518716L; /** * 因为UnicastRemoteObject的构造方法抛出了RemoteException异常,因此这里默认的构造方法必须写,必须声明抛出RemoteException异常 * @throws RemoteException */ public HelloImpl() throws RemoteException { } /** * 简单的返回“Hello World!"字样 * * @return 返回“Hello World!"字样 * @throws java.rmi.RemoteException */ public String helloWorld() throws RemoteException { return "Hello World!"; } /** * 一个简单的业务方法,根据传入的人名返回相应的问候语 * * @param someBodyName 人名 * @return 返回相应的问候语 * @throws java.rmi.RemoteException */ public String sayHelloToSomeBody() throws RemoteException { return user.getName() + "!"; } } 

HelloServer完成的是注册功能,将上面实际工作的HelloImpl进行注册,客户端调用时查找已经注册的HelloImpl实例并调用即可。注册的地址是localhost的8888端口。不同的JVM时将localhost改为具体的IP即可。

/** * 创建RMI注册表,启动RMI服务,并将远程对象注册到RMI注册表中。 */ public class HelloServer { private static User user = new User(); public User getUser() { return user; } public void setUser(User user) { this.user = user; } public static void main(String args[]) { try { //创建一个远程对象 HelloImpl rhello = new HelloImpl(); //本地主机上的远程对象注册表Registry的实例,并指定端口为8888,这一步必不可少(Java默认端口是1099),必不可缺的一步,缺少注册表创建,则无法绑定对象到远程注册表上 LocateRegistry.createRegistry(8888); //把远程对象注册到RMI注册服务器上,并命名为RHello //绑定的URL标准格式为:rmi://host:port/name(其中协议名可以省略,下面两种写法都是正确的) Naming.bind("rmi://localhost:8888/RHello",rhello); // Naming.bind("//localhost:8888/RHello",rhello); System.out.println(">>>>>INFO:远程IHello对象绑定成功!"); } catch (RemoteException e) { System.out.println("创建远程对象发生异常!"); e.printStackTrace(); } catch (AlreadyBoundException e) { System.out.println("发生重复绑定对象异常!"); e.printStackTrace(); } catch (MalformedURLException e) { System.out.println("发生URL畸形异常!"); e.printStackTrace(); } } } 

HelloClient模拟了客户端的调用,从localhost的8888端口找到注册的HelloImpl实例并调用。

/** * 客户端测试,在客户端调用远程对象上的远程方法,并返回结果。 */ public class HelloClient { public static void main(String args[]){ try { //在RMI服务注册表中查找名称为RHello的对象,并调用其上的方法 IHello rhello =(IHello) Naming.lookup("rmi://localhost:8888/RHello"); System.out.println(rhello.helloWorld()); User user = new User(); user.setName("inso"); rhello.setUser(user); System.out.println(rhello.sayHelloToSomeBody()); } catch (NotBoundException e) { e.printStackTrace(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } } } 

User用于客户端调用服务器端代码时传递的参数,说明RMI支持传递对象,需要实现Serializable接口。

public class User implements Serializable{ private static final long serialVersionUID = -4631891643752276172L; private String name; public String getName() { return "user's name is " + name; } public void setName(String name) { this.name = name; } } 

先启动HelloServer注册实例,再启动HelloClient进行调用即可看到结果。

还可以将IHello.java,HelloClient.java,User.java拷贝到另外的机器上,模拟客户端实现真正的分布式测试。将服务器端和客户端的localhost改为具体的IP即可。

RMI基础的更多相关文章

  1. RMI基础篇

    远程方法调用(Remote Method Invocation,RMI)从JDK1.1就已经实现,它大大增强了Java开发分布式应用的能力. RMI可以实现通过网络完成不同JVM间的通信,不仅可以传递 ...

  2. Java RMI之HelloWorld篇

    Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...

  3. JAVA RMI helloworld入门

    Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...

  4. java的RMI(Remote Method Invocation)

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

  5. Java RMI 远程方法调用

    Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...

  6. Java远程方法调用(RMI)

    Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...

  7. Java RMI简单例子HelloWorld

    Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...

  8. Java RMI 框架_远程方法调用(2016-08-16)

    概念: Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可 ...

  9. 【Socket】Java Socket基础编程

    Socket是Java网络编程的基础,了解还是有好处的, 这篇文章主要讲解Socket的基础编程.Socket用在哪呢,主要用在进程间,网络间通信.本篇比较长,特别做了个目录: 一.Socket通信基 ...

随机推荐

  1. BZOJ 2748: [HAOI2012]音量调节【二维dp,枚举】

    2748: [HAOI2012]音量调节 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 2010  Solved: 1260[Submit][Statu ...

  2. 五 : springMVC拦截器

    springMVC拦截器的实现一般有两种方式 第一种方式是要定义的Interceptor类要实现了Spring的HandlerInterceptor 接口 第二种方式是继承实现了HandlerInte ...

  3. HDU 2412 Farm Irrigation

    题目: Benny has a spacious farm land to irrigate. The farm land is a rectangle, and is divided into a ...

  4. Spark性能调优之解决数据倾斜

    Spark性能调优之解决数据倾斜 数据倾斜七种解决方案 shuffle的过程最容易引起数据倾斜 1.使用Hive ETL预处理数据    • 方案适用场景:如果导致数据倾斜的是Hive表.如果该Hiv ...

  5. PHP中put和post区别

    1. 使用支持和范围的区别: PHP提供了对PUT方法的支持,在Http定义的与服务器的交互方法中,PUT是把消息本体中的消息发送到一个URL,形式上跟POST类似; PHP 提供对诸如 Netsca ...

  6. PostgreSql 分页limit

    摘录自:http://jingyan.baidu.com/article/a17d528538119b8098c8f2ca.html 语法: select * from persons limit   ...

  7. python简单词频统计

    任务 简单统计一个小说中哪些个汉字出现的频率最高 知识点 文件操作 字典 排序 lambda 代码 import codecs import matplotlib.pyplot as plt from ...

  8. Linux下如何释放cache内存

    转自:http://www.linuxidc.com/Linux/2015-02/112685.htm 在Linux下频繁存取文件后,物理内存会很快被用光,当程序结束后,内存不会被正常释放,而是一直作 ...

  9. mybatis-枚举类型的typeHandler&自定义枚举类型typeHandler

    MyBatis内部提供了两个转化枚举类型的typeHandler给我们使用. org.apache.ibatis.type.EnumTypeHandler 是使用枚举字符串名称作为参数传递的 org. ...

  10. arduino与DS1302时钟调试失败的分析

    前两天测试了时钟模块,但是,一直失败,能读取时间,但是设置不了时间,所以.这次我查了很多资料,发现好像是信号线的问题,线太长,数据收到干扰, 资料如下http://www.51hei.com/bbs/ ...