今天在看代理设计模式,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. C# 修改iframe url

    一.修改本级的iframe url 首先在js中编写函数: <script type="text/javascript"> function reloadfrm2() ...

  2. Hololens生成与安装(旁加载)应用

    Hololens生成应用的几种方式: 一:HoloToolkit编辑器生成appx应用 二:Vistul Studio 2015 创建应用 旁加载概述: 你可以将应用旁加载到你的设备,而无需将它们提交 ...

  3. RedisDesktopManager

    下载地址: https://github.com/uglide/RedisDesktopManager/releases

  4. [Jenkins]admin用户登陆,提示登陆无效(之前登陆OK,三天没有登陆,突然提示登陆无效,重启无法解决)的解决方法

    问题出现现象: 系统一直正常,突然某天登陆,提示用户无效,无法登陆成功. 问题分析过程: 1.查看日志:/var/log/jenkins/jenkins.log(通过ps -elf | grep je ...

  5. iOS程序崩溃相关的处理办法

    一.bug追踪 1.捕获异常:Exception breakpoint 步骤: 2.终止调用:Symbolic breakpoint 步骤:前两步和一 基本是一样的,不截图了,只是在第二步选择的时候选 ...

  6. mysql无法输入中文

    #查看系统的环境变量 echo $LANG zh_CN.UTF-8 vim /etc/sysconfig/i18n 1 LANG="en_US.UTF-8"2 SYSFONT=&q ...

  7. Activiti(工作流)学习资源总结

    刚进公司第一个项目就是oa项目,不会activiti,只得自学,途中搜集到的activiti学习资源总结 1.activiti初体验 http://blog.csdn.net/bluejoe2000/ ...

  8. es6--(三)set和map数据结构

    1.Set和WeakSet Set与数组相似,但是Set结构的成员必须是唯一的. WeakSet与对象类型,但是WeakSet结构的成员只能是对象 Set结构的实例属性和方法 属性: Set.prot ...

  9. 记一次-angular-数字格式化

    一个收费功能模块,需要做数据验证. input标签的ng-model的数据格式化 <input type="number" class="form-control& ...

  10. BOS物流管理系统-第八天

    BOS物流管理系统-第八天-权限系统设计-Shiro 回顾: 两大块业务:基础设置模块,业务派单模块. 两天:权限控制. 拦截器大的范围的.纯登录级别(认证级别)大颗粒的权限控制的一种技术. Shir ...