1)RMI(remote method invocation)是java原生支持的远程调用,RMI采用JRMP(java RemoteMessageing Protocol)作为通信协议。可以认为是纯java版本的分布式远程调用解决方法。
2)RMI的核心概念
3)RMI实现步骤
1、创建远程接口,并继承java.rmi.Remote接口
2、实现远程接口,并继承:UnicastRemoteObject
3、创建服务器程序,createRegistry() 方法注册远程对象
4、创建客户端程序,(获取注册信息,调用接口方法)
RMI_SERVER
package com.itheima.service;import java.rmi.Remote;
import java.rmi.RemoteException;public interface UserService extends Remote {String sayHello(String name) throws RemoteException;
}
package com.itheima.service.impl;import com.itheima.service.UserService;import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;public class UserServiceImpl extends UnicastRemoteObject implements UserService {public UserServiceImpl() throws RemoteException {}@Overridepublic String sayHello(String name) throws RemoteException {return name + "调用了服务端的sayHello方法";}
}
package com.itheima.server;import com.itheima.service.UserService;
import com.itheima.service.impl.UserServiceImpl;import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;public class ServerMain {public static void main(String[] args) throws RemoteException, AlreadyBoundException, MalformedURLException {//启动RMI注册服务,指定端口号LocateRegistry.createRegistry(8888);//创建要被访问的远程对象的实例UserService userService = new UserServiceImpl();//将远程对象实例注册到RMI注册服务器上Naming.bind("rmi://127.0.0.1:8888/UserServer", userService);System.out.println("服务端启动中………………");}
}
RMI_CLIENT
package com.itheima.service;import java.rmi.Remote;
import java.rmi.RemoteException;public interface UserService extends Remote {String sayHello(String name) throws RemoteException;
}
package com.itheima.client;import com.itheima.service.UserService;import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;public class ClientMain {public static void main(String[] args) throws RemoteException, NotBoundException, MalformedURLException {UserService userService = (UserService) Naming.lookup("rmi://127.0.0.1:8888/UserServer");String s = userService.sayHello("客户端");System.out.println(s);}
}
注意:
client中Naming.lookup需要强转成UserService 此时的package路径要与server中的Userserver中的路径一致:
否则出现报错:
"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe" "-javaagent:D:\ruanjian\ideaiu14\ideaiu14\idea\IntelliJ IDEA 2020.1\lib\idea_rt.jar=63728:D:\ruanjian\ideaiu14\ideaiu14\idea\IntelliJ IDEA 2020.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_131\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar;F:\RPC\RMI\rmi_client\target\classes" com.itheima.client.ClientMain
Exception in thread "main" java.rmi.UnmarshalException: error unmarshalling return; nested exception is: java.lang.ClassNotFoundException: com.itheima.service.UserService (no security manager: RMI class loader disabled)at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)at java.rmi.Naming.lookup(Naming.java:101)at com.itheima.client.ClientMain.main(ClientMain.java:12)
Caused by: java.lang.ClassNotFoundException: com.itheima.service.UserService (no security manager: RMI class loader disabled)at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:556)at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:646)at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:311)at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:265)at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1758)at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1710)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2000)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1535)at java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)... 3 moreProcess finished with exit code 1
运行结果:
需要先启动服端:
服务端启动中………………
客户端结果:
客户端调用了服务端的sayHello方法
说明:在两个项目中,客户端成功的调用了服务器的sayHello()方法