今天在看代理设计模式,java中远程代理的实现一定会用到RMI的,很久没有温习过RMI的知识了,今天就重新过一遍这个知识点来让自己加深印象,构建一个简单的RMI小程序需要用到一下几个类:

  • java.rmi.Remote
  • java.rmi.RemoteException
  • java.rmi.Naming

UML类图:

类图很简单,但是有几点需要注意:

  • 服务器端的接口应该继承自java.rmi.server.UnicastRemoteObject类并实现java.rmi.Remote接口
  • 由于是远程方法调用,有可能由于网络原因而出现异常,服务器端接口的方法应该抛出java.rmi.RemoteException
  • 服务器端接口的具体实现类必须显示地声明一个无参构造方法并抛出RemoteException, 这是因为UnicastRemoteObject类的无参构造方法就抛出了RemoteException,这样在实例化MyRemoteImpl之前会先实例化UnicastRemoteObject
  • 由于参数和返回值需要在网络中传播,如果你的参数和返回值不是java原始数据类型(例如自定义的对象),那么该对象需要实现java.io.Serializable, 这样JVM才能对该对象进行序列及反序列化

我们再来看看具体的实现:

MyRemote接口

import java.rmi.Remote;
import java.rmi.RemoteException; public interface MyRemote extends Remote { public String getServerTime(String employee) throws RemoteException; }

MyRemoteImpl实现类

import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Date; public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote { private static final long serialVersionUID = 6812592847867041499L; public MyRemoteImpl() throws RemoteException {
super();
} public static void main(String[] args) throws MalformedURLException, RemoteException, AlreadyBoundException {
MyRemote myRemote = new MyRemoteImpl();
Naming.bind("rmi://192.168.3.4:1099/myRemote", myRemote);
System.out.println("Ready...");
} @Override
public String getServerTime(String employee) throws RemoteException {
return String.format("Hello %s, Italy time is: %s", employee, new Date());
} }

客户端测试类:

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException; public class RmiClient { public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException {
MyRemote myRemote = (MyRemote) Naming.lookup("rmi://192.168.3.4:1099/myRemote");
System.out.println(myRemote.getServerTime("Linda"));
} }

现在运行测试还为时尚早,为了实现跨JVM的远程方法调用我们还需要做一些必须的事情:

  • 使用rmic工具生成Stub桩供远程调用(Java 1.5之后可以不用生成这个文件?还在研究)
  • rmiregistry开放RMI注册
  • 使用java.rmi.Naming的bind方法来绑定服务

我们一步一步来:

首先生成stub文件,客户端需要这个文件来调用远程对象,这个文件其实就是远程对象在本地的一个代理,客户端以为是跟远程对象直接打交道,其实客户端调用的是该客户服务对象,该桩又调用远程对象。

生成的桩文件:

运行rmiregistry命令:

运行MyRemoteImpl的main方法来将服务绑定到远程计算机的1099端口

我们写的是一个RMI程序,为了测试跨内存空间(跨JVM)的远程方法调用,我把服务器端的以下class文件放到了国外服务器上面:

  • MyRemote.class
  • MyRemoteImpl.class
  • MyRemoteImpl_Stub.class

把以下客户端的class放到本地:

  • MyRemote.class
  • MyRemoteImpl_Stub.class
  • RmiClient.class

现在让我来测试一下,运行命令:

java RmiClient

从运行结果可以看出来,本地客户端成功调用到了远在欧洲的对象并把String值返回到了本地通过控制台打印出来。下一个待解决的问题是如何可以不需要stub文件来进行远程方法调用,正在学习中。

