Spring远程调用技术<1>-RMI
在java中,我们有多种可以使用的远程调用技术
1.远程方法调用(remote method invocation, RMI)
适用场景:不考虑网络限制时(例如防火墙),访问/发布基于java的服务
2.Caucho的Hession和Burlap
适用场景:考虑网络限制时,通过http访问/发布基于java的服务。Hession是二进制协议,Burlap是基于XML的
3.Spring基于HTTP的远程服务(HTTP invoke)
适用场景:考虑网络限制,并希望使用基于xml或专有的序列化机制实现java序列化时,访问/发布基于Spring的服务
4.使用JAX-RPC和JAX-WS的Web Server
适用场景:访问/发布平台独立的、基于SOAP的Web服务
5.还有EJB技术
参考http://www.cnblogs.com/wwzyy/p/5655600.html
这里远程方法的调用,方法的执行是在服务端执行的,客户端只是获取服务端处理完返回的结果。
一、首先开始配置服务端,建立java普通项目就行
先导入spring的jar包,这里使用的是spring4.1.1
1.配置远程调用的接口(MyServer.java)
package com.spring.rmiServer; public interface MyServer { public void getMsg(); public String getMsgById(Integer id); public Integer add(Integer a, Integer b); }
2.实现类(MyServerImpl.java)
package com.spring.rmiServer; public class MyServerImpl implements MyServer { @Override public void getMsg() { System.out.println("call getMsg.."); } @Override public String getMsgById(Integer id) { System.out.println("call getMsgById "+ id); return "id is "+id; } @Override public Integer add(Integer a, Integer b) { System.out.println("call add "); return a+b; } }
3.配置RMI服务(RMIConfig.java),使用java配置的方式
package com.spring.rmiServer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.remoting.rmi.RmiServiceExporter; @Configuration public class RMIConfig { //@Bean()的name默认是方法名 @Bean(name="rmiExporter") public RmiServiceExporter rmiExporter(MyServer myServer){ RmiServiceExporter rmiExporter = new RmiServiceExporter(); rmiExporter.setService(myServer); rmiExporter.setServiceName("My_server"); rmiExporter.setServiceInterface(MyServer.class); //rmiExporter.setRegistryHost("localhost"); rmiExporter.setRegistryPort(1199);//远程的端口 return rmiExporter; } @Bean(name="myServer") public MyServer myServer(){ return new MyServerImpl(); } }
4.启动服务
public static void main(String[] args) {
//当出现java.net.ConnectException: Connection refused: connect,可以这样解决,指定ip地址
System.setProperty("java.rmi.server.hostname" , "192.168.23.128" );
ApplicationContext ac = new AnnotationConfigApplicationContext(com.spring.rmiServer.RMIConfig.class);
System.out.println("start rmi server..");
}
二、配置客户端
1.配置要访问的远程接口,和服务端的那个接口一模一样,实现类不用写,因为服务端已经实现了,客户端调用就行
(MyServer.java)
package com.spring.rmiServer; public interface MyServer { public void getMsg(); public String getMsgById(Integer id); public Integer add(Integer a, Integer b); }
2.配置文件 (ClientContext.xml)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="org.springframework.remoting.rmi.RmiProxyFactoryBean"> <!-- 要调用的接口 --> <property name="serviceInterface" value="com.spring.rmiServer.MyServer"></property> <!-- url --> <property name="serviceUrl" value="rmi://192.168.23.128:1199/My_server"></property> </bean> </beans>
3.启动客户端(Client.java)
public static void main(String[] args) { ApplicationContext app = new ClassPathXmlApplicationContext("com/spring/rmiClient/ClientContext.xml"); MyServer myServer = app.getBean(MyServer.class); System.out.println(myServer.getMsgById(03)); }
注意:有时候会由于主机ip的原因出现拒绝访问异常
3种解决方法:
1. 服务器端添加代码: System.setProperty("java.rmi.server.hostname" , "192.168.23.128" );上面代码使用的就是这种方法。
2. 在 RMI 服务器上 root 身份登录,输入 Vi /etc/hosts ,在第一行添加 192.168.39.11 ieie
3. 若是用 spring, 则在 RmiServiceExporter 中添加属性 <property name="registryHost" value="192.168.23.128" />
缺点:
但是它存在某种限制,RMI很难穿越防火墙,这是RMI使用任意端口来交互(这是防火墙通常不允许的)。在企业内部网络幻境中,我们通常不需要担心。但如果在互联网运行,可能会有麻烦。
还有就是RMI是基于java的,也就是说客户端和服务端必须都是由java开发,这样接口才能对得上。因为RMI使用了java的序列化机制,所以通过网络传输的对象类型必须要保证在调用两端的java运行中是完全相同的版本