发表于: 2017-11-11 23:49:28

1 1010


今天完成的任务:

1.学习rmi的概念

RMI全称是Remote Method Invocation-远程方法调用。用在开发分布式网络应用中,是一种核心的解决方案。RMI可以部署在任何jre环境上运行,是分布式应用纯java的一种方案。但是由于JRMPjava remote method protocol是针对java来使用的,所以不适合使用在非

java的环境。https://www.cnblogs.com/langtianya/p/4939077.htl 

 

Spring中,也对rmi进行了封装,可以让我们方便的使用rmiSpring RMI中,主要有两个类:org.springframework.remoting.rmi.RmiServiceExporterorg.springframework.remoting.rmi.RmiProxyFactoryBean服务端使用RmiServiceExporter暴露RMI远程方法,客户端用RmiProxyFactoryBean间接调用远程方法。

 

spring支持的rmi很简单,不用服务接口继承Remot不用服务实现类继承UnicastRemoteObject,也不用我们自己注册rmi的远程服务实现类,服务器端 你需要做的仅仅是 写好你需要提供远程服务的实现类,然后将其交给RmiServiceExporter RmiServiceExporter会将实现类发布为RMI服务。

客户端 也很简单

只需要使用RmiProxyFactoryBean从服务器端的URL从获取服务对象  并进行封装给你定义的id  然后从spring容器中获取RmiProxyFactoryBean封装的id即可.此测试代码中 服务器和客户端都在一个项目中 也可换成多个项目 在不同的电脑中,只需要在服务器的RmiServiceExporter中加入 p:registryHost="ip地址" 即可 ,客户端将localhost换成ip地址即可.

参考:

https://www.cnblogs.com/langtianya/p/4939077.html

 

2.学习一下rmi怎么配置怎么使用。

首先是javarmi的使用。

服务器端,一个IHello接口。

public interface IHello extends Remote {
     String
sayHello(String name)throws RemoteException;
     int
sum(int a,int b)throws RemoteException;
}

一个实现。

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

public class
IHelloImpl extends UnicastRemoteObject implements IHello{
   
private static final long serialVersionUID = 1961558474342609777L;
    public
IHelloImpl() throws RemoteException {
   
super();
   
}
   
public String sayHello(String name){
        
return "hello"+name;
   
}
   
public int sum(int a,int b){
       
return a+b;
   
}
}

然后一个main函数。

import java.net.MalformedURLException;
import
java.rmi.AlreadyBoundException;
import
java.rmi.Naming;
import
java.rmi.RemoteException;
import
java.rmi.registry.LocateRegistry;

public class
HelloServer {
   
public static void main(String[] args) throws RemoteException {
       
try {
            IHello rHello =
new IHelloImpl();
           
LocateRegistry.createRegistry(8999);
           
Naming.bind("rmi://127.0.0.1:8999/Rhello", rHello);
            
System.out.println(">>INFO:远程绑定成功了");
       
}catch (RemoteException e){
            e.printStackTrace()
;
       
} catch (MalformedURLException e) {
            e.printStackTrace()
;
       
} catch (AlreadyBoundException e) {
            e.printStackTrace()
;
       
}
    }
}

客户端,测试一下能不能连接到。

public class HelloClient {
   
public static void main(String[] args) {
       
try{
            IHello rHello = (IHello) Naming.lookup(
"rmi://127.0.0.1:8999/Rhello");
           
System.out.println(rHello.sayHello("chen"));
           
System.out.println(rHello.sum(3,4));
       
}catch (Exception e){
            e.printStackTrace()
;
       
}
    }
}

另外在客户端还需要把服务端的接口拿过来。。

参考: http://blog.csdn.net/zmx729618/article/details/52130722

 

需要注意:首先,接口必须要继承Remote接口,然后所有的接口都必须抛出RemoteException异常。实现类里面必须要继承serializable接口并且也需要抛出异常。并且因为构造方法需要抛出异常,所以只能用显式的构造方法,不能使用默认的方法。

学习一下rmi的原理:

理解的还不是很深,能学多少是多少。

