一.rmi
远程方法调用,是java特有的一种RPC实现。
二.特性
1.支持面向对象的多态性,优势之一
2.java独有,不支持其他语言
3.使用java原生序列化
4.BIO(异步阻塞IO)通信
由于使用原生序列化和异步阻塞io通信,导致该类型性能较差,不适合高并发场景。
三、实现
1.服务端。
HelloService接口,继承Remote
package com.rmiServer;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface HelloService extends Remote{
String sayHello(String someOne) throws RemoteException;
}
HelloServiceImpl为HelloService的实现类,需要继承UnicastRemoteObject。
package com.rmiServer.impl;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import com.rmiServer.HelloService;
public class HelloServiceImpl extends UnicastRemoteObject implements HelloService{
private static final long serialVersionUID = 6203776714625426526L;
public HelloServiceImpl() throws RemoteException {
super();
}
@Override
public String sayHello(String someOne) throws RemoteException {
return "Hello,"+someOne;
}
}
CustomSocketFactory,自定义端口通信,因为通信端口是随机产生的, 有可能被防火墙拦截。
package com.rmiServer;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.server.RMISocketFactory;
public class CustomSocketFactory extends RMISocketFactory{
@Override
public Socket createSocket(String host, int port) throws IOException {
return new Socket(host,port);
}
@Override
public ServerSocket createServerSocket(int port) throws IOException {
if(port==0){
port=8020;
}
System.out.println("rmi notify port " + port);
return new ServerSocket(port);
}
}
服务端启动类ServerMain
package com.rmiServer;
import java.io.IOException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.RMISocketFactory;
import com.rmiServer.impl.HelloServiceImpl;
public class ServerMain {
public static void main(String[] args) {
try {
//创建服务
HelloService helloService=new HelloServiceImpl();
//注册服务
LocateRegistry.createRegistry(8010);
//指定通信端口,防止被防火墙拦截
RMISocketFactory.setSocketFactory(new CustomSocketFactory());
Naming.bind("rmi://localhost:8010/helloService", helloService);
System.out.println("ServerMain Provide RPC service now");
} catch ( AlreadyBoundException | IOException e) {
e.printStackTrace();
}
}
}
2.客户端
HelloService接口,与服务器端对应
package com.rmiServer;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface HelloService extends Remote{
String sayHello(String someOne) throws RemoteException;
}
客户端启动类
package com.rmiClient;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
public class ClienMain {
public static void main(String[] args) {
try {
//服务引入
com.rmiServer.HelloService helloService=(com.rmiServer.HelloService) Naming.lookup("rmi://localhost:8010/helloService");
System.out.println(helloService.sayHello("is Client"));
} catch (MalformedURLException | RemoteException | NotBoundException e) {
e.printStackTrace();
}
}
}
3。先启动服务器端,再启动客户端。
结果
Hello,is Client