【RMI】--Proxy代理模式之远程代理

RemoteProxy

     远程代理模式是代理模式的一个具体应用案例,当你需要在本地的JVM上调用其他JVM上对象的方法时, 远程代理可以非常容易的帮你实现。
1.创建远程接口
package com.dreamli.rmi.test01;

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

/**
 * @Description : 定义远程接口,需要扩展 Remote并在远程方法上抛出 RemoteException
 * @Warning :
 * @Author DreamLi
 * @Package ProxyPattern - com.dreamli.rmi.test01 - MyRemote.java
 * @Date : 2018年1月21日 下午12:54:03
 * @Version : 1.0.0
 */
public interface MyRemote extends Remote {

    public String sayHello() throws RemoteException;

}

2.实现远程接口,提供真正的远程服务
package com.dreamli.rmi.test01;

import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/**
 * @Description : 远程服务 --- 提供真实服务的对象
 * @Warning :
 * @Author DreamLi
 * @Package ProxyPattern - com.dreamli.rmi.test01 - MyRemoteImpl.java
 * @Date : 2018年1月21日 下午1:06:04
 * @Version : 1.0.0
 */
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {

    private static final long serialVersionUID = 6780156706603775814L;

    protected MyRemoteImpl() throws RemoteException {
        super ();
    }

    @Override
    public String sayHello() throws RemoteException {
        return "Hello, RMI..." ;//真实的服务
    }
    public static void main(String[] args ) {
        try {
            // 创建远程服务对象
            MyRemote myRemote = new MyRemoteImpl();
            // 绑定远程服务对象到 rmiregistry
            Naming.rebind( "RemoteServer" , myRemote );
        } catch (Exception e ) {
            e .printStackTrace();
        }
    }
}

3.产生Stub和Skeleton
将目录切到项目的bin目录下或WEB项目的classes目录下, 运行 rmic com.dreamli.rmi.test01.MyRemoteImpl 产生stub文件




4.启动registry
依然是在bin/classes 目录下运行 remiregistry 命令启动registry


5.启动服务
运行远程服务实现的 main() 方法 —> MyRemoteImpl

6.测试
package com.dreamli.rmi.test01;

import java.rmi.Naming;

public class MyRemoteClient {
    public static void main(String[] args ) {
        new MyRemoteClient().go();
    }
    public void go() {
        try {
            MyRemote myRemote = (MyRemote) Naming.lookup( "rmi://127.0.0.1/RemoteServer” );// RemoteServer 就是注册(rebind)时的 key
            String hello = myRemote .sayHello();
            System. out .println( hello );
        } catch (Exception e ) {
            e .printStackTrace();
        }
    }
}

运行 client,结果如下:


虽然这种方式可以实现, 但是正如上面图中所示, rmic 方式已经过时,因此使用 Registry 代替

2.Registry实现RMI
远程接口依然不变
package com.dreamli.rmi.test02;

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

/**
* @Description: 定义远程接口,需要扩展 Remote并在远程方法上抛出 RemoteException
* @Warning:
* @Author DreamLi
* @Package ProxyPattern - com.dreamli.rmi.test01 - MyRemote.java
* @Date: 2018年1月21日 下午12:54:03
* @Version: 1.0.0
*/
public interface MyRemote extends Remote {

    public String sayHello() throws RemoteException;

}

远程服务
package com.dreamli.rmi.test02;

import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/**
* @Description: 远程服务 --- 提供真实服务的对象
* @Warning:
* @Author DreamLi
* @Package ProxyPattern - com.dreamli.rmi.test01 - MyRemoteImpl.java
* @Date: 2018年1月21日 下午1:06:04
* @Version: 1.0.0
*/
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {

    private static final long serialVersionUID = 6780156706603775814L;

    protected MyRemoteImpl() throws RemoteException {
        super();
    }

    @Override
    public String sayHello() throws RemoteException {
        return "Hello, RMI...";
    }
    
    public static void main(String[] args) {
        try {
            // 创建远程服务对象
            MyRemote myRemote = new MyRemoteImpl();
            // 绑定远程服务对象到 rmiregistry
            Naming.rebind("RemoteServer", myRemote);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

用来代替 rmic 和 registry 的registry
package com.dreamli.rmi.test02;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class ServerRegistry {

    private static Registry registry;

    private static Registry getRegistry() throws RemoteException {
        try {
            return registry == null ? (registry = LocateRegistry.createRegistry(9001)) : registry;
        } catch (RemoteException e) {
            e.printStackTrace();
        }

        throw new RemoteException("Create registry faild...");
    }

    public static void main(String[] args) {
        try {
            MyRemote server = new MyRemoteImpl();
            getRegistry().bind("RemoteServer", server);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}


客户端:
package com.dreamli.rmi.test02;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class MyRemoteClient {
    public static void main(String[] args) {
        new MyRemoteClient().go();
    }
    
    public void go() {
        try {
//          MyRemote myRemote = (MyRemote) Naming.lookup("rmi://127.0.0.1:9001/RemoteServer”);//这种方式也可以
            Registry registry = LocateRegistry.getRegistry("127.0.0.1", 9001);
            MyRemote myRemote = (MyRemote) registry.lookup("RemoteServer");
            String hello = myRemote.sayHello();
            System.out.println(hello);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


测试:
首先运行 ServerRegistry, 然后运行 MyRemoteClient, 可以看到远程服务的返回数据:

你可能感兴趣的:(DesignPattern)