发表于: 2017-11-11 23:49:28
1 1009
今天完成的任务:
1.学习rmi的概念
RMI全称是Remote Method Invocation-远程方法调用。用在开发分布式网络应用中,是一种核心的解决方案。RMI可以部署在任何jre环境上运行,是分布式应用纯java的一种方案。但是由于JRMP(java remote method protocol)是针对java来使用的,所以不适合使用在非
java的环境。https://www.cnblogs.com/langtianya/p/4939077.htl
在Spring中,也对rmi进行了封装,可以让我们方便的使用rmi。Spring RMI中,主要有两个类:org.springframework.remoting.rmi.RmiServiceExporter和org.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怎么配置怎么使用。
首先是java的rmi的使用。
服务器端,一个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的流程是这样的。
这里面提到了stub和skeleton,这两个算是客户端和服务端沟通的代理。并且所有和网络相关的代码都写在了这两个代理中,这样我们就不需要自己去打理这些内容。
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
..
评论