rmi 是用来实现java分布式应用的技术。因为随着系统功能的增加或者业务量,被请求的次数的提升,我们使用单机的环境肯定不能满足需求,所以就出现了分布式。

rmi的流程是这样的。

这里面提到了stubskeleton,这两个算是客户端和服务端沟通的代理。并且所有和网络相关的代码都写在了这两个代理中,这样我们就不需要自己去打理这些内容。

stub是客户端的一个代理,作用是为客户端编码远程命令并把他们发送到服务器。服务端返回的数据stub再解码返回调用结果给客户端。

Skeleton是服务端的代理,作用是是把远程命令解码,调用服务端的远程对象的方法,把结果在编 码发给stub

那么还有一个问题,客户端是怎么找到服务端的端口,然后去调用的?客户端使用的是stub代理,stub知道服务端在哪。可是stub又是怎么知道服务端的端口呢??

上面的问题就引出了RMIRegistry,这个东西是用来提供一个服务,创建一个注册表,然后提供一个名字,并且使用naming.bind 来绑定IP地址,如下:

LocateRegistry.createRegistry(8999);
Naming.bind("rmi://127.0.0.1:8999/Rhello", rHello);

然后在客户端就可以使用Naming.lookup来调用,这样就联系起来了。

Naming.lookup("rmi://127.0.0.1:8999/Rhello");

参考

http://blog.csdn.net/sinat_34596644/article/details/52599688

http://blog.csdn.net/qb2049_xg/article/details/3278672#p3

http://www.jianshu.com/p/2c78554a3f36

 

3.SpringRMI学习。

服务端

还是需要一个接口和一个实现类,并且需要有一个配置文件。

接口

public interface HelloRMI {
   
int getAdd(int a,int b);
}

实现

public class HelloRMIImpl implements HelloRMI{
   
public int getAdd(int a,int b){
       
return a+b;
   
}
}

配置

<bean class="comNaNteng.springRMI.HelloRMIImpl" id="helloRMIImpl"/>
   
<bean
id="MyRmiServer" class="org.springframework.remoting.rmi.RmiServiceExporter">
    <property
name="service" ref="helloRMIImpl"/>
    <property
name="serviceName" value="helloRMI"/>
    <property
name="serviceInterface" value="comNaNteng.springRMI.HelloRMI"/>
    <property
name="registryPort" value="9999"/>
</bean>

测试(就当做是发布在web容器上面):

public class RMITest {
   
public static void main(String[] args) {
       
new ClassPathXmlApplicationContext("springRMI.xml");
       
System.out.println("ok");
    
}
}

 

客户端

接口

public interface HelloRMI {
   
int getAdd(int a, int b);
}

配置

<bean class="org.springframework.remoting.rmi.RmiProxyFactoryBean" id="myRMIClient">
    <property
name="serviceInterface" value="comNaNteng.springRMI.HelloRMI"/>
    <property
name="serviceUrl" value="rmi://127.0.0.1:9999/helloRMI"/>
</bean>

测试:

public class RMIClient {
   
public static void main(String[] args) {
        ApplicationContext ac=
new ClassPathXmlApplicationContext("rmiClient.xml");
       
HelloRMI helloRMI= (HelloRMI) ac.getBean("myRMIClient");
       
System.out.println("连接到了");
       
System.out.println(helloRMI.getAdd(3,4));
   
}
}

大概就是这些,使用SpringRMI来实现比不使用简单了一些。主要还是实现了解耦的思想。

需要的端口和ip的配置都写在了配置文件里面。

另外接口也不需要去继承Remote直接用普通接口就行。

实现类里面也不需要去处理异常也不用继承序列化。


 

 

 

明天计划:

rmi是现在自己的项目里面。

看看能不能做完任务。

遇到问题:

1。一个简单的rmi项目报错。发现是客户端和服务端的包路径不同。。。

2.开始的时候报错,是因为服务端注册的端口和绑定的端口写的不一样。。。还是理解不够。

收获:

学习了RMI的基础知识

禅道:

任务八第一天。

http://taskNaNteng.com/zentao/task-view-10342.html

..


返回列表 返回列表
评论

    分享到