一、JAVA RMI概述
RMI(Remote Method Invocation):远程方法调用。
JAVA RMI(Remote Method Invocation,远程方法调用)是用Java在JDK1.2中实现的,它大大增强了Java开发分布式应用的能力,是纯JAVA的RPC框架(java对RPC的实现)。
JRMP(Java Remote Messaging Protocol)是专为Java的远程对象制定的通信协议。
JAVA RMI可以实现像在调用当前进程中提供的服务一样调用其他进程中提供的服务方法,不必关注底层网络协议部分(例不需要自己创建Socket链接等)。
RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。
二、深入理解 JAVA RMI
首先要先启动注册器,当前服务器启动后会将服务注册到注册器。客户端通过URI去注册器中获取服务信息,注册器返回服务的代理对象(Stub)。
当客户端调用服务方法时,Stub会通过JRMP协议(TCP/IP)链接服务端,服务端更具参数信息调用具体服务方法,返回结果。
继承关系:
三、实战
接口:
- 必须继承 java.rmi.Remote 接口;
- 接口中每个方法必须抛出 java.rmi.RemoteException 异常;
package com.miselehe.rmi.api; import java.rmi.Remote; import java.rmi.RemoteException; /** * 公共接口 * */ public interface ISayHello extends Remote { public String sayHello(String name) throws RemoteException; public String sayHi(String name) throws RemoteException; }
服务实现类:
- 必须继承 java.rmi.server.UnicastRemoteObject类;
- 需要声明抛出 java.rmi.RemoteException异常的构造方法;
package com.miselehe.rmi.server.service; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import com.miselehe.rmi.api.ISayHello; public class SayHelloImpl extends UnicastRemoteObject implements ISayHello { /** * */ private static final long serialVersionUID = 1L; public SayHelloImpl() throws RemoteException { super(); // TODO Auto-generated constructor stub } public String sayHello(String name) throws RemoteException { // TODO Auto-generated method stub return "Hello! " + name; } public String sayHi(String name) throws RemoteException { // TODO Auto-generated method stub return "Hi! " + name; } }
启动服务端:
package com.miselehe.rmi.server; import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import com.miselehe.rmi.api.ISayHello; import com.miselehe.rmi.server.service.SayHelloImpl; /** * RMI 服务端 - 发布服务 * */ public class RMIService { public static void main(String[] args) { try { ISayHello sayHello = new SayHelloImpl(); // 启动注册表程序 或 手动去JDK安装目录下 执行 bin/rmiregistry.exe LocateRegistry.createRegistry(123); //1099是默认端口, 客户端调用时可省略端口号 // 注册URI 和 服务信息 // 格式: rmi://域名或IP:端口号/服务标记名称 Naming.rebind("rmi://127.0.0.1:123/sayHello", sayHello); System.out.println("Server start!!!"); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }客户端调用:
package com.miselehe.rmi.client; import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; import com.miselehe.rmi.api.ISayHello; /** * RMI 客户端 * */ public class RMIClient { public static void main(String[] args) { // TODO Auto-generated method stub try { // 代理对象 SayHelloImpl_stub // 此处必须使用 接口处理, 不能使用实现类(此处返回的是代理对象,类型转换失败) ISayHello sayHello = (ISayHello)Naming.lookup("rmi://127.0.0.1:123/sayHello"); System.out.println(sayHello.sayHello("搜答案的")); System.out.println(sayHello.sayHi("阿道夫")); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NotBoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }