文档章节

使用JAVA RMI开发分布式应用程序

邓小峰
 邓小峰
发布于 2009/04/13 10:07
字数 1587
阅读 2134
收藏 2

       RMI,远程方法调用(Remote Method Invocation)是Enterprise JavaBeans的支柱,是建立分布式Java应用程序的方便途径。RMI是非常容易使用的,但是它非常的强大。
  RMI的基础是接口,RMI构架基于一个重要的原理:定义接口和定义接口的具体实现是分开的。下面我们通过具体的例子,建立一个简单的远程计算服务和使用它的客户程序,你可以在适当的地方使用RMI来实现分布式服务。

RMI主要包括几个部分: 

远程服务的接口定义

● 远程服务接口的具体实现

● 桩(Stub)和框架(Skeleton)文件

● 一个运行远程服务的服务器

● 一个RMI命名服务,它允许客户端去发现这个远程服务

● 类文件的提供者(一个HTTP或者FTP服务器)

● 一个需要这个远程服务的客户端程序

大白话解释一下就是:有一个特殊的服务器端和一个特殊的客户端;为什么特殊呢?因为这个服务器提供服务的方法必须实现Romote接口,而且必须提供stub和skeleton文件,还不许有一个命名服务;客户端要实现客户端的接口;

下面我们手动实现RMI,建立一个简单的分布式服务的例子

 第一步:服务器上程序接口

Calculator.cs

import java.rmi.Remote;

/**
 * @author 小峰 远程服务接口
 */
public interface Calculator extends Remote {
 public int add(int a, int b) throws java.rmi.RemoteException;
}
第二步:服务器上接口的实现

CalculatorImpl.cs文件

import java.io.Serializable;
import java.rmi.RemoteException;

/**
 * @author 小峰 接口的实现
 */
@SuppressWarnings("serial")
public class CalculatorImpl implements Calculator, Serializable {

 /**
  * 实现接口方法,两个整数相加
  */
 @Override
 public int add(int a, int b) throws RemoteException {
  return a + b;
 }

}
 
第三步:生成桩(Stubs)和框架(Skeletons)

D:\JAVAProject\hiberante\WebContent\WEB-INF\classes>D:\JDK6\bin\rmic CalculatorI
mpl
现在就可以使用了

第四步:编写服务端程序

RomoteServer.cs

import java.rmi.Naming;

/**
 * @author 邓小峰
 *
 */
public class RomoteServer {
 public RomoteServer() {
  try {
   Calculator c = new CalculatorImpl();
   Naming.rebind("rmi://localhost:1099/CalculatorService", c);
  } catch (Exception e) {
   System.out.println("Trouble: " + e);
  }
 }

 /**
  * @param args
  */
 public static void main(String[] args) {
  new RomoteServer();
 }

}
 
第五步:客户端程序

RemoteClient.cs

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

public class RemoteClient {

 /**
  * @param args
  * @throws NotBoundException
  * @throws RemoteException
  * @throws MalformedURLException
  */
 public static void main(String[] args) throws MalformedURLException,
   RemoteException, NotBoundException {
  try {
   Calculator c = (Calculator) Naming
     .lookup("rmi://localhost/CalculatorService");
   System.out.println(c.add(4, 5));
  } catch (Exception ex) {
   System.out.println(ex);
  }
 }
}

第六步:注册,不管是服务端程序还是服务端程序,要想启动都需要先注册

D:\JAVAProject\hiberante\WebContent\WEB-INF\classes>D:\jdk6\bin\rmiregistry

第七步:启动服务器程序

D:\JAVAProject\hiberante\WebContent\WEB-INF\classes>java RomoteServer

第八步:启动客户端程序

D:\JAVAProject\hiberante\WebContent\WEB-INF\classes>D:\jdk6\bin\java RemoteClient

 

呵呵,是不是很看到运算结果了?

 

RMI的深入点介绍

 

一:工作原理

RMI系统结构,在客户端和服务器端都有几层结构。

         ---------                                      ---------

        | 客户对象|                                    | 远程对象|

         ---------                                     ---------

            | |                                             | |

