Registry registry = LocateRegistry.getRegistry(); registry.rebind(RemoteService.name, stub);
Java 平台支持两种方式来做分布式应用。IDL与RMI方式。IDL是基于CORBA规范的,能够用来调用非java写的语言应用。
IDL使用CORBA/IIOP协议,而RMI使用JRMP协议。
J2SE5的RMI的开发主要分7步:
1 定义远程接口
2 写server端代码
3 执行rmic
4 写client
5 注冊RMI
6 执行server
7 执行client
RMI的远程接口必须是 java.rmi.Remote的实现类。
并且client和server必须在同一个包下,全部的方法參数和返回值必须是基本类型或者实现了序列化接口的对象。异常不能乱抛,异常必须是RemoteException,或者它的子类。
RMIC已经过时了。
J2SE5的RMI我就不讲了。那个须要RMIC来生成一些东西,贼复杂。
尽管RMIC还保留在JDK的bin文件夹下,可是执行RMIC还是会出现警告的,RMIC过时了。
到了J2SE8,RMI开发就相当简单了:
我把步骤总结一下:
1 写服务接口
2 写远程服务实现类
3 写简单的server
4 写client
server接口非常easy。
public interface RemoteService extends Remote{ String hello() throws RemoteException; String name = "remoteService"; }
这个接口非常easy的,可是符合了RMI的规范。
首先实现了Remote的接口,其次方法返回值是string,string是能够序列化的,再次,抛出的异常是RemoteException异常。
实现类非常easy:
public class RemoteServiceBean implements RemoteService { public RemoteServiceBean() { super(); } @Override public String hello() throws RemoteException { return "Hello world!"; } }
最复杂的是server:
public class Server { static int port = 2019; public static void main(String[] args) throws RemoteException, AlreadyBoundException, MalformedURLException { RemoteService remoteService = new RemoteServiceBean(); RemoteService stub = (RemoteService)UnicastRemoteObject.exportObject(remoteService,port); LocateRegistry.createRegistry(Registry.REGISTRY_PORT); Registry registry = LocateRegistry.getRegistry(); registry.rebind(RemoteService.name, stub); System.out.println("Bounded!"); } }
这个server能够说,麻雀虽小。五脏俱全。
首先是获取接口的存根,也叫stub。
UnicastRemoteObject.exportObject方法就是获取存根的。
事实上是创建了一个代理对象,这个代理对象的实现就是调用远程的server方法。
其次启动注冊server。关于服务的注冊,我们之前可能是没有这个概念的。
注冊server感觉非常多余。
之前我们接触的远程服务,可能有RESTFUL,EJB,WEB SERVICE。RESTFUL没有注冊server,EJB、web service也没有。RMI与它们不同,注冊server相当于一个中介,远程server把存根对象(stub)发送给注冊server,然后注冊server将其保存起来。client通过注冊server提取存根,存根是个代理。代理内部通过网络连接来调用server端的代码。使用服务注冊机制方便的一点是client代码非常简洁。EJB因为没有注冊server,所以复杂的调用是通过client来实现的,client使用ejbclient类库来调用。
LocateRegistry.createRegistry代码就是启动注冊server的。
Registry registry = LocateRegistry.getRegistry(); registry.rebind(RemoteService.name, stub);
这两行代码是将存根对象通过网络发送到注冊server上。
再次,启动远程server。
执行main函数就能够同一时候启动注冊server和远程server了。
RMI是用来做分布式服务的。
分布式意味着远程server能够有多个。
由一个单独的注冊server来管理多台远程server提供的存根。
全部client都通过这唯一的一台注冊server来获取存根,调用服务。
可是问题在于注冊server仅仅有一台,当请求压力大了,注冊server非常easy爆掉!这就是RMI的瓶颈所在。