发表于: 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了
下面是百度原文
远程方法调用是一种计算机之间对象互相调用对方函数,启动对方进程的一种机制,
使用这种机制,某一台计算机上的对象在调用另外一台计算机上的方法时,使用的程
序语法规则和在本地机上对象间的方法调用的语法规则一样。[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的简单使用。
评论