作为工作3年多的我,发现在自己在代码的设计缺乏良好的思路有,所以想学习系统的设计模式,最近看了接口模式、适配器、外观、组合、代理模式,
说实话组合模式看着比较迷惑,后续还要看几遍多理解下,刚好在看代理模式,写个小例子,并学习下RMI(远程方法调用)
1、代码文件结构如下:
2、Rocket.java 远程接口,必须继承Remote的接口,Remote接口并不包含任何方法,只用于标识其方法可以从非本地虚拟机上调用的接口。
任何远程对象都必须直接或间接实现此接口。只有在“远程接口”(扩展 java.rmi.Remote
的接口)中指定的这些方法才可远程使用。
接口中方法都需要throws RemoteException,RemoteException
是许多与通信相关的异常的通用超类,这些异常可能会在执行远程方法调用期间发生。
远程接口(扩展 java.rmi.Remote
的接口)的每个方法必须在其 throws 子句中列出 RemoteException
。
package com.jaws.proxy;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* 远程接口,必须继承Remote接口
* @author jiangpan
*
*/
public interface Rocket extends Remote{
public void start() throws RemoteException;
}
3、RocketImpl.java,远程对象,实现Rocket接口;必须继承UnicastRemoteObject类,UnicastRemoteObject用于导出带 JRMP 的远程对象和获得与该远程对象通信的 stub。我并知道JRMP是什么,就百度了下JRMP,以下是百科中对JRMP的解释:
package com.jaws.proxy;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
/**
* 远程对象,必须继承UnicastRemoteObject
* @author jiangpan
*
*/
public class RocketImpl extends UnicastRemoteObject implements Rocket{
public RocketImpl() throws RemoteException {
super();
// TODO Auto-generated constructor stub
}
@Override
public void start() throws RemoteException {
// TODO Auto-generated method stub
System.out.println("server: rocket starting....");
}
}
4、通过JDK中的RMIC.exe工具编译RocketImpl.class
通过RMIC编译后,将在同级目录RocketImpl_Stub.class,这个类就是工具为RocketImpl(远程对象)自动生成的代理类(stub),stub是用于返回给客户端的代理对象,客户端通过stub对象调用远程对象的方法,stub对象隐藏网络传输的过程,使我们只需要写简单的代码就能调用远程对象的方法。
5、启动rmiregistry服务,有两种方式启动
a.通过命令方式启动
b.通过代码方式启动 LocateRegistry.createRegistry(5000);//如果是在实际开发中,我觉得通过代码的方式启动比命令启动好
6、RegisterRocket .java,创建远程对象,并注册到对象注册表中
package com.jaws.proxy;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
/**
* 创建远程对象,并注册
* @author Administrator
*
*/
public class RegisterRocket {
public static void main(String[] args) {
try {
//通过代码的方式启动RMIRegistry服务
LocateRegistry.createRegistry(5000);
RocketImpl biggie = new RocketImpl();
//对象与HTTP地址绑定,格式为rmi://host:port/name,
Naming.rebind("rmi://localhost:5000/Biggie", biggie);// 将指定名称重新绑定到一个新的远程对象
System.out.println("registered biggie");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
启动完成,程序一直在运行状态
7、ShowRocketClient .java,模拟客户端调用的远程方法
package com.jaws.proxy;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class ShowRocketClient {
public static void main(String[] args) {
try {
Context context = new InitialContext();
//通过JDNI获取远程对象
Object stub1 = context.lookup("rmi://localhost:5000/Biggie");
//通过RMI获取远程的代理对象
Object stub2 = Naming.lookup("rmi://localhost:5000/Biggie");//返回与指定 name
关联的远程对象的引用(一个 stub)
Rocket rocket1 = (Rocket)stub1;
rocket1.start();
Rocket rocket2 = (Rocket)stub2;
rocket2.start();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NotBoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
运行客户端程序后,远程端打印日志,证明的远程对象的start()被执行