发表于: 2018-01-29 22:20:17

1 831


今天完成的事情:(一定要写非常细致的内容,比如说学会了盒子模型,了解了Margin) 

使用原生java RMI完成同JVM下项目的分离.

原生有两种方式:

方式1,使用Naming类.

首先我们需要有一个服务接口,并且继承Remote接口,抛出相应的RemoteException.

package rmi.in;

import java.rmi.Remote;
import java.rmi.RemoteException;

/**
* @author Arike
* Create_at 2018/1/29 14:43
*/
public interface RmiTest extends Remote {
String getNum() throws RemoteException;
}

然后是服务实现类,需要继承RmiTest并且实现UnicastRemoteObject接口

package rmi.imp;

import rmi.in.RmiTest;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/**
* @author Arike
* Create_at 2018/1/29 14:45
*/
public class RmiTestImpl extends UnicastRemoteObject implements RmiTest {
private static final long serialVersionUID = 1L;
   
   public RmiTestImpl() throws RemoteException {
super();
   }

@Override
   public String getNum() throws RemoteException {
return String.valueOf(Math.random()*10);
   }
}

使用Naming类注册注册表需要自己手动启动rmiregistry工具开启端口,如果是maven项目需要进入到classes文件夹下启动命令行工具,查询列表需要看到本项目的字节码文件.然后执行 rmiregistry (默认是开启1099端口,如果需要修改,执行rmiregistry 端口号)

启动之后可以执行我们写好的服务端类

package rmi.run;

import rmi.imp.RmiTestImpl;
import rmi.in.RmiTest;

import java.rmi.Naming;

/**
* @author Arike
* Create_at 2018/1/29 14:59
*/
public class Start {
public static void main(String[] args) {
RmiTest rmi = null;
       try{
rmi = new RmiTestImpl();
           Naming.rebind("rmi",rmi);
           System.out.println("rmi server is ready");
       }catch(Exception e){
e.printStackTrace();
       }
}
}

执行之后

可以看到我们的服务属于一直运行状态.

然后去客户端,  客户端需要有一个相同全限定命名的接口,接口中的方法要与服务端相同, 用以调用服务端的远程实现.

客户端类:

package rmi.client;

import rmi.in.RmiTest;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

/**
* @author Arike
* Create_at 2018/1/29 15:35
*/
public class Start {
public static void main(String[] args) {
try {
RmiTest rmi = (RmiTest) Naming.lookup("rmi");
           System.out.println(rmi.getNum());
       } catch (NotBoundException | MalformedURLException | RemoteException e) {
e.printStackTrace();
       }
}
}

直接使用Naming.lookup获取到远程对象(实际是一个中介,并不是远程实现类本身),大致就是下面这么一个思路.

运行试一下.

可以看到已经成功调用服务端实现类的方法.


服务端实现2,使用Registry接口.使用Registry接口就可以不用再自己手动使用rmiregistry工具注册接口了,可以直接在代码中实现.

接口,实现类和Naming方式相同,只有服务实现有区别.

package rmi.run;

import rmi.imp.RmiTestImpl;
import rmi.in.RmiTest;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

/**
* @author Arike
* Create_at 2018/1/29 16:38
*/
public class Start2 {
public static void main(String[] args) {
RmiTest rmi = null;
       Registry registry =null;
       try{
rmi = new RmiTestImpl();
           registry = LocateRegistry.createRegistry(1099);
           registry.rebind("rmi",rmi);
           System.out.println("RMI服务已启动");
       }catch(Exception e){
e.printStackTrace();
       }
}
}

启动:

客户端的使用方法和Naming方法一样.


明天计划的事情:(一定要写非常细致的内容) 

将远程RMI跑通.
遇到的问题:(遇到什么困难,怎么解决的) 


然后关于跨机器,我做了很多demo,尝试了很多不同的方式生成服务端,只要跨IP分离,我尝试了网上的很多的列子都以失败告终.我明天打算好好看一下IBM给的介绍,非要把这个远程分离完成了.

但是通过一天的折腾,还是了解到了关于跨IP的问题出在哪里,有一篇博客中提到其实RMI跨IP实际上是因为跨到了不同的JVM,在不同的java虚拟机里面要访问同一个实现类,就需要将这个实现类的信息跨域发送到需要使用的客户端的JVM中,也就是我刚才那张图里的stub(存根,骨架), 我们在本地JVM其实并没有用到这个东西.

查询的资料都是以前老版本,1.3之前生成这个中间骨架的教程,是使用dos命令行生成,但是在jdk1.8上不好使,各种报错.


收获:(通过今天的学习,学到了什么知识)

java原生的东西其实才是我们运行一切的根本,好好深入了发现还是很有用.

今天在IBM官方给的一些文档中了解到了serializable的一些更深层次的东西.

https://www.ibm.com/developerworks/cn/java/j-lo-serial/

可以学习一下.



返回列表 返回列表
评论

    分享到