发表于: 2017-09-15 15:58:46

4 817


今天做的事:

今天开始任务8,首先了解SpringRMI是什么。

了解SpringRMI之前,我们需要先看一下Java的rmi,因为SpringRMI就是对java.rmi进行了一定的封装,接下来看一下


RMI 指的是远程方法调用 (Remote Method Invocation)。

它是一种机制,能够让在某个 Java虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。可以用此方法调用的任何对象必须实现该远程接口。


从JDK1.1开始就已经有rmi了

下面是百度原文

JDK1.1
什么是RMI
  远程方法调用是一种计算机之间对象互相调用对方函数,启动对方进程的一种机制,
  使用这种机制,某一台计算机上的对象在调用另外一台计算机上的方法时,使用的程
  序语法规则和在本地机上对象间的方法调用的语法规则一样。[1] 


接下来,我们只需要知道,SpringRMI是用来做远程调用的就可以了,具体里面的逻辑,实现方法等等都不需要我们考虑,只需要关注业务逻辑即可

这里推荐第一篇blog教程:http://blog.csdn.net/zhongweijian/article/details/8005124

这是官网上泽南贡献的,里面的代码我就不贴了,很占篇幅,就是照着copy即可

这里要注意,我们需要在客户端调用服务端的jar包。

然后看一下,首先要先开启服务端

看到服务端开启后并没有停下来,还在运行中

接下来我们要开启客户端,调用服务端的方法

看到打印结果,证明我们调用成功。


那如果服务端没启动,我们运行客户端会怎么样?

这里服务端需要我们手动停止

我们可以看到一堆莫名其妙的错误,关键句在我们圈起来的这部分,证明连接服务端失败了。


这时我们就可以看到SpringRMI的作用机理了,接下来讲解一下

首先贴一个链接,对于RMI有一个简单的解释,源码分析看不太懂,太花时间,就算了

http://www.cnblogs.com/youngjoy/p/4754958.html


这里有两个类需要明确一下

RmiProxyFactoryBean的主要功能是对RMI客户端封装,生成代理对象,查询得到RMI的stub对象,并通过这个stub对象发起相应的RMI远程调用请求。

RmiServiceExporter主要功能是将服务端远程对象提供的服务导出供客户端请求调用,同时将导出的远程对象和注册器绑定起来供客户端查询。


上述简单的例子中就使用了这两个类,所以有必要了解它们的用途


而服务端的main函数中用到了

BufferedReader

这个类时用来读取大量字节流的,这个main函数貌似是手动输入exit结束服务端进程,测试了一下,确实是这样



这个例子解析完成。


接下来我又写了一个java实现rmi的demo

链接在此:http://blog.csdn.net/zmx729618/article/details/52130722

不用写相关的Spring配置文件,这里是使用java中的一些类方法实现的

首先

public interface IHello extends Remote 

接口要继承

public class HelloImpl extends UnicastRemoteObject implements IHello 

实现类需要序列化,就是继承Serializable,这里继承UnicastRemoteObject,是变相继承序列化的接口


public class HelloServer {
public static void main(String[] args) {
try{
//创建一个远程对象
           IHello iHello = new HelloImpl();
           //生成远程对象注册表Registry的实例,并指定端口为8888(默认端口是1099)
           LocateRegistry.createRegistry(8888);
   
           //把远程对象注册到RMI注册服务器上,并命名为RHello
           //绑定的URL标准格式为:rmi://host:port/name(协议名可以省略,下面两种写法都可以)
           Naming.bind("rmi://127.0.0.1:8888/RHello", iHello);
           System.out.println(">>INFO:远程IHello对象绑定成功!");
       }catch (RemoteException e) {
System.out.println("创建远程对象发生异常!");
           e.printStackTrace();
       } catch (AlreadyBoundException e) {
System.out.println("发生重复绑定对象异常!");
           e.printStackTrace();
       } catch (MalformedURLException e) {
System.out.println("发生URL畸形异常!");
           e.printStackTrace();
       }
}
}

通过对应的类方法进行接口的注册,还有url的配置等等,这里需要抛一些异常

然后客户端

public class HelloClient {

public static void main(String[] args) {
try{
// 在RMI服务注册表中查找名称为RHello的对象,并调用其上的方法
           IHello iHello = (IHello) Naming.lookup("rmi://127.0.0.1:8888/RHello");
           System.out.println(iHello.sayHello("world"));
           System.out.println(iHello.sum(1,2));
       }catch (Exception e){
e.printStackTrace();
       }
}
}

直接用对应的类方法调用即可,最后可以成功输出


这里有个小坑,挺有趣的

我最开始将server端代码放在一个叫java.rmi的package中,然后运行的时候报错

/**
* 之前的java开头的package会报安全错误
* java.lang.SecurityException: Prohibited package name: java.rmi
* 禁止包名使用java开头
* 但是包名中带java是可以的,如rmi.java
*/

就是JVM在加载你的package时,会检测你的名字是否存在安全问题,这里涉及的问题有点深,我就看了个大概,结论就是,起包名的时候不要用java开头。


然后还有一个SpringRMI的问题

在配置文件中有这两项

<!--设置注册端口-->
<!--<property name="registryPort" value="9999"></property>-->
<!--设置服务端口-->
<!--<property name="servicePort" value="8888" />-->

一个是注册端口,一个是服务端口

看到有人是这么介绍的

一个registerPort即注册端口,用来暴露发现服务。一个servicePort即服务端口,用来传输数据。

然后目前还不太了解ServicePort是用来干嘛的,因为客户端使用的时候是直接和registryPort进行连接的;可能会在进行数据传输的时候使用servicePort?不太了解。


明天计划:推进任务8,将Service和web分离,为自己的项目配置SpringRMI


问题:springRMI的registryPort和servicePort的区别;这个还是有点不太理解,没有应用场景,求大佬解答


收获:SpringRMI和JavaRMI的简单使用。




返回列表 返回列表
评论

    分享到