玩玩RMI的更多相关文章

  1. tomcat RMI 停不掉

    项目采用jfinal框架,做了一个RMI的服务,对其它程序提供服务.实现上,写了一个RmiPlugin package com.wisdombud.cloudtalk.plugin; import j ...

  2. Exception thrown by the agent : java.rmi.server.ExportException: Port already in use

    今天有个应用一直起不来,感觉配置都对啊,奇了怪了.看日志发现如下: STATUS | wrapper | 2017/01/04 08:09:31 | Launching a JVM...INFO | ...

  3. RMI(远程接口调用)

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

  4. Java RMI之HelloWorld篇

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

  5. Spring远程调用技术<1>-RMI

    在java中,我们有多种可以使用的远程调用技术 1.远程方法调用(remote method invocation, RMI)  适用场景:不考虑网络限制时(例如防火墙),访问/发布基于java的服务 ...

  6. Java的RMI远程方法调用实现和应用

    最近在学习Dubbo,RMI是很重要的底层机制,RMI(Remote Method Invocation)远程方法调用是一种计算机之间利用远程对象互相调用实现双方通讯的一种通讯机制.使用这种机制,某一 ...

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

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

  8. 启动tomcat时 错误: 代理抛出异常 : java.rmi.server.ExportException: Port already in use: 1099;

     错误: 代理抛出异常 : java.rmi.server.ExportException: Port already in use: 1099; nested exception is:  java ...

  9. JAVA RMI 实例

    下面我将介绍一个完整的实例,让初学者能快速体验RMI的功用. 分为以下四个步骤 1. 创建远程接口及声明远程方法(HelloInterface.java)2. 实现远程接口及远程方法(继承Unicas ...

随机推荐

  1. [ An Ac a Day ^_^ ] [kuangbin带你飞]专题八 生成树 UVA 10600 ACM Contest and Blackout 最小生成树+次小生成树

    题意就是求最小生成树和次小生成树 #include<cstdio> #include<iostream> #include<algorithm> #include& ...

  2. SQL总结之导入导出

    (5)还原数据库[倒库] [数据泵模式]先要在D盘创建个目录,如D:/dbback 然后去plsql中创建目录sql命令:create directory dbback as 'D:\dbback'; ...

  3. 关于Objective-C Associated Objects

    一.相关函数 与Associated Objects相关的函数有三个 1 void objc_setAssociatedObject(id object, const void *key, id va ...

  4. Unity3D脚本使用:Random

    实例: 为集合变量赋值,并运行,点击按钮,运行结果如图   

  5. AndroidAsyncHttp 临时修复 JsonHttpResponseHandler 避免死循环

    由于 AndroidAsyncHttp 1.4.4 的 JsonHttpResponseHandler  存在死循环的 BUG,1.4.5 版本发布不知道要何时,所以只能临时替换该类来修复这个错误. ...

  6. jenkins jmeter持续集成批处理jmx脚本

    这篇文章介绍jenkis jmeter的持续集成,利用jenkins定时任务去批处理执行jmeter的jmx脚本文件,并且生成测试报告 1:jmeter的安装这里我就不在赘述了,如有问题可参考我的jm ...

  7. 关于Android平台的搭建的心得---汪永骏

    我本来是.net开发的,但看到目前互联网形式都朝着移动端开发迈进.大势所向,我便也开始学习Android的开发 今天就是要聊一下,我对Android开发的一些心得.今天讲的是,我在搭建Android平 ...

  8. Proteus中MATRIX-8X8 LED灯的连接

    上面8个引脚用于选择行,低电平有效.下面8个引脚用于选择列,高电平有效. 经测试,红色点阵LED与之相反,是上面的引脚用于选择列,且高电平有效:下面的引脚用于选择行,低电平有效. 在AT89C51单片 ...

  9. [河南省ACM省赛-第三届] 素数 (nyoj 169)

    #include <iostream> #include <cstdio> #include <queue> #include <cstring> #i ...

  10. redis12--常用API

    上一篇总结我们使用我们本地的Eclipse中创建的jedis工程,链接到了我们处于VMware虚拟机上的Linux系统上的Redis服务,我们接下来讲一下jedis的一些常用的API.(1)jedis ...