分享

14.4.1 RMI介绍 - 《Spring 2.0宝典》 - 免费试读 - book.c...

 软件团队头目 2007-10-04

 RMI介绍

RMIRemote Method Invocation(远程方法调用)的 所写。它允许一个Java程序调用网络中另一台计算机上的Java方法,就如调用本机的方法一样。实现RMI调用的程序和被调用的方法,都必须是Java代码,即客户端和服务器端都必须通过纯Java实现。

RMI是基于Java的分布式编程模型,使用RMI进行远程方法调用时,无须考虑方法底层的网络传输细节。下面使用RMI的示例程序:

先编写RMI服务器端,RMI需要通过远程接口“暴露”服务。也就是说,所有想被客户机调用的方法都必须在Remote接口里声明,否则无法完成调用。远程接口如下:

远程接口必须集成java.rmi.Remote接口

public interface Server extends Remote

{

         //所有在Remote接口里声明的方法都必须抛出RemoteException异常

    String helloWorld(String name) throws RemoteException;

    Person getPerson(String name,int age)throws RemoteException;

}

远程接口必须继承java.rmi.Remote接口。远程接口里声明的方法会通过网络传输,而网络是不可靠的,因此,所有的远程方法都必须抛出RemoteExceptionRMI服务是典型的面向接口编程,只有在远程接口里定义的方法才会作为远程服务。

下面是远程服务提供类,远程服务提供类必须实现远程接口,并继承java.rmi.server.UnicastRemoteObject对象,继承该类能“暴露”远程服务。

//远程服务类,远程服务类必须继承UnicastRemoteObject,并实现Remote接口

public class ServerImpl extends UnicastRemoteObject implements Server

{

         //远程服务类必须拥有构造器,且构造器必须抛出RemoteException异常

    public ServerImpl()throws RemoteException

    {

}

//实现Remote接口必须实现的方法

    public String helloWorld(String name)throws RemoteException

    {

           return name + ", 您好!";

    }

//实现Remote接口必须实现的方法

    public Person getPerson(String name,int age)throws RemoteException

    {

           return new Person(name,age);

    }

         //下面是服务类的本地方法,不会“暴露”为远程服务。

         public void info()

{

         System.out.println(“我是本地方法”);

}

//下面提供程序入口,将远程类实例绑定为本机的服务。

    public static void main(String[] args)throws Exception

{

           //创建远程服务类实例

           Server imp = new ServerImpl();

                   //注册远程服务的端口

                   LocateRegistry.createRegistry(1099);

                   //将远程服务实例绑定为远程服务。

                   Naming.rebind("rmi://:1099/fdf", imp);

    }

}

远程服务类必须有构造器,即使找个构造器什么都不做。而且,构造器必须抛出RemoteException异常。将两个编辑好的源文件存盘,然后编译。对于使用RMI,仅仅编译还不够,还必须使用rmic命令编译服务类,编译服务类是为了生成stubskeleton——查看存放class文件的地方,多了如下两个class文件:

q      ServerImpl_Stub.class

q      ServerImpl_Skel.class

这两个类就是服务类生成的stubskeleton。客户端程序面向接口编程,客户端部分需要Server接口的class文件,还需要stub文件。客户端的源代码如下:

public class RMIClient

{

         //主方法,程序入口

    public static void main(String[] args)throws Exception

    {

                   //通过JNDI查找远程服务

           Server ser = (Server)Naming.lookup("rmi://:1099/fdf");

                   //调用远程方法

           System.out.println(ser.helloWorld("yeeku"));

                   //调用远程方法。

           System.out.println(ser.getPerson("yeeku",28));

    }

}

从客户端程序看,无法感受到Server的实现在远端。程序调用Server实例方法时,与平常调用方法只有非常细微的区别:调用远程方法必须抛出RemoteException

再看远程方法的返回值,helloWorld的返回值是String,而getPerson的返回值则是Person对象。远程方法的返回值必须有一个要求:实现Serializable接口。因为远程的方法的参数、返回值都必须在网络上传输,网络只能传输字节流,因此,要求参数、返回值都可以转换成字节流——即实现序列化。主程序的如下一行代码,用于注册远程服务端口:

LocateRegistry.createRegistry(1099);

1099RMI服务的默认端口。然后执行如下代码绑定远程服务

Naming.rebind("rmi://:1099/fdf", imp);

客户端使用JNDI查找,查找远程服务名。将远程服务对象类型转换成远程接口类型,客户端面向接口编程。RMI的具体实现,依然是依赖于底层的Socket编程。RMI依赖于TCP/IP传输协议,服务器端skeleton建立ServerSocket监听请求,而客户端建立Socket请求连接。RMI实现了网络传输的多线程、IO等底层细节。这些细节的实现就隐藏在rmic命令的执行中:使用rmic命令编译时生成的两个class文件:

q      stub:该文件用于与客户端交流,建立Socket请求连接。

q      skeleton:该文件用于与服务器端交流,建立ServerSocket监听请求。

RMI的原理示意如图14.2所示。

14.2 RMI原理示意图

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多