RMI服務(wù)接口
提供服務(wù)的RMI服務(wù)接口必須實(shí)現(xiàn)Remote接口
import java.rmi.Remote;
import java.rmi.RemoteException;
import com.google.protobuf.GeneratedMessageLite;
import com.yaowan.h5qipai.protobuf.message.code.Poker.RMIParam;
/**
* RMI服務(wù)
* @author
*
* @param <T>
*/
public interface RMIService extends Remote{
public Entity<? extends GeneratedMessageLite> dispatch(Entity<RMIParam> paramEntity )throws RemoteException;
}
RMI服務(wù)啟動(dòng)
RMI服務(wù)端口
RMI需要兩個(gè)端口:
- 服務(wù)開(kāi)啟端口
Registry registry = LocateRegistry.createRegistry(port);
port端口,用來(lái)開(kāi)啟RMI服務(wù),RMI終端連接需要制定連接此端口
String URL = "rmi://"+host+":"+port+"/rmiservice";
rmiService = (RMIService)Naming.lookup(URL);
- 服務(wù)交互端口
RMI終端在與RMI服務(wù)端建立連接后會(huì)需要利用此端口來(lái)進(jìn)行交互, 而此端口在RMI服務(wù)器啟動(dòng)后是隨機(jī)生成的,這樣在防火墻穿透時(shí)就不好處理, 因?yàn)殡S機(jī)防火墻都不知道對(duì)外開(kāi)放哪個(gè)端口了,故在生產(chǎn)環(huán)境下是需要制定此端口的,這樣我們就需要實(shí)現(xiàn)RMISocketFactory類,來(lái)指定此端口
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.server.RMISocketFactory;
import com.yaowan.framework.util.LogUtil;
public class RMILocalSocketFactory extends RMISocketFactory {
private int dataPort;
public RMILocalSocketFactory(int dataPort){
this.dataPort = dataPort;
}
@Override
public ServerSocket createServerSocket(int port) throws IOException {
if(port == 0){
port = dataPort;
LogUtil.info("RMIDataPort: "+port);
}
LogUtil.info("RMI createServerSocket: "+port);
return new ServerSocket(port);
}
@Override
public Socket createSocket(String host, int port) throws IOException {
String key = host+":"+port;
LogUtil.info("RMI createSocket: "+key);
return new Socket(host, port);
}
}
RMI服務(wù)啟動(dòng)
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.RMISocketFactory;
import java.rmi.server.UnicastRemoteObject;
import org.apache.commons.lang3.exception.ExceptionUtils;
import com.yaowan.framework.core.GlobalConfig;
import com.yaowan.framework.util.LogUtil;
/**
* RMI服務(wù)端啟動(dòng)器
* @author
*
*/
public class RMIServiceServer {
String host;
private int port;
private String URL;
//RMI服務(wù)抽象也必須靜態(tài)化
private static RMIService rmiService;
//RMI服務(wù)的實(shí)現(xiàn)類必須靜態(tài)化
private static RMIService rmiServiceImpl;
public RMIServiceServer(int port) {
this.port = port;
this.host = GlobalConfig.getString("IntranetIP");
URL = "rmi://"+host+":"+port+"/dispatche";
}
/**
* 用于啟動(dòng)RMI服務(wù)
*/
public void start() {
try {
// System.setProperty("java.rmi.server.hostname", host);
int dataPort = GlobalConfig.getInt("RMIDataPort");
if(dataPort == 0){//如果未設(shè)置,默認(rèn)用此端口
dataPort = 19998;
}
RMISocketFactory.setSocketFactory(new RMILocalSocketFactory(dataPort));
//RMI服務(wù)的實(shí)現(xiàn)類必須靜態(tài)化
rmiServiceImpl = new RMIServiceImpl();
//RMI服務(wù)抽象也必須靜態(tài)化
rmiService=(RMIService)UnicastRemoteObject.exportObject(rmiServiceImpl,0); //固定端口設(shè)置,配合在RMISocketFactory實(shí)現(xiàn)中做處理
System.setProperty("java.rmi.server.hostname",host);
LogUtil.info("Binding server implementation to registry");
Registry registry = LocateRegistry.createRegistry(port);
registry.rebind("dispatche", rmiService);
// Naming.rebind(URL, rmiService);
LogUtil.info("Waiting for invocations from clients ...");
LogUtil.info("URL: "+URL);
} catch (RemoteException e) {
LogUtil.error(ExceptionUtils.getStackFrames(e));
} catch (MalformedURLException e) {
LogUtil.error(ExceptionUtils.getStackFrames(e));
}catch(Exception e){
LogUtil.error(ExceptionUtils.getStackFrames(e));
}
}
}
需要注意點(diǎn):
- RMI服務(wù)抽象也必須靜態(tài)化
- RMI服務(wù)的實(shí)現(xiàn)類必須靜態(tài)化