- 浏览: 452376 次
- 性别:
- 来自: 西安
文章分类
最新评论
-
进退取舍:
谢谢,这个用上了!!
Java 一个线程池的示例 -
pb_water:
感谢楼主,打算买楼主的书,支持一下,楼主功德无量
JavaScript内核系列第0版整理稿下载 -
lancezhcj:
有图会直观的多呢,再摸索摸索
有限自动机与建模 -
hsmsyy:
这里应该是原创了吧,楼主我觉得闭包的作用:实现面向对象。有待商 ...
JavaScript内核系列 第7章 闭包 -
wll52:
在应用退出之前,需要释放连接 con.disconnect() ...
使用smack与GTalk通信
Java的远程方法调用(Remote Method Invocation) 是为了分布式计算而提出来的,最近做一个项目需要用到,所以学习了一番,现在将一个简单的demo贴出来,以便想要学习RMI的同志可以快速上手。
RMI的调用是基于接口的,这个接口的定语需要客户知道,客户程序运行时需要一个实现该接口的类的存根(stub)。RMI的内部使用了TCP/IP连接方式,因此需要一个安全机制,且需要对客户机的权限进行一定的设置。
想要被远程调用的接口需要扩展Remote类,接口中定义的方法需要对RemoteException异常进行处理,当然,也可以只是抛出异常,将对异常的处理延迟到别的类。
RMI的安全处理机制使用的是RMISecurityManager,这个类提供必要的安全验证等处理,而权限控制是通过在客户端和服务端分别设置policy文件来做到的。
下面给出一个比较简单,但是能说明问题的例子,略去了不必要的代码,而且这个程序可以通过扩展达到你的某些特殊要求。
这个例子是这样,设计一个接口TaskContainer,这个接口对LinkedList进行了一个简单的封装,用途是作为Task的容器,其中可以加入多个Task,这些Task又分别可以独立运行(运行的逻辑可以自行扩展)。TaskContainer扩展了Remote类,因此是可以通过远程调用的。
package rmidemo; import java.rmi.Remote; import java.rmi.RemoteException; public interface TaskContainer extends Remote{ int getTaskCount() throws RemoteException; Task getTask() throws RemoteException; void addTask(Task t) throws RemoteException; }
下面是这个接口的实现
package rmidemo; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.util.LinkedList; public class TaskContainerImpl extends UnicastRemoteObject implements TaskContainer{ private static final long serialVersionUID = 4656230894967394376L; LinkedList<Task> taskList; public TaskContainerImpl() throws RemoteException{ taskList = new LinkedList<Task>(); } public Task getTask() throws RemoteException{ return taskList.size() > 0 ? taskList.removeFirst() : null; } public int getTaskCount() throws RemoteException{ return taskList.size(); } public void addTask(Task task) throws RemoteException{ taskList.add(task); } }
代码非常简单,就不用多说了,需要注意的是这个类需要扩展UnicastRemoteObject类,而且每个方法都要对RemoteException异常进行处理,这里只是简单的抛出。
下面是引用到的Task接口和其实现
package rmidemo; import java.rmi.Remote; import java.rmi.RemoteException; public interface Task extends Remote{ void execute() throws RemoteException; int getTaskID() throws RemoteException; }
Task也很简单,一个执行方法,一个获得Task的ID的方法,实现:
package rmidemo; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class TaskImpl extends UnicastRemoteObject implements Task{ private static final long serialVersionUID = -4520397655735981164L; private int taskID; protected TaskImpl(int i) throws RemoteException { taskID = i; } public void execute() throws RemoteException{ System.out.println("execute task = "+taskID);//这里只是一个简单的打印,你可以任意扩展之 } public int getTaskID() throws RemoteException{ return taskID; } }
定义完这些具体的逻辑,就可以在server端进行RMI的配置了,下面是RMI的主入口TaskServer
package rmidemo; import java.rmi.Naming; import java.rmi.RMISecurityManager; import java.rmi.registry.LocateRegistry; public class TaskServer { private static final String host = "localhost"; private static final int port = 9527; public static void main(String[] args){ System.setProperty("java.security.policy", "TaskServer.policy");//权限控制 if(System.getSecurityManager() == null){ System.setSecurityManager(new RMISecurityManager()); }//安全管理器的安装 try{ System.out.println("Constructing server"); LocateRegistry.createRegistry(port);//注册 TaskContainer container = new TaskContainerImpl(); container.addTask(new TaskImpl(1));//想容器中添加几个Task container.addTask(new TaskImpl(2)); container.addTask(new TaskImpl(3)); System.out.println("binding server impl to registry"); Naming.rebind("//"+host+":"+port+"/TaskContainer", container); }catch(Exception e){ e.printStackTrace(); } } }
先安装一个权限配置文件,再安装一个安全管理器,然后注册监听端口,并创建需要被远程调用的对象container,并通过Naming.rebind(String url, Object remote)方法对其绑定,以便远程对其按照URL进行访问。
权限的配置需要放在一个单独的文件中,这个例子中,配置放在TaskServer.policy文件中,其内容如下:
grant { permission java.net.SocketPermission "*:1000-9999","accept,connect,listen,resolve"; };
以上为服务器端的全部配置,不过,现在还不能使用,不是因为没有客户端,而是RMI需要一个存根stub才能使远程的线程来调用。
JDK里带了一个工具rmic.exe,这个工具可以根据扩展了Remote的类的class文件生成一个存根类,如根据x.class,生成x_stub.class。如果你的类有包名的话,你需要提供给rmic一个完整的包路径。
通过下面的命令即可完成这个动作:
$ rmic rmidemo.TaskContainerImpl $ rmic rmidemo.TaskImpl
现在在类的完整的路径下生成两个文件TaskContainerImpl_stub.class,TaskImpl_stub.class,服务端的所有配置到此结束。下面我们来看看客户端的代码。
相比服务端,客户端的代码就相当简单了,只需要一个用于测试的类即可:
package rmidemo; import java.rmi.Naming; import java.rmi.RMISecurityManager; public class TaskClient { private static final String host = "localhost"; private static final int port = 9527; public static void main(String[] args){ System.setProperty("java.security.policy", "TaskClient.policy");//install the policy file //install RMI Security Manager System.setSecurityManager(new RMISecurityManager()); String url = "rmi://"+host+":"+port+"/"; try{ TaskContainer container = (TaskContainer)Naming.lookup(url+"TaskContainer"); while(container.getTaskCount() > 0){ container.getTask().execute();//invoke the remote method. } }catch(Exception e){ e.printStackTrace(); } } }
同样,客户端也需要一个权限配置文件,TaskClient.policy
grant { permission java.net.SocketPermission "*:1000-9999","connect"; };
好了,客户端的代码及配置到此结束。现在,我们可以运行这个典型的RMI了,为了清晰起见,我们在控制台上运行这两个程序(分别启两个cmd窗口,因为RMI的server端不会退出[CTRL+C]),先启动server端,再运行客户端,可以看到,server窗口的输出为:
Constructing server binding server impl to registry execute task = 1 execute task = 2 execute task = 3
而客户端没有人户输出就结束了,这正好说明了RMI的意义和流程,client调用的是远程的方法(即server端的对象的方法)
好了,这个简单的例子就说到这里,程序很简单,我就不打包了。如果有任何问题,可以留言。
评论
permission java.net.SocketPermission
"*:1000-9999","connect";
授权什么意思么?只能连接1000-9999的端口服务么?
很喜欢你写的东西,有深度。
实际项目中的用处还是很大的,但是如果应用比较小的话,体现不出来,事实上如果项目小的话几乎不会用到RMI。
RMI的好处在于将底层的TCP/IP通信封装起来了,其中内部使用的仍然是通过socket来传输序列化过的对象,然后在远程反序列化,执行。
我之前开发过一个BBMS,http://code.google.com/p/bbms/
你可以看看,这里就大概给你说下其中的流程,只是一个方面的例子,你应该就可以理解为什么RMI很重要了:
BBMS是一个基于总线机制的消息系统,所有的实体都可以挂载在总线上,但是实体的物理地址是不知道的。比如,实体A和实体B都挂载在BUS上,但是A不知道B的物理地址,当A想B发送消息(比如邮件,短消息等)的时候,它就向BUS提交一个请求,BUS上有所有实体的注册表,如果收到消息了,它会根据目标实体做回调,比如B是在远程,然后BUS会调用B的一个方法来通知B消息到达,这里就是远程方法调用了。
简而言之,RMI主要用在分布式的系统上,而一般的项目很少涉及到分布式。我曾经在的一家公司做的产品主要是一个Report Server,其中有很多模块都是要支持RMI的。
很喜欢你写的东西,有深度。
发表评论
-
JavaScript内核系列 第15章 服务器端的JavaScript
2012-02-12 21:39 2325第15章已经在icodeit上发布,这一章分为上/下两篇,请朋 ... -
使用vim开发python及graphviz绘图
2011-12-23 14:49 6457基本需求 使用vim中的autocmd命令可以很容易的将正在 ... -
Java脚本技术应用实例
2011-01-22 11:24 4268前言 一直以来都很喜欢可以自由扩展的软件,这一点应该已经在很 ... -
可编程计算器(phoc)的设计与实现
2011-01-17 11:34 1983前言 借助JavaScript脚本 ... -
函数式编程(javascirpt)
2009-04-18 22:18 1264前言 Javascript,有人称 ... -
C和指针
2009-05-21 23:15 1117前言 指针是C的灵魂,正是指针使得C存在了这么多年,而且将长 ... -
C和指针(续)
2009-05-25 23:41 1360前言 上一篇《C和指针》可能对关于C和指针的有些内容没有说透 ... -
有限自动机与建模
2009-06-06 10:48 1786前言 在学校学程序设计语言的时候,能接触到的所有例子没有一个 ... -
事件和监听器
2009-06-21 22:06 1437前言 事件监听器是经 ... -
基于总线的消息服务(BBMS)的设计与实现
2009-07-25 22:19 1364前言 异步事件的通知机制在比较有规模的软件设计中必然会有涉及 ... -
JavaScript内核系列 第9章 函数式的Javascript
2010-05-13 19:20 3787第九章 函数式的Javascript 要说Ja ... -
JavaScript内核系列 第8章 面向对象的JavaScript(下)
2010-05-06 09:40 3672接上篇:JavaScript内核系列 第8章 面向对象的Jav ... -
JavaScript内核系列 第8章 面向对象的JavaScript(上)
2010-05-06 09:26 2906第八章 面向对象的 Javascript ... -
JavaScript内核系列 第7章 闭包
2010-05-04 08:48 3874第七章 闭包 闭包向来给包括JavaScript程序 ... -
JavaScript内核系列 第6章 正则表达式
2010-04-27 19:44 4050第六章 正则表达式 正则表达式是对字符串的结构 ... -
JavaScript内核系列 第5章 数组
2010-04-24 15:17 4531第五章 数组 JavaScript的数组也是一个比较 ... -
Swing小应用(Todo-List)之三
2010-04-22 20:47 2136前言 去年9月份开发的那个小工具sTodo,只是做到了能用, ... -
JavaScript内核系列 第4章 函数
2010-04-18 17:31 5095第四章 函数 函数,在C语言之类的过程式语言中 ... -
JavaScript内核系列 第3章 对象与JSON
2010-04-12 09:12 6133第三章 对象与JSON JavaScript对象与传 ... -
JavaScript内核系列 第2章 基本概念
2010-04-03 19:44 5689第二章 基本概念 ...
相关推荐
这个"JAVA RMI简单例子"旨在帮助我们深入理解RMI的基本原理和实现步骤。 RMI的核心概念包括远程接口、远程对象和RMIC编译器。首先,我们需要定义一个远程接口,该接口声明了可以在远程服务器上执行的方法。这些方法...
根据提供的文件信息,本文将详细解释RMI(远程方法调用)的概念、工作原理以及一个简单的RMI示例。RMI是一种Java技术,允许在不同的Java虚拟机(JVM)之间进行远程过程调用。 ### RMI简介 RMI是Java平台提供的一种...
以下是对"java RMI简单例子"的详细解释: 1. **RMI的基本概念**: - **远程对象**:在RMI中,一个对象如果可以在不同的JVM上执行其方法,那么就被称为远程对象。 - **远程接口**:定义远程对象需要实现的接口,...
在这个简单的例子中,我们将深入理解Spring RMI的工作原理以及如何实现一个基本的Spring RMI应用。 首先,让我们了解RMI的基本概念。RMI允许Java对象在不同的JVM之间进行通信,仿佛它们都在同一台机器上。它通过...
在"rmi简单例子,可以学习一下"这个主题中,我们将深入探讨RMI的基本概念、工作原理以及如何创建一个简单的RMI应用。 RMI的核心思想是将Java对象的方法调用跨越网络进行,使得一台机器上的客户端程序可以像调用本地...
RMI在Java中提供了一种强大的分布式计算模型,使得对象之间的远程通信变得简单且高效。通过定义远程接口、实现远程对象、在服务器端注册以及在客户端调用这些步骤,可以构建起一个完整的RMI系统。在实际应用中,RMI...
在本实例中,我们将详细了解如何创建一个简单的RMI应用。 首先,我们要定义一个远程接口。在Java RMI中,所有可被远程调用的方法都必须在一个实现了`Remote`接口的接口中声明。这个接口被称为远程接口。例如: ```...
以上就是一个简单的RMI应用实例,它展示了如何定义、实现远程接口,以及在服务器和客户端之间进行交互。在实际开发中,你可能需要考虑异常处理、安全性、性能优化等更多因素,但这个基础例子已经足以让你理解RMI的...
远程服务的接口定义 远程服务接口的具体实现 桩(Stub)和框架... 一个RMI命名服务,它允许客户端去发现这个远程服务 类文件的提供者(一个HTTP或者FTP服务器) 一个需要这个远程服务的客户端程序
spring 与rmi 的整合 1.首先编写接口 interface : 这里的接口要继承Remote, 它是一个标识接口 2.编写实现类 3.编写main方法用于启动 service 4 配置spring文件 编写客户端测试类
一个简单的RMI示例步骤如下: 1. 定义远程接口,如: ```java import java.rmi.Remote; import java.rmi.RemoteException; public interface MyRemoteInterface extends Remote { String doSomething(String ...
创建客户端RMI调用服务端的应用程序。 启动服务端,再启动客户端,测试是否调用成功。 如果客户端和服务端不在同一台电脑上,则需要对刚才定义的服务类采用rmic 编译一个客户端的框架类_stub并拷贝到客户端的类...
通过这个简单的实例,学习者可以了解到Java RMI的基本工作流程,以及如何在实践中部署和使用远程对象。深入研究后,还可以探索更复杂的场景,如并发调用、安全性控制、容错机制等,以构建更加健壮和高效的分布式系统...
### Java RMI基础知识与示例解析 ...通过以上详细分析,我们可以清楚地了解到如何使用Java RMI来实现简单的分布式应用。尽管RMI在现代Java开发中的使用频率不高,但了解其基本原理和技术细节仍然具有一定的价值。
总结来说,Java RMI简单示例主要展示了以下知识点: 1. **远程接口**:定义了远程方法的签名,需要继承`Remote`接口。 2. **远程对象**:服务器端的类实现远程接口,并继承`UnicastRemoteObject`,以支持远程调用。 ...
### RMI 使用实例详解 #### 一、RMI 概述 远程方法调用(Remote Method Invocation,简称 RMI)是 Java 平台提供的一种分布式计算技术,它允许开发者创建可跨网络调用的方法,就像在本地调用一样简单。RMI 的设计...
下面将详细解释RMI的基本概念、工作原理以及如何创建一个简单的RMI应用。 1. **RMI基本概念** - **远程对象**:RMI的核心是远程对象,它是驻留在网络上另一台计算机上的Java对象,可以通过网络调用其方法。 - **...
在这个"SpringRMI小例子"中,我们将深入探讨如何利用Spring框架来增强RMI的功能,使其更加灵活和易于管理。 首先,我们需要理解Spring框架在RMI中的角色。Spring提供了对RMI的高级抽象,通过其`org.springframework...
这个“简单的RMI实例”演示了如何在不依赖像Tomcat这样的Web服务器的情况下实现RMI。下面我们将深入探讨RMI的基本概念、配置过程以及如何创建和运行这个实例。 ### RMI基本概念 1. **远程对象(Remote Object)**:...