使用远程服务
学习内容
访问和发布RMI服务
使用Hessian和Burlap服务
使用Spring的HTTP invoker
使用Spring开发Web服务
Spring远程调用概览
作为一个Java开发者,我们有多种可以使用的远程调用技术,包括:
远程方法调用(Remote Method Invocation RMI)
Caucho的Hessian和Burlap
Spring基于HTTP的远程服务
使用JAX-RPC和JAX-WS的Web Service
远程调用是客户端应用和服务器端之间的会话。在客户端,他所需要的一些功能并不在该应用的实现范围之内,所以应用要向能提供这些功能的其他系统寻求帮助。而远程应用通过远程服务暴露这些功能。
Spring通过多种远程调用技术支持RPC
RPC模型 | 适用场景 |
远程方法调用(RMI) | 不考虑网络限制时(例如防火墙),访问/发布基于Java的服务 |
Hessian或Burlap | 考虑网络限制时,通过HTTP访问/发布基于Java的服务。Hessian是二进制协议,而Burlap是基于XML的 |
HTTP invoker | 考虑网络限制,并希望使用基于XML或专有的序列化机制实现Java序列化时,访问/发布基于Spring的服务。 |
JAX-RPC和JAX-WS | 访问/发布平台独立的、基于SOAP的Web服务 |
在所有的模型中,服务都作为Spring所管理的bean配置到我们的应用中。这是通过一个代理工厂bean实现的,这个bean能够把远程服务像本地对象一样装配到其他bean的属性中去。
客户端向代理发起调用,就像代理提供了这些服务一样。代理代表客户端与远程服务进行通信,由他负责处理连接的细节并向远程服务发起调用。
更重要的是,如果调用远程服务时发生java.rmi.RemoteException异常,代理会处理此异常并重新抛出非检查型异常RemoteAccessException。
在服务器端,我们可以使用上表所列出的任意一种模型将Spring管理的Bean发布为远程服务。下图展示了远程导出器(remote exporter)如何将bean方法发布为远程服务。
无论我们开发的是使用远程服务的代码,还是实现这些服务的代码,或者两者兼而有之,在Spring中,使用远程服务纯粹是一个配置的问题。
使用RMI
1、导出RMI服务
传统的RMI配置
编写一个服务实现类,类中的方法必须抛出java.rmi.RemoteException异常;
创建一个继承于java.rmi.Remote的服务接口;
运行RMI编译器,创建客户端Stub类和服务器端skeleton类;
启动一个RMI注册表,以便持有这些服务;
在RMI注册表中注册服务。
在Spring中配置RMI服务
RmiServiceExporter可以把任意Spring管理的Bean发布为RMI服务。如下图所示,RmiServiceExporter把bean包装在一个适配器类中,然后适配器类被绑定到RMI注册表中,并且代理到服务类的请求--在本例中服务类也就是SpitterServiceImpl
使用RmiServiceExporter将SpitterServiceImpl发布为RMI服务的最简单方式是在Spring中使用如下的@Bean方法进行配置
@Bean
public RmiServiceExporter rmiExporter(SpitterService spitterService) {
RmiServiceExporter rmiExporter = new RmiServiceExporter();
rmiExporter.setService(spitterService);
rmiExporter.setServiceName("spitterService");
rmiExporter.setServiceInterface(SpitterService.class);
return rmiExporter;
}
这里会把SpitterService的Bean设置到Service属性中,表明RmiServiceExporter要把该Bean发布为一个RMI服务。ServiceName属性命名了RMI服务,serviceInterface属性指定了此服务所实现的接口。
@Bean
public RmiServiceExporter rmiExporter(SpitterService spitterService) {
RmiServiceExporter rmiExporter = new RmiServiceExporter();
rmiExporter.setService(spitterService);
rmiExporter.setServiceName("spitterService");
rmiExporter.setServiceInterface(SpitterService.class);
rmiExporter.setRegistryHost("rmi.spitter.com");
rmiExporter.setRegistryPort(1199);
return rmiExporter;
}
2、装配RMI服务
客户端配置Spring
Spring的RmiProxyFactoryBean是一个工厂bean,该bean可以为RMI服务创建代理。使用RmiPRoxyFactoryBean引用IHello的RMI服务是非常简单的,只需要在客户端的Spring配置中增加如下的@Bean方法:
@Bean
public RmiProxyFactoryBean rmiProxy() {
RmiProxyFactoryBean rmiProxy = new RmiProxyFactoryBean();
rmiProxy.setServiceUrl("rmi://localhost:1999/iHello");
rmiProxy.setServiceInterface(IHello.class);
return rmiProxy;
}
服务的URL是通过RmiProxyFactoryBean的serviceUrl属性来设置的,客户端和RMI代理的交互方式如下:
使用Hessian和Burlap发布远程服务
1、导出RMI服务
传统的RMI配置
编写一个服务实现类,类中的方法必须抛出java.rmi.RemoteException异常;
创建一个继承于java.rmi.Remote的服务接口;
运行RMI编译器,创建客户端Stub类和服务器端skeleton类;
启动一个RMI注册表,以便持有这些服务;
在RMI注册表中注册服务。