【Spring】几种RPC模型的使用与比较——RMI
上回写到<基于JMS的RPC>时使用到了:
·org.springframework.jms.remoting.JmsInvokerServiceExporter
·org.springframework.jms.remoting.JmsInvokerProxyFactoryBean
spring在实现RPC的几种方式上都提供了风格一致的支持。
在这里我打算把几种RPC模型记录下来并作比较。
·RMI
·Hessian/Burlap
·HTTP Invoker
·JAX-WS
先从最基本的RMI开始。
RMI相关的API早在JDK1.1时就有了,我在这里简单描述一下RMI的原生实现(代码可以从别的地方参考)。
·声明一个远程接口,接口必须继承java.rmi.Remote,方法需要抛出java.rmi.RemoteException。
·为远程接口提供实现,实现类需要继承UnicastRemoteObject。
·或者可以使用rmi相关命令创建skelton和stub。
·启动一个RMI注册表并注册。
如果是spring实现RMI,方法会简单很多。
我们只需要用到两个类:
·org.springframework.remoting.rmi.RmiServiceExporter
·org.springframework.remoting.rmi.RmiProxyFactoryBean
我简单定义一下接口和实现类:
package pac.testcase.ws; public interface MyService { public boolean inviteMeIn(); public String welcome(); }
package pac.testcase.ws.impl; import pac.testcase.ws.MyService; public class MyServiceImpl implements MyService{ public boolean inviteMeIn() { return true; } public String welcome() { return "Everybody is welcome!!"; } }
简简单单,不需要继承其他任何东西,非常pojo。
下面是spring相关配置:
<bean id="myService" class="pac.testcase.ws.impl.MyServiceImpl" /> <bean class="org.springframework.remoting.rmi.RmiServiceExporter" p:service-ref="myService" p:serviceName="welcomeService" p:serviceInterface="pac.testcase.ws.MyService" />
将我们的pojo导出为RMI服务,在这里我采用默认配置。
地址在默认情况时如下:
/** * Set the host of the registry for the exported RMI service, * i.e. {@code rmi://HOST:port/name} * <p>Default is localhost. */ public void setRegistryHost(String registryHost) { this.registryHost = registryHost; } /** * Set the port of the registry for the exported RMI service, * i.e. {@code rmi://host:PORT/name} * <p>Default is {@code Registry.REGISTRY_PORT} (1099). * @see java.rmi.registry.Registry#REGISTRY_PORT */ public void setRegistryPort(int registryPort) { this.registryPort = registryPort; }
客户端方面使用RmiProxyFactoryBean,被代理的服务就像一个简单的bean一样:
<bean id="clientSideService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean" p:serviceUrl="rmi://localhost:1099/welcomeService" p:serviceInterface="pac.test.RemoteService" />
配置中的pac.test.RemoteService就是那个简单的bean,根据客户端的需要,在这里重新定义一下。
package pac.test; public interface RemoteService { public String welcome(); }
这样就可以在服务端调用了,不用做什么Naming.lookup(serviceUrl)之类的操作,一切都想调用本地那样。
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); RemoteService service = (RemoteService)context.getBean("clientSideService"); System.out.println(service.welcome());
RMI虽然简单高效,但使用RMI会存在一个问题(其实还有别的问题,比如防火墙什么的)——RMI使用的是Java的序列化机制,序列化你懂的,他有版本问题。
于是在下一篇我打算试试Hessian/Burlap。
本文出自 “Map.get(X)=new Object()” 博客,请务必保留此出处http://runtime.blog.51cto.com/7711135/1405562