RMI笔记

RMI(remote method invoke)
一、基本原理
RMI通过代理来负责客户和远程对象之间通过socket进行通信的细节。
RMI分别为远程对象生成了客户端代理和服务端代理。客户端的叫stub,服务端的叫Skeleton。
Stub进行参数编组,将下列信息发给服务端:
1)要访问的远程对象的名字
2)被调用的方法的描述
3)编组后的参数的字节序列

服务端由skeleton来处理这一信息,进行下列动作
1)反编组参数
2)定位要访问的对象
3)调用远程对象相应的方法
4)对返回值或者异常进行相应的编组
5)将编组后的内容发给客户端。

二、创建一个RMI应用
1、创建远程类接口
        1)直接或间接继承Remote接口
        2)接口中所有的方法抛出RemoteException异常
2、创建远程类,实现远程接口
        1)远程类继承UnicastRemoteObject,
        2)可以不继承,直接在构造函数中调用UnicastRemoteObject.exportObject(this,0).
        3)远程类的构造函数需要声明抛出RemoteException
        4)远程方法必须抛出RemoteException
3、创建服务器程序,
        通过 JNDI的javax.naming.Context在rmigegistry注册表中注册远程对象。
        几个方法bind,rebind,lookup,unbind
        创建远程对象:
        HelloService service1 = new HelloServiceImpl("service1");
        Context namingContext = new InitialContext();
        namingContext.rebind("rmi:HelloService",service1);
4、创建客户端程序。
        获取远程对象的存根对象
       String url = "rmi://localhost/";
       HelloService service1 = (HelloService) namingContext.lookup(url
                                        + "HelloService1");

三、远程对象设计工厂模式
        就是创建一个工厂类和产品类,这个工厂类和产品类都是远程对象,都要实现remote接口,远程方法都要声明RemoteException
        1)客户端每次访问一个远程对象的时候,都会得到一个新的stub对象。
        2)stub对象重写了equal方法,如果两个stub对象都是对应一个远程对象的代理,则equal返回true。equal不是远程方法。
        3)stub对象操作远程方法,会导致远程对象的实现类进行相应的操作。

四、远程方法中的参数与返回值的传递
        在服务器端和客户端传递的方法或返回值,必须是远程对象、可序列化对象,或者是基本类型数据,否则在进行远程方法调用的时候会出现UnmarshalException.

五、回调客户端的远程对象

六、远程对象的并发访问

七、分布式垃圾收集
        1、RMI框架采用分布式垃圾收集机制。
        1)DGC回收规则:一个远程对象不受到任何本地引用和远程引用,这个对象可以被回收。
        2)租约通知:通知服务器远程对象被引用了。
        3)租约期限:通过java.rmi.dgc.leaseValue来设置。
        4)通过实现java.rmi.server.Unreferenced接口,可以来释放相关资源。
        5)强制服务端等待客户端获得该远程对象的引用service.isAccessed()

八、远程对象的equals()、hashCode()和clone()方法
        stub重写了equal和hashcode方法,没有重写clone

九、使用安全管理器
1、客户端使用安全管理器的两个步骤
        1)创建安全策略文件,例如:
        grant{
          permission java.net.SocketPermission "*:1024-65535","connect";
        };
        2)为客户端设置安全策略文件和RMISecurityManager
        System.setProperty("java.security.policy", SimpleClient.class
                                        .getResource("client.policy").toString());
    System.setSecurityManager(new RMISecurityManager());//会从client.policy中读取安全策略
2、通过命令进行设置
    java -D java.security.policy=c:\chapter11\client.policy SimpleClient
3、如果服务端需要从客户端动态加载类,也要按照类似方式设置。

十、RMI应用部署以及类的动态加载
        java.rmi.server.codebase系统属性,从指定的位置动态加载类文件

十一、远程激活
        1、RMI框架提供了一种远程激活机制,当有一个客户去访问远程对象的时候,还去创建这个远程对象。和延迟加载差不多的概念。
        rmid:激活系统。远程对象由这个系统来管理生命周期。
       2、RMI类介绍
Activatable:可以被激活的远程对象都是这个类的实例,ActivationID表示激活对象的唯一标识符。
       ActivationGroup:激活组,可以被激活的对象都放在这里面。
       ActivationGroupDesc:描述激活组(属性文件,启动虚拟机的路径)  
    一个激活组对应一个java虚拟机,rmid程序根据ActivationGroupDesc提供的信息来启动一个java虚拟机,然后在这个虚拟机内创建并管理可以激活的远程对象,每个激活组都有唯一的id,用ActivationGroupID来表示。        
    ActivationDesc用来描述一个可以激活的远程对象。
ActivationDesc(ActivationGroupID groupID, String className, String location, MarshalledObject data)
3、一个远程对象如果希望被激活,它的远程类应该继承java.rmi.activation.Activatable类。
4、rmid程序激活对象步骤

//1.创建一个激活组描述符ActivationGroupDesc对象
                        ActivationGroupDesc group = new ActivationGroupDesc(prop, null);
                        //2.向rmid程序注册ActivationGroup,配置信息由group提供
                        ActivationGroupID id = ActivationGroup.getSystem().registerGroup(
                                        group);
                        String classURL = System.getProperty("java.rmi.server.codebase");
                        MarshalledObject param1 = new MarshalledObject("service1");
                        MarshalledObject param2 = new MarshalledObject("service2");
                        //3.创建激活对象描述符ActivationDesc
                        ActivationDesc desc1 = new ActivationDesc(id,
                                        "activate.HelloServiceImpl", classURL, param1);
                        ActivationDesc desc2 = new ActivationDesc(id,
                                        "activate.HelloServiceImpl", classURL, param2);
                        //4.向rmid注册激活对象,配置信息由desc提供
                        HelloService s1 = (HelloService) Activatable.register(desc1);
                        HelloService s2 = (HelloService) Activatable.register(desc2);
                        System.out.println(s1.getClass().getName());

                        Context namingContext = new InitialContext();
                        //5.向rmiregistry注册激活对象
                        namingContext.rebind("rmi:HelloService1", s1);
                        namingContext.rebind("rmi:HelloService2", s2);

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值