首页

java远程方法调用rmi应用场景及代码示例

标签:rmi,java,远程方法调用,分布式,RMI,RPC,对象流     发布时间:2015-06-01   

一、前言

java编程语言设计之初就是面向对象和支持网络的,基于对象的rmi已内置java分布式系统平台中。对于tcp/ip网络编程,基于socket套接字进行编程展开,对于socket编程,需要把复杂的业务定义统一提交到该接口上,所以就会有大量的重复代码,在复杂的分布式系统计算中,容易出错,同时代码的维护难度比较大。需要实现快速、高效、安全、易扩展系统就变得追求和倡导的主题。Java RMI实现机理是基于代理的类加载器获取远程虚拟机内存中的对象,详情参见下方第五章节

二、RMI简介

        远程方法调用(Remote Method Invocation ,RMI),实现在不同的Java虚拟机(JVM)间对象间的通信,客户端(一个JVM)可以同步调用服务器(其它JVM)的对象的方法。作为rmi底层实现,会有很负责的Socket实现,对于用户只提供简单透明的对象调用方法接口,rmi基本结构包括三个抽象层,具体如下:

1、存根/框架层(Stubs/Skeletons Layer)

       在基层上设计上,主要引入两大对象存根(Stub)和框架(Skeleton),当然在最底层基于tcp/ip协议将所有数据对象转化为字节流(byte stream),在基层层面上都是基于Proxy代理设计模型进行设计,stub代表远处客户方对象在本地的存根(调用映象),Skeleton类具体实现连接及stub通信,向远程服务实现参数实例化调用,并返回结果给到stub对象上,总而言之,Skeletons实现的整个框架设计的高内聚支持类,没有具体的业务设计关联

2、远程引用层(Remote Reference Layer)

远程引用层定义和配置支持RMI连接的调用语义(semantics)

进行远程访问调用需要用到远程调用协议JRMP(Java Remote Method Protocol),具体的调用对象方法包含在java.rmi.server包内

3、传输层(Transport Layer)

传输层在终端和服务端间建立基于流的网络连接,同时配置并管理这些连接

三、RMI开发步骤如下:

使用rmi编写c/s模式应用程序,主要包括以下6个步骤:

1.定义远程调用接口

2.实现远程接口

3.准备远程调用所设计的调用对象

4.生产存根对象stub和框架skeleton

5.用Rmiregistry找到远程对象

6.运行调试RMI应用接口

四、RMI示例代码

1.服务端代码包括主服务类Server.java、业务接口及实现类(Business.java、BusinessImpl.java)

Server类

import java.rmi.registry.LocateRegistry;@b@import java.rmi.registry.Registry;@b@import java.rmi.server.UnicastRemoteObject;@b@@b@/**@b@ * @author issuser@b@ *@b@ */@b@public class Server {@b@@b@    /**@b@     * @param args@b@     */@b@    public static void main(String[] args) throws Exception{@b@        // TODO Auto-generated method stub@b@        int port=9527;@b@        String name="BusinessDemo";@b@        Business business=new BusinessImpl();@b@        UnicastRemoteObject.exportObject(business,port);@b@        Registry registry=LocateRegistry.createRegistry(1099);@b@        registry.rebind(name, business);@b@@b@    }@b@@b@}

Business接口类

import java.rmi.Remote;@b@import java.rmi.RemoteException;@b@@b@public interface Business extends Remote {@b@@b@    public String echo(String message) throws RemoteException;@b@}

BussinessImpl接口实现类

import java.rmi.RemoteException;@b@@b@public class BusinessImpl implements Business {@b@@b@    @Override@b@    public String echo(String message) throws RemoteException {@b@        // TODO Auto-generated method stub@b@        if("quit".equalsIgnoreCase(message.toString())){@b@            System.out.println("Server will be shutdown!");@b@            System.exit(0);@b@        }@b@        System.out.println("Message from client:"+message);@b@        return "Server response:"+message;@b@    }@b@    @b@}

2.客户端调用类Client,同时也包括服务端映射Business接口类及BusinessImpl类

import java.rmi.registry.LocateRegistry;@b@import java.rmi.registry.Registry;@b@@b@public class Client {@b@@b@    public static void main(String[] args) throws Exception{@b@        // TODO Auto-generated method stub@b@        @b@        Registry registry=LocateRegistry.getRegistry("localhost");@b@        String name="BusinessDemo";@b@        Business business=(Business)registry.lookup(name);@b@        business.echo("hello ruirui");@b@    }@b@@b@}

五、源码分析

1. 像上面4.2中客户端调用类java.rmi.registry.LocateRegistory类,从下图源码中可以看出代理工具类获取注册器对象

java远程方法调用rmi应用场景及代码示例

2. 然后找到对应的工具类源码sun.rmi.server.Util,可以看出其是由代理类通过类加载器找出远程对象

java远程方法调用rmi应用场景及代码示例

3. 然后通过代理映射类java.lang.reflect.Proxy,代理类原理通过加载器来实例化

java远程方法调用rmi应用场景及代码示例

4. 如上面4.2中通过java.rmi.registry.Registry类的lookup方法,如下图可以看出其实通过Hashtable存储查找

java远程方法调用rmi应用场景及代码示例