RMI,是java提供的远程方法调用技术,能够通过普通方法调用的简单写法,就能实现分布式服务调用,下面是百度上的解释:
技术架构
RMI 框架采用代理来负责客户与远程对象之间通过 Socket 进行通信的细节。RMI 框架为远程对象分别生成了客户端代理和服务器端代理。位于客户端的代理必被称为存根(Stub),位于服务器端的代理类被称为骨架(Skeleton)。
RMI的优缺点
优点:RMI代码简单,没有过多的配置,原理也很简单
缺点:基于JVM的规范,只能在JVM之间进行远程服务调用,不能跨语言调用
下面是一个1v1聊天的demo,完整源码:有角的圆/learn-java - Gitee.com
服务端代码
public class Server {
public static void main(String[] args) {
try {
// 创建注册表(端口 1099) RMISocketFactory
Registry registry = LocateRegistry.createRegistry(1099);
UserService service = new UserServiceImpl(registry);
// 绑定服务到注册表
registry.rebind("UserService", service);
System.out.println("Server has started.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
UserService
public interface UserService extends Remote {
// 客户端用户用户登录,通知服务端客户端上线了
String login(String name) throws RemoteException;
// 接收客户端用户发送的消息
ResponseMessage say(RequestMessage message) throws RemoteException;
}
UserServiceImpl
/**
* 远程服务需要继承UnicastRemoteObject
*/
public class UserServiceImpl extends UnicastRemoteObject implements UserService {
/**
*
*/
private static final long serialVersionUID = 1L;
private Registry registry;
public UserServiceImpl(Registry registry) throws RemoteException {
super(); // 初始化远程对象
this.registry=registry;
}
@Override
public ResponseMessage say(RequestMessage message) throws RemoteException {
try {
System.out.println(message.getUser()+"->"+message.getTargetUser()+" : "+message.getMessage());
IMessageListener eventListener = (IMessageListener)registry.lookup("listener-"+message.getTargetUser());
eventListener.onEvent(message);
return ResponseMessage.ok();
} catch (Exception e) {
e.printStackTrace();
return ResponseMessage.err(e.getMessage());
}
}
@Override
public String login(String name) throws RemoteException {
System.out.println("用户["+name+"]上线了");
return null;
}
}
客户端代码
public class Client {
public static void main(String[] args) {
try {
// 获取注册表(需指定服务端 IP)
Registry registry = LocateRegistry.getRegistry("localhost", 1099);
// 查找远程对象
UserService service = (UserService) registry.lookup("UserService");
Scanner scanner = new Scanner(System.in);
String line = "";
RequestMessage helloMessage = new RequestMessage();
helloMessage.setUser("");
helloMessage.setTargetUser("");
System.out.println("输入命令(login,target,message) l:张三 t:李四 m:hello 其他默认m:");
while (true) {
System.out.print(helloMessage.getUser() + "->" + helloMessage.getTargetUser() + ":");
line = scanner.nextLine();
if (line == null || "".equals(line.trim())) {
continue;
}
if (line.startsWith("l:")) {
helloMessage.setUser(line.substring(2));
// 注册自身 用用户名绑定自身的消息监听器
registry.rebind("listener-"+line.substring(2), new MessageListener(line.substring(2)));
// 登录成功
service.login(line.substring(2));
} else if (line.startsWith("t:")) {
helloMessage.setTargetUser(line.substring(2));
} else if (line.startsWith("m:")) {
helloMessage.setMessage(line.substring(2));
ResponseMessage response = service.say(helloMessage);
if (!response.isSuccess()) {
System.out.println("Response: " + response.getErrMsg());
}
} else {
helloMessage.setMessage(line);
ResponseMessage response = service.say(helloMessage);
if (!response.isSuccess()) {
System.out.println("Response: " + response.getErrMsg());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
启动服务度
启动两个客户端
命令简介
l:zhangsan //zhangsan登录
t:lisi // 选定目标lisi
m:msg // 发送消息,也可以省略m: