`
xm_king
  • 浏览: 395370 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
博客专栏
Group-logo
Spring技术内幕读书笔...
浏览量:15658
社区版块
存档分类
最新评论

JNDI和Java RMI远程调用(一)

    博客分类:
  • JAVA
阅读更多

 

     对于 Java EE 开发来说, Java RMI JNDOI 是两个非常重要的特性。 RMI 提供了远程调用的特性,而 JNDI 为应用程序提供了命名和目录服务,对于没有开发过大型项目的人来说,这些概念可能很陌生,那么为什么 Java EE 需要 JNDI RMI 呢,这源于企业级开发的需要。分布式结构有以下几个企业级系统所必须的特性:

        1.          性能:企业级系统需要强大的性能,单靠一台服务器通常无法满足性能需要,所以需要多台服务器协同工作。

        2.          健壮性:冗余的服务器组成阵列,当某个服务器无法正常工作的时候,保证系统用户不受影响。

        3.          可维护性:各个部分独立分开来,维护自己的运行状态,提高整个系统的灵活性和可维护性。

正是由于这些原因,企业级系统采用了分布式的结构,将系统分为各个不同的组件,各个组件之间靠消息或远程调用等机制来通信。在这种情况下就需要提供两类机制来保证组件之间能顺利协同工作。

        a)          命名和目录机制:在分布式结构下,如何定位一个资源、一个对象就成为了非常重要的问题。打个比方,一个人若在一个团队里和伙伴协同工作,那么当他需要别人帮忙的时候,就需要知道如何去寻找他人,一个办法就是建立通讯录。同样的道理,如果对象 A 需要调用不再同一台服务器上的远程对象 B 提供的方法,那么对象 A 如何寻找对象 B 呢。这是也可以建立通讯录的机制, JNDI Java Nam Directory Interface Java 命名和地址接口)就可以扮演通讯录的角色。利用 JNDI 的目录机制就相当于在通讯薄中翻查某个人的联系信息,当然,要使用通讯薄查找,首先要建立通讯薄,把具体的联系方式记录在通讯薄上,这就是 JNDI 提供的命名服务,也就是将资源绑定到目录上的简称。

         b)         消息机制和远程调用机制:找到远程对象或者资源之后,可以发送消息来通信,也可以利用远程调用机制来直接调用远程对象的方法。前者属于一种松耦合的结构,双方仅仅通过消息作为媒介,不直接发生关系, JMS 实现了这种方式;而后者属于紧耦合的结构,也就是 RMI 方式, JavaRMI Java Remote Method Interface 的简称。为什么需要 RMI ?设想一下,当对象 A 找到远程对象 B 之后,需要调用 B 的方法,但是调用 B 的方法,和调用本地的方法不同,由于 B A 不在同一台服务器上(准确的说,不再同一台 JVM 中),就造成了很多的问题。

  l   如何传递参数? Java 的参数传递是传引用而非传值的,所以 A 不能将指向本机内存中的一个引用当做参数传递给 B

  l 当远程组件在不同平台、不同语言下运行的,又该如何与其进行通信。

     Java RMI 实现远程调用

从很早之前开始,分布式环境就需要在不同主机之间进行进程通信和方法调用, RPC 就是为了这个目的而产生的,它允许一个程序访问另一台机器上的另一个程序的方法。而 RMI RPC 的基础上更进一步, RPC 是远程访问程序方法,而 RMI 允许访问远程对象。所以和 RPC 相比,基于面向对象开发的 RMI 可以充分利用继承、封装和多态的面向对象开发的特点。

Java RMI Java 的远程调用方式,利用它可以开发出分布式的远程对象,这些远程对象生存在不同的虚拟机上,并利用 RMI 协议进行通信。基本的 Java RMI 采用的是 JRMP Java Remote Method Protocol ),这个协议帮助 Java 远程对象进行通信,但是不支持对其他平台的支持,特别是对流行的 CORBA 的支持 (CORBA 支持 IIOP) ,所以在 Java RMI 的基础上,人们建立了 Java RMI  - IIOP。

注意:远程是一个与实际位置无关的概念,一个远程对象可以和客户端在同一个机器上,也可以分别在网络上的两台机器上。

当然有了美好的愿望还不够,要实现 RMI 需要解决很多的问题。

         1)         数据格式的兼容问题。在两个通信的组件之间数据格式会出现不一致,比如整数类型在A组件上是用2个字节表示的,而在B组件上是用4个字节表示的,这样当一个整数类型的参数从A组件传到B组件的时候,就会发生数据格式不一致的现象。这在 JAVA 之外的很多语言来说,是一个非常棘手的问题,但是 Java 的通用数据格式就避免了这种情况的发生。

        2)         参数传递方式的选择,一般来说,程序设计有两种参数的传递方式:值传递( pass by value )和引用传递 (pass by reference) 传值是将数据做一次拷贝,将拷贝得到的数据副本作为参数进行传递。用这种方式,被调用的方法中修改的只是数据的副本,而不是数据本身,所以原数据没有作修改。引用传递是将数据的引用传递,任何修改都将作用到数据本身。在远程调用的情况下,两种方式都可以传递参数,但都有一些问题。 对于值传递问题,由于是传递副本,所以远程对象的方法无法改变数据本身。另一个问题是若要传递对象参数,则需要将对象序列化,当对象空间很大的时候,序列化会带来很大的开销。 传递一个本地数据的引用到远程组件之后,远程组件根据此应用在其本地找到数据。所以还需要一次远程调用,往回访问引用数据本身。在 JavaRMI 中对这两种方式都支持。

        3)         系统的不稳定性

      在只有一个 JVM 的情况下,如果此 JVM 崩溃了,那么所有运行在其之上的程序全都一起失效,不会产生一部分对象仍然存在而另一部分消失的情况。但是在远程调用的环境中,有多个 JVM 在同时进行,如果其中一台 JVM 崩溃了,那么在其中的远程对象也消失,如果其他 JVM 中的对象不知道这些远程对象已经消失了,那么他们就会继续试图和这些“幽灵”对象进行通信,并发生异常。另外,由于远程对象之间通过网络进行通信,当网络发生故障的时候,对象应该得到通知。这些情况在 JavaRMI 中都得到了很好的支持。

 

要理解对象之间如何远程调用首先需要了解 Stubs( 存根 ) Skeletons( 骨架 ) 的概念。假设有两个对象 A B B 是远程对象,提供方法供 A 调用,我们称 B 为服务器端,对象 A 是远程方法的调用方,我们称 A 为客户端。 JavaRMI 如何让 A 对象调用 B 的方法呢,实际上 JavaRMI 会在客户端模拟被调用的对象 B ,生成一个本地对象,这个本地对象就叫 Stub (存根),存根生存在客户端,但代表了远程对象,它接受 A 的方法调用,并将这些方法调用映射到远端实际 B 对象。对于对象 A 来说,由于有了存根的存在,远程调用形式看起来都和本地调用一致。

B 对象所在的服务器端,对应地存在 Skeleton( 骨架 ) skeleton 是远程对象的代理,负责从网络接受调用的请求。并且将这些调用转移给实现的对象,所以可以认为,远程调用实际是通过 stub skeleton 进行的。

客户端和服务器端都不直接和对方以及网络打交道,有了 stub skeleton ,开发者可以从这些工作中解脱出来。

了解了 stubs skeletons 之后,我们来看以下服务器端的远程对象。要使用远程对象首先要有一个远程接口。因为 RMI 调用的是远程接口。在面向对象设计中,一个基本的思想就是接口与实现相分离。接口定义了一个对象暴露给外界的信息。从一个用户来看,接口表示了这个用户能对这个对象进行的操作。而实现是程序内部的实际逻辑,是操作的具体过程,这一部分往往不需要暴露给外界。通过接口与实现的分离,开发者可以在不改变接口的情况下 ( 不改变用户的调用方式 ) ,改变程序方法的实现。

RMI 采用了同一思想,在 RMI 的远程调用中,客户端只能调用远程的接口。所以远程对象实现之前首先需要建立一个远程接口,此接口定义了这个远程对象对外提供的所有方法,同时此接口需要同时继承 java.rmi.Remote 接口,比如如下的代码:

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface HelloInterface extends Remote {

  public void sayHello(String from)throws RemoteException;

}

 

 

 

 

 

 


这里定义了一个接口 HelloInterface , 它继承了 Remote 接口,所以是一个远程接口。在接口 HelloInterface 中,自定义了 sayHello ()方法。这就是远程对象提供的方法。方法声明会抛出 RemoteException 异常,当网络不正常的情况出现的时候就会出现这个异常。开发者可以处理这个异常,决定当网络故障等情况出现时的程序行为。 (Java RMI 努力让网络变得透明,即远程调用和在本地调用形式上一致,但是同时开发者需要注意,网络问题是不可避免的。 )

定义了远程接口之后,就需要实现远程对象。远程对象实现了远程接口,提供具体功能的实现。要让一个对象成为一个远程对象,并且让远程宿主 ( 远程宿主:就是提供了对远程调用支持的容器,让它来控制远程对象。当远程接口被调用的时候,远程宿主自动调用远程对象的对应方法。 ) 可以调用它的方法,可以使用以下方式的任何一种:

继承 Javax.rmi.PortableRemoteObject 对象,这样当远程对象生成的时候,会自动调用 PortableRemoteObject 的构造函数,这个构造函数帮助对象可以被远程调用

手动将对象设置成远程对象。可能对象本身已经继承了某个基类,而无法继承 PortableRemoteObject, 这是需要手动将对象设置为远程对象:

javax.rmi.PortableRemoteObject.exportObject()

下面就是实现了 HelloInterface 接口的远程对象 HelloImpl

 

 

 

import java.rmi.RemoteException;

import javax.rmi.PortableRemoteObject;

public class HelloImpl extends PortableRemoteObject implements HelloInterface {

    protected HelloImpl() throws RemoteException {

       super();   }

    public void sayHello(String from)throws RemoteException {

       System.out.println("hello from"+from);

       System.out.flush();

    }

}

 

 

 

 


 

从上面的代码中,我们可以看到:

1)      HelloImpl 继承 PortableRemoteObject 而称为远程对象

2)      HelloImpl 实现 HelloInterface 远程接口

3)      HelloImpl 的构造函数调用基类构造函数,并且此构造函数会抛出 RemoteException 异常。

4)      HelloImpl 实现了 sayHello 方法。

在一个典型的远程对象的调用中,还需要有一个服务器端的应用来生成远程对象,并将其暴露给外界。同时还存在连接服务器端的客户端。接下来介绍调用远程对象时,如何传递参数。之前已经讲过,一般有两种传递参数的方式:值传递和引用传递。在 RMI-IIOP 中,对两种方式都支持。但实际上, RMI-IIOP 的参数传递是值传递的,引用传递是通过模拟的方式实现的。

Java RMI 的基本概念已经介绍完了,要使用远程对象,不仅要实现远程对象,换需要提供能够定位远程对象的机制,下面一节将要介绍 JNDI

分享到:
评论

相关推荐

    三种方式实现java远程调用(rmi),绝对可用

    Java远程调用(Remote Method Invocation,RMI)是Java平台中一种重要的分布式计算技术,它允许在不同网络环境中的Java对象之间进行透明的交互。在本文中,我们将深入探讨三种不同的RMI实现方法:原始方式、Spring...

    Java RMI远程方法调用

    3. **RMI Registry**:RMI注册表是一个服务,用于存储远程对象的引用,它使用JNDI(Java Naming and Directory Interface)服务提供命名和目录功能。客户端通过注册表查找并获取远程对象的引用。 4. ** stubs 和 ...

    Java RMI 用于远程调用 进行分布式开发

    ### Java RMI 用于远程调用 进行分布式开发 #### 概述 Java RMI(Remote Method Invocation)是Java平台提供的一种实现分布式计算的技术,它允许开发者在不同JVM间进行方法调用,如同调用本地对象一样简单。通过...

    rmi 远程调用 实现客户端之间会话

    在Java RMI中,一个JVM作为服务器,暴露远程接口,而其他JVM作为客户端,通过这些接口进行远程调用。 标题中的“rmi 远程调用 实现客户端之间会话”指的是利用RMI技术让多个客户端与同一服务端建立会话,进行交互。...

    JAVARMI远程方法调用简单实例.docx

    在实际应用中,RMI可以与其他Java技术如EJB、JMS(Java消息服务)和JNDI(Java命名和目录接口)结合使用,以构建复杂的分布式系统。然而,需要注意的是,虽然RMI提供了面向对象的远程调用,但它本身并不处理并发控制...

    Java分布式处理技术RMI,JNDI,

    Java 分布式处理技术 RMI,JNDI Java 分布式处理技术是指在 Java 平台上实现分布式...RMI 和 JNDI 是 Java 分布式处理技术的核心组件,RMI 实现了对象之间的交互,而 JNDI 提供了一个统一的接口来访问不同的目录服务。

    基于RMI的Java远程调用.zip

    在"基于RMI的Java远程调用.pdf"文件中,可能会详细解释这些步骤,并提供示例代码来帮助读者理解和实践RMI技术。它可能会涵盖常见问题,如处理异常、优化性能、使用RMI-IIOP(RMI over IIOP,一种在CORBA基础设施上...

    JAVA实现简单分布式,JAVA调用远程方法

    在Java编程领域,分布式系统和远程方法调用(Remote Method Invocation, RMI)是关键的高级概念,它们允许不同计算机间的程序协同工作,提高系统的可扩展性和灵活性。本篇文章将探讨如何使用Java来实现简单的分布式...

    java 远程调用rmi实现的简单例子

    Java RMI(Remote Method Invocation,远程方法调用)是Java平台提供的一种用于在不同网络节点上的Java对象之间进行通信的技术。这个技术允许一个Java对象在一台机器上执行方法,而这个方法的实现实际上位于另一台...

    JavaRMI超棒书

    - **生成存根和骨架**:使用Java RMI工具生成客户端和服务端的存根和骨架代码,以实现远程调用。 - **测试与部署**:编写测试应用程序验证远程对象的功能,最后部署应用程序并确保其正常运行。 #### 五、案例分析...

    JAVA RMI测试代码

    Java RMI(Remote Method Invocation,远程方法调用)是Java平台提供的一种分布式计算技术,它允许Java对象在不同的网络环境中进行交互,就像调用本地方法一样。RMI是构建分布式应用的重要工具,尤其适用于需要跨...

    java远程方法调用

    1. 定义远程接口:创建一个接口,继承自`java.rmi.Remote`,并在接口中声明将被远程调用的方法。方法声明中必须包含`throws RemoteException`,用于处理可能出现的远程通信异常。 2. 实现远程接口:创建一个类实现...

    java RMI demo

    Java RMI(Remote Method Invocation,远程方法调用)是Java平台提供的一种分布式计算技术,它允许在不同的Java虚拟机之间进行方法调用,仿佛对象就在本地一样。RMI是Java在网络编程中的一个重要组成部分,尤其在...

    java_in_rmi.rar_Java RMI_RMI java_rmi _精通rmi

    首先,RMI的核心概念是远程方法调用,它允许一个Java对象调用位于另一台计算机上的对象的方法。这种机制依赖于Java的序列化机制,将远程对象的引用转化为可以在网络上传输的字节流,然后在目标机器上反序列化恢复...

    JAVA rmi教学课件

    总的来说,RMI是Java中实现分布式计算的关键技术,它通过存根、骨架和远程接口的机制,提供了透明的远程调用能力,简化了跨JVM的编程。开发者可以通过学习和理解RMI,构建出高效且易于维护的分布式系统。

    java-rmi-server.rar_Java RMI_rmi _服务器

    1. 创建远程接口:首先定义一个继承自java.rmi.Remote的接口,声明所有要远程调用的方法。 ```java public interface MyRemoteInterface extends Remote { String doSomething(String input) throws ...

    技术专栏 _ 深入理解JNDI注入与Java反序列化漏洞利用.pdf

    这种注入可以和RMI服务相结合,以实现攻击者定义的Java方法的远程调用。 文章中提到了JdbcRowSetImpl利用链和FastJson反序列化漏洞,这些是JNDI注入攻击利用的实例。JdbcRowSetImpl是Java的一个类,它允许通过JNDI...

    JAVA RMI入门教程

    骨架则在服务器端运行,它接收到客户端的远程调用,将这些调用转换为服务器上的本地调用,并将结果返回给客户端。存根和骨架由RMI编译工具自动生成,这个工具会分析服务器端的类,生成对应的存根和骨架代码。 RMI...

Global site tag (gtag.js) - Google Analytics