美文网首页
Java RMI服务搭建

Java RMI服务搭建

作者: ffewi | 来源:发表于2018-04-30 20:24 被阅读0次

    什么是RMI?

    RMI:远程方法调用(Remote Method Invocation)。

    如何建立RMI服务?

    建立服务端
    Eclips新建Java Project,自定义名称,例如笔者项目名称:rmi-server。

    第1步. 首先建立两个基本的请求对象与响应对象,分别为:BaseIn.javaBaseOut.java

    BaseIn.java

    package api;
    
    import java.io.Serializable;
    
    /**
     * 
     * 基本入参对象基类
     *
     */
    public class BaseIn implements Serializable {
        private static final long serialVersionUID = 1L;
        // 入参对象
        private Object params;
        // 调用类型
        private String invokeType;
    
        public BaseIn() {
    
        }
    
        public BaseIn(Object params, String invokeType) {
            super();
            this.params = params;
            this.invokeType = invokeType;
        }
    
        public Object getParams() {
            return params;
        }
    
        public void setParams(Object params) {
            this.params = params;
        }
    
        public String getInvokeType() {
            return invokeType;
        }
    
        public void setInvokeType(String invokeType) {
            this.invokeType = invokeType;
        }
    
    }
    
    

    BaseOut.java

    package api;
    
    import java.io.Serializable;
    
    /**
     * 
     * 基本返回对象基类
     *
     */
    public class BaseOut implements Serializable {
        private static final long serialVersionUID = 1L;
        // 调用类型
        private String invokeType;
        // 交易状态
        private boolean status;
        // 业务消息
        private String msg;
    
        public BaseOut() {
    
        }
    
        public BaseOut(String invokeType, boolean status, String msg) {
            super();
            this.invokeType = invokeType;
            this.status = status;
            this.msg = msg;
        }
    
        public String getInvokeType() {
            return invokeType;
        }
    
        public void setInvokeType(String invokeType) {
            this.invokeType = invokeType;
        }
    
        public boolean isStatus() {
            return status;
        }
    
        public void setStatus(boolean status) {
            this.status = status;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
    }
    
    

    第2步. 然后定义一个Rmi请求的数据解析器接口与实现,分别为:IRmiApi.javaRmiApiImpl.java

    IRmiApi.java 继承 java.rmi.Remote

    package api;
    
    import java.rmi.Remote;
    import java.rmi.RemoteException;
    
    /**
     * 
     * RMI服务功能接口定义
     *
     */
    public interface IRmiApi extends Remote {
    
        /**
         * 方法处理响应器
         * 
         * @param baseIn
         * @return
         * @throws RemoteException
         */
        <T extends BaseOut> T handler(BaseIn baseIn) throws RemoteException;
    
    }
    
    

    RmiApiImpl.java 继承 java.rmi.server.UnicastRemoteObject 并且要有构造方法

    package api;
    
    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject;
    
    public class RmiApiImpl extends UnicastRemoteObject implements IRmiApi {
    
        private static final long serialVersionUID = -1L;
    
        protected RmiApiImpl() throws RemoteException {
            super();
        }
    
        @SuppressWarnings("unchecked")
        @Override
        public <T extends BaseOut> T handler(BaseIn baseIn) throws RemoteException {
    
            // 定义响应对象
            T response = null;
            // 处理NullPoint
            if (baseIn == null) {
                return response;
            }
            System.out.println("接收到请求:" + baseIn.getInvokeType());
            // 具体处理流程
            if ("EXIT".equals(baseIn.getInvokeType())) {
                System.out.println("接收到服务退出指令...");
                System.out.println("服务停止成功!!!");
                System.exit(0);
            } else if ("getMyInfo".equals(baseIn.getInvokeType())) {
                response = (T) new BaseOut(baseIn.getInvokeType(), true,
                        "获取我的消息-交易成功");
            } else {
                System.out.println("未知请求【" + baseIn.getInvokeType() + "】");
            }
    
            System.out.println("请求【" + baseIn.getInvokeType() + "】结束!");
            return response;
        }
    
    }
    
    
    

    第3步. 以上即完成了整体结构的实现,现在编写RMI服务启动入口(StartRmi.java)。

    StartRmi.java 启动服务入口

    package api;
    
    import java.net.MalformedURLException;
    import java.rmi.AlreadyBoundException;
    import java.rmi.Naming;
    import java.rmi.RemoteException;
    import java.rmi.registry.LocateRegistry;
    
    public class StartRmi {
    
        public static void main(String[] args) {
    
            try {
                System.out.println("RMI服务启动中...");
                // 实例化服务解析类
                IRmiApi api = new RmiApiImpl();
                // 注册端口
                LocateRegistry.createRegistry(9090);
                // 服务地址: rmi://ip:port/serverName
                String url = "rmi://127.0.0.1:9090/rmi";
                // 绑定服务解析器
                Naming.bind(url, api);
                System.out.println("启动完毕:" + url);
            } catch (RemoteException e) {
                e.printStackTrace();
            } catch (MalformedURLException | AlreadyBoundException e) {
                e.printStackTrace();
            }
    
        }
    }
    
    

    现在即可启动查看效果:

    控制台输出:

    RMI服务启动中...
    启动完毕:rmi://127.0.0.1:9090/rmi
    

    第4步. 启动完毕,已经完成大部分实现。但是怎么停止呢?编写停止功能(StopRmi.java

    StopRmi.java

    package api;
    
    import java.net.MalformedURLException;
    import java.rmi.Naming;
    import java.rmi.NotBoundException;
    import java.rmi.RemoteException;
    import java.rmi.UnmarshalException;
    
    public class StopRmi {
    
        public static void main(String[] args) {
            String url = "rmi://127.0.0.1:9090/rmi";
            IRmiApi api;
            try {
                api = (IRmiApi) Naming.lookup(url);
                api.handler(new BaseIn(null, "EXIT"));
            } catch (UnmarshalException e) {
                String errMsg = e.getMessage();
                if (errMsg != null && errMsg.indexOf("Connection reset") != -1) {
                    System.out.println("停止RMI服务成功!!!");
                } else {
                    e.printStackTrace();
                }
    
            } catch (MalformedURLException | RemoteException | NotBoundException e) {
                e.printStackTrace();
            }
    
        }
    
    }
    
    

    运行测试:

    控制台输出:

    [Console StopRmi ]:
        停止RMI服务成功!!!
    
    [Console StartRmi]:
        RMI服务启动中...
        启动完毕:rmi://127.0.0.1:9090/rmi
        接收到请求:EXIT
        接收到服务退出指令...
        服务停止成功!!!
    

    到此,整个RMI服务端测试完毕!

    如何建立客户

    建立客户端

    Eclips新建Java Project,自定义名称,例如笔者项目名称:rmi-client。

    第1步. 复制server端 BaseIn.javaBaseOut.java,并且保证包路径一致!!!

    - rmi-client
        - src
            - api
                * BaseIn.java
                * BaseOut.java
    

    第2步. 复制server端IRmiApi.java,并且保证包路径一致!!!

    - rmi-client
        - src
            - api
                * BaseIn.java
                * BaseOut.java
                * IRmiApi.java
    

    第3步. 建立请求发送器。

    ApiClient.java

    package app;
    
    import java.rmi.Naming;
    
    import api.BaseIn;
    import api.BaseOut;
    import api.IRmiApi;
    
    public class ApiClient {
    
        private static final String DEFAUTL_SERVER_URL = "rmi://127.0.0.1:9090/rmi";
    
        private static IRmiApi server = null;
    
        private ApiClient() {
    
        }
    
        private static void connet() throws Exception {
            if (server == null) {
                server = (IRmiApi) Naming.lookup(DEFAUTL_SERVER_URL);
            }
    
        }
    
        /**
         * 请求器
         * 
         * @param baseIn
         * @return
         */
        public static <T extends BaseOut> T sendRequest(BaseIn baseIn) {
            try {
                connet();
                return server.handler(baseIn);
            } catch (Exception e) {
                String errMsg = e.getMessage();
                if (errMsg != null && errMsg.indexOf("Connection reset") != -1) {
                    System.out.println("停止RMI服务成功!!!");
                } else {
                    e.printStackTrace();
                }
            }
            return null;
        }
    
    }
    
    

    测试Test.java

    package app;
    
    import api.BaseIn;
    import api.BaseOut;
    
    public class Test {
    
        public static void main(String[] args) {
            // 调用业务服务
            BaseOut result = ApiClient.sendRequest(new BaseIn(null, "getMyInfo"));
            System.out.println(result);
            // 停止服务
            BaseOut off = ApiClient.sendRequest(new BaseIn(null, "EXIT"));
            System.out.println(off);
        }
    }
    
    

    重写BaseOut.java toString 方便打印:

    @Override
        public String toString() {
            return "BaseOut [invokeType=" + invokeType + ", status=" + status
                    + ", msg=" + msg + "]";
        }
        
    

    控制台输出

    [Console rmi-client ]:
        BaseOut [invokeType=getMyInfo, status=true, msg=获取我的消息-交易成功]
        停止RMI服务成功!!!
        null
    
    [Console rmi-server]:
        RMI服务启动中...
        启动完毕:rmi://127.0.0.1:9090/rmi
        接收到请求:getMyInfo
        请求【getMyInfo】结束!
        接收到请求:EXIT
        接收到服务退出指令...
        服务停止成功!!!
    

    至此,RMI服务搭建完成!!!

    拓展练习

    运行jar包调用服务:
    服务端:rmi-server.jar
    获取地址:http://ovt5bckd8.bkt.clouddn.com/rmi-server.jar
    客户端:rmi-client.jar
    获取地址:http://ovt5bckd8.bkt.clouddn.com/rmi-client.jar

    运行示例:

    [rmi-server.jar]
    D:\>java -jar rmi-server.jar
    RMI服务启动中...
    启动完毕:rmi://127.0.0.1:9090/rmi
    接收到请求:getMyInfo
    请求【getMyInfo】结束!
    接收到请求:EXIT
    接收到服务退出指令...
    服务停止成功!!!
    
    D:\>
    
    [rmi-client.jar]
    D:\>java -jar rmi-client.jar
    BaseOut [invokeType=getMyInfo, status=true, msg=获取我的消息-交易成功]
    停止RMI服务成功!!!
    null
    
    D:\>
    

    相关文章

      网友评论

          本文标题:Java RMI服务搭建

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