------------------------------       ---------------------------------

     |  占位程序 Stub |                         |  骨干网 Skeleton |

-------------------------------         ------- ------------------------

               | |                                  | |

     -----------------------------------------------------------------

               |  远 程 引 用 层 Remote Reference Layer  |

     ------------------------------------ ----------------------------

                                    | |

                   ------------------------------------

                      |  传 输 层 Transport Layer  |

                   ------------------------------------

方法调用从客户对象经占位程序(Stub)、远程引用层(Remote Reference

Layer)和传输层(Transport Layer)向下,传递给主机,然后再次经传

输层,向上穿过远程调用层和骨干网(Skeleton),到达服务器对象。

占位程序扮演着远程服务器对象的代理的角色,使该对象可被客户激活。

远程引用层处理语义、管理单一或多重对象的通信,决定调用是应发往一个

服务器还是多个。传输层管理实际的连接,并且追追踪可以接受方法调用的

远程对象。服务器端的骨干网完成对服务器对象实际的方法调用,并获取返

回值。返回值向下经远程引用层、服务器端的传输层传递回客户端,再向上

经传输层和远程调用层返回。最后,占位程序获得返回值。

(以上为引用他人原话)

二:rmi相关类

rmi由5个包和3个应用工具组成:

     java.rmi                        组织客户端的rmi类,接口和异常

     java.rmi.sever                 组织服务器端的rmi类,接口和异常

     java.rmi.registry              组织用于管理rmi命名服务的类

     java.rmi.dgc                    组织用于管理分布式垃圾收集的类

     java.rmi.activation            组织用于实现按需缉获的rmi服务的类

     rmic                            编译器,生成stub和sketon

     rmiregistry                     一个为rmi提供命名服务的服务器,这项服务把名字和对象关联在一起

     rmid                            一个支持rmi激活框架的服务器

但是大多数情况下,我们只需要使用每个包的一部分方法和接口就可以成功的实现一个使用rmi分布式解决方案

 


实际应用的思考

如果我们要是使用RMI,当然不会是这样笨拙的使用方式,肯定得有RMI的容器,让我们轻易地编程和注册、客户端轻易调用。什么容器提供RMI服务器端的开发、注册和调用呢?我们可以轻而易举地把上面的代码服务器端程序改成一个web程序,客户端程序也是一样,关键是容器要能够自动register就ok了。

下面列举一个Tomcat中注册RMI的例子

我们知道我们可以在tomcat启动的时候预先加载一些类,我们就可以把绑定的过程(也就是我们的服务器代码写成在servlet中加载),所以例子如下

web.xml添加


  
  
  
  RMIServlet
  RMIServlet
  
  RMIServlet
  0
 

RMIServlet.cs如下


import java.io.IOException;
import java.rmi.AccessException;
import java.rmi.AlreadyBoundException;
import java.rmi.NoSuchObjectException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import rmi.Calculator;
import rmi.CalculatorImpl;

/**
 * Servlet implementation class RMIServlet
 */
public class RMIServlet extends HttpServlet {

 /**
  *
  */
 private static final long serialVersionUID = -1942511496585743905L;

 /**
  * @see HttpServlet#HttpServlet()
  */
 public RMIServlet() {
  super();
 }

 /**
  * @see Servlet#init(ServletConfig)
  */
 public void init(ServletConfig config) throws ServletException {
  Registry registry = null;
  try {
   registry = LocateRegistry.createRegistry(1099);
  } catch (RemoteException e1) {
  }
  Calculator c = new CalculatorImpl();
  try {
   registry.bind("CalculatorService1", c);
  } catch (AccessException e) {
   e.printStackTrace();
  } catch (RemoteException e) {
   e.printStackTrace();
  } catch (AlreadyBoundException e) {
   e.printStackTrace();
  }
 }

 /**
  * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse
  *      response)
  */
 protected void service(final HttpServletRequest request,
   final HttpServletResponse response) throws ServletException,
   IOException {
 }

 public void destroy() {
  Registry registry = null;
  try {
   registry = LocateRegistry.getRegistry(1099);
  } catch (RemoteException e1) {
  }
  try {
   UnicastRemoteObject.unexportObject(registry, false);
  } catch (final NoSuchObjectException e) {
  }
  try {
   registry.unbind("CalculatorService1");
  } catch (final AccessException e) {
  } catch (final RemoteException e) {
  } catch (final NotBoundException e) {
  }

 }
}

 

然后

D:\jdk6\bin\rmiregistry

重新启动Tomcat试试,就ok了,现在已经是自动注册和绑定了

 

© 著作权归作者所有

共有 人打赏支持
邓小峰
粉丝 26
博文 38
码字总数 17272
作品 0
广州
高级程序员
私信 提问
加载中

评论(1)

1
111
文章介绍还不错,我对RMI的编程不是很明白,我现在也要做RMI的编程,有两个学科,可以说是两张表,他们之间有共同的一个参数,现在要修改这个参数数值,怎么让服务器通知另个学科中的参数也跟着修改,这个要怎么去实现?你能否提供下资料和建议,谢谢啊!
RMI:Java中的分布式计算框架

RMI全称是Remote Method Invocation-远程方法调用,Java RMI在JDK1.1中实现的,其威力就体现在它强大的开发分布式网络应用的能力上,是纯Java的网络分布式应用系统的核心解决方案之一。其实...

qq_39521554
2018/05/15
0
0
用RMI实现基于Java的分布式计算(1)

向您介绍使用RMI实现Java的分布式计算。由于Java具有跨平台、代码可移植性、安全高效等广泛而强大的功能,因而在开发网络Java分布式应用的时候,可以用它自身的机制实现分布式计算。 概述 随...

山哥
2012/02/24
0
0
【亲测】RMI之Hassion

一、RMI RMI(Remote Method Invocation,远程方法调用)是Java在JDK1.2中实现的, Java RMI 支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用。(即它能...

Armymans
2018/11/30
0
0
Java EE部分核心技术简介

EJB — JavaEE的基石: 1、 EJB (Enterprise JavaBeans) : 一个Java服务器端组件开发的规范,定义了一个用来开发面向对象分布式应用组件的标准方法,软件厂商根据它来实现EJB服务器。 Java...

顶层设计
2012/08/03
0
0
J2EE平台简介 

1.1.1 J2EE规范 J2EE(Java 2 Platform,Enterprise Edition)是SUN公司定义的一个开发分布式企业级应用的规范。它提供了一个多层次的分布式应用模型和一系列开发技术规范。多层次分布式应用模...

曾赛
2009/09/06
382
0

没有更多内容

加载失败,请刷新页面

加载更多

【git命令】git-rebase

修改历史提交记录 作用简要概括为:可以对某一段线性提交历史进行编辑、删除、复制、粘贴;因此,合理使用rebase命令可以使我们的提交历史干净、简洁! 前提:不要通过rebase对任何已经提交到...

echojson
13分钟前
1
0
Python+Appium自动化测试环境搭建

1.Android SDK 下载SDK并配置系统环境变量ANDROID_HOME。 2.Appium 2.1 直接下载安装 官网下载安装appium-desktop-setup.exe。 2.2 通过npm下载安装 appium本质是一个nodejs库所以要先安装n...

维他ViTa
50分钟前
2
0
MacOS安装单机版HBase

MacOS安装HBase,必然是用于测试了,从简入手、从简配置。 直接通过brew安装即可: brew install hbase 成功安装后,验证是否成功,如果不出意外的话,应该有如下输出: RippleMBP:~ userna...

RippleChan
今天
3
0
linux下oracle随操作系统启动而启动

大家一定还记得,我们在windows下安装oracle后,重起windows,数据库会自动启动,但在linux下,如果我们重起了操作系统, 就会发现数据库需要手工去输入,这个本来有好处,让dba知道操作系统已经重起...

突突突酱
今天
4
0
nacos之springboot

本地操作系统:ubuntu18,我使用docker的方式启动nacos服务 docker image方式启动nacos 在docker hub上可以搜到nacos-server List-1.1 拉去最新的版本 mjduan@mjduan-ubuntu:/opt/software$ ...

克虏伯
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部