针对现在火热的RPC框架,jdk也有自己自带的工具集。java.rmi包就是为了实现远程方法调用技术而开发的。rmi为java语言独有,不支持其他语言,所以能够完美的支持java语言所独有的特性。由于是靠java原生的序列化机制、底层通信基于BIO实现的Scoket完成,所以性能较差,高并发情况下不推荐此方案。主要的思路是服务端要继承UnicastRemoteObject类,通过Naming类的底层,也就是Registry类来通过固定的接口将服务端对象通过一种特殊的字符串格式将该对象序列化后绑定到远程对象Naming.bind("rmi://ip:port/name",object),其他服务端可以通过Naming.lookup("rmi://ip:port/name")来获取该对象。但是使用途中发现一个问题,某些时候通信无法正常经行。其实是因为通信端口是随机的,某些随机的端口可能被防火墙拦截,此处可以使用工厂模式指定通信端口。
//面向接口编程。定义一个接口 public interface HelloService extends Remote { String say(String type) throws RemoteException; }
//实现接口的类,该类需要序列化, public class HelloServiceImpl extends UnicastRemoteObject implements HelloService { private static final long serialVersionUID=-6109531770408903300L; @Override public String say(String type) throws RemoteException { return "hello,"+type; } public HelloServiceImpl() throws RemoteException { super(); } }
//服务端代码 public class ServiceMain { public static void main(String[] args) throws Exception { HelloServiceImpl helloService = new HelloServiceImpl(); //创建通信接口 LocateRegistry.createRegistry(8801); //将对象绑定为远程对象 Naming.bind("rmi://localhost:8801/helloService",helloService); System.out.println("ServiceMain is provice Rmi Service now"); } }
public class ClientMain { public static void main(String[] args) throws Exception{ //引入服务,获取远程对象 HelloService helloService = (HelloService)Naming.lookup("rmi://localhost:8801/helloService"); //调用远程对象的代码 可以执行 System.out.println("Service return result is:"+helloService.say("world")); } }