美文网首页JAVA
RMI注意事项

RMI注意事项

作者: 大华夏 | 来源:发表于2017-08-18 11:58 被阅读134次

    RMI服务接口

    提供服务的RMI服务接口必须实现Remote接口

    import java.rmi.Remote;
    import java.rmi.RemoteException;
    
    import com.google.protobuf.GeneratedMessageLite;
    import com.yaowan.h5qipai.protobuf.message.code.Poker.RMIParam;
    
    
    /**
     * RMI服务
     * @author 
     *
     * @param <T>
     */
    public interface RMIService extends Remote{
    
        public Entity<? extends GeneratedMessageLite> dispatch(Entity<RMIParam> paramEntity )throws RemoteException;
    }
    

    RMI服务启动

    RMI服务端口

    RMI需要两个端口:

    • 服务开启端口
    Registry registry = LocateRegistry.createRegistry(port);
    

    port端口,用来开启RMI服务,RMI终端连接需要制定连接此端口

    String URL = "rmi://"+host+":"+port+"/rmiservice";
    rmiService = (RMIService)Naming.lookup(URL);
    
    • 服务交互端口
      RMI终端在与RMI服务端建立连接后会需要利用此端口来进行交互, 而此端口在RMI服务器启动后是随机生成的,这样在防火墙穿透时就不好处理, 因为随机防火墙都不知道对外开放哪个端口了,故在生产环境下是需要制定此端口的,这样我们就需要实现RMISocketFactory类,来指定此端口
    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服务启动

    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服务端启动器
     * @author 
     *
     */
    public class RMIServiceServer {
        
        String host;
        private int port;
        private String URL;
        //RMI服务抽象也必须静态化
        private static RMIService rmiService;
        //RMI服务的实现类必须静态化
        private static RMIService rmiServiceImpl;
        public RMIServiceServer(int port) {
            this.port = port;
            this.host = GlobalConfig.getString("IntranetIP");
            URL = "rmi://"+host+":"+port+"/dispatche";
        }
        /**
         * 用于启动RMI服务
         */
        public void start() {
            try {
    //          System.setProperty("java.rmi.server.hostname", host);
                
                int dataPort = GlobalConfig.getInt("RMIDataPort");
                if(dataPort == 0){//如果未设置,默认用此端口
                    dataPort = 19998;
                }
                
                RMISocketFactory.setSocketFactory(new RMILocalSocketFactory(dataPort));
                //RMI服务的实现类必须静态化
                rmiServiceImpl = new RMIServiceImpl();
                //RMI服务抽象也必须静态化
                rmiService=(RMIService)UnicastRemoteObject.exportObject(rmiServiceImpl,0); //固定端口设置,配合在RMISocketFactory实现中做处理
                
                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));
            }
        }
    }
    

    需要注意点:

    • RMI服务抽象也必须静态化
    • RMI服务的实现类必须静态化

    相关文章

      网友评论

        本文标题:RMI注意事项

        本文链接:https://www.haomeiwen.com/subject/hangrxtx.html