Spring远程支持的功能集成类使用不同的技术。远程支持使用Spring通用的POJOs实现减轻远程业务开发。当前,Spring支持以下的远程技术
- 远程方法调用(RMI)通过
RmiProxyFactoryBean
和RmiServiceExporter
,Spring支持传统的RMI(使用java.rmi.Remote
和java.rmi.RemoteException
)和借助RMI调用简易的远程(使用任何Java接口) - Spring的HTTP调用。Spring提供了一种特殊的远程策略(允许借助HTTP实现Java序列化),支持任何Java接口(就像RMI调用)。对应的支持类是
HttpInvokerProxyFactoryBean
和HttpInvokerServiceExporter
- Hessian 通过使用
HessianProxyFactoryBean
和HessianServiceExporter
,你可以使用轻量级二级制的基于HTTP协议暴露你的业务。 - Burlap Burlap是针对Hessian的基于XML的可选方案。Spring对此提供了支持类比如BurlapProxyFactoryBean 和BurlapServiceExporter
- JAX-WS Spring借助JAX-WS为web业务提供了远程支持
- JMS. 远程使用JMS,如同底层协议,借助JmsInvokerServiceExporter 和JmsInvokerProxyFactoryBean 类支持
- AMQP 远程使用AMQP,作为底层协议,由Spring AMQP项目支持
当讨论Spring的远程能力时,使用如下的领域模式和对应的业务:
public class Account implements Serializable{
private String name;
public String getName(){
return name;
}
public void setName(String name) {
this.name = name;
}
}
public interface AccountService {
public void insertAccount(Account account);
public List<Account> getAccounts(String name);
}
public interface RemoteAccountService extends Remote {
public void insertAccount(Account account) throws RemoteException;
public List<Account> getAccounts(String name) throws RemoteException;
}
// the implementation doing nothing at the moment
public class AccountServiceImpl implements AccountService {
public void insertAccount(Account acc) {
// do something...
}
public List<Account> getAccounts(String name) {
// do something...
}
}
我们将将业务暴露给一个远程客户,通过使用RMI并讨论一点使用RMI的缺陷。稍后我们将继续显示使用Hassian作为协议的例子。
21.2 使用RMI暴露业务
使用Spring的RMI支持类,你可以通过RMI底层暴露你的业务。这步设置好后,基本上有一个与远程EJBs相似的配置,除了那个没有安全上下文传播的标准支持或者远程事物传播。当使用RMI调用时,Spring为这样另外的调用提供了钩子,这样你可以配置安全框架或者通用的安全凭证。
21.2.1 使用RmiServiceExporter暴露业务
使用RmiServiceExporter,我们可以暴露AccountService对象的接口,作为RMI对象。这个接口可以通过RmiProxyFactoryBean或者在一个事物RMI业务的RMI访问这个接口。RmiServiceExporter借助RMI调用者支持任何非RMI业务的暴露。
当然了,首先得在Spring容器中设置我们的业务。
<bean id="accountService" class="example.AccountServiceImpl">
<!-- any additional properties, maybe a DAO? -->
</bean>
下一步,我们得使用RmiServiceExporter暴露我们的业务
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<!-- does not necessarily have to be the same name as the bean to be exported -->
<property name="serviceName" value="AccountService"/>
<property name="service" ref="accountService"/>
<property name="serviceInterface" value="example.AccountService"/>
<!-- defaults to 1099 -->
<property name="registryPort" value="1199"/>
</bean>
如你所见,我们重写了RMI注册器的端口号。通常,你的应用服务器也包含一个RMI注册器,并与另一个注册器对接是明智的。更多地,业务名用于绑定业务底层。所以现在,业务将绑定在'rmi://HOST:1199/AccountService'。我们将在稍后使用这个url关联客户端的业务。
注意:servicePort属性已经忽略了(默认为0)。这意味着每个匿名的端口将用于与service通信。
21.2.2 连接客户端的业务
我们的客户端是一个简单的对象使用AccountService管理账户。
public class SimpleObject {
private AccountService accountService;
public void setAccountService(AccountService accountService) {
this.accountService = accountService;
}
// additional methods using the accountService
}
为联系客户端的业务,将创建一个分离的Spring容器,包含了最简单的对象和业务,其与配置关联
<bean class="example.SimpleObject">
<property name="accountService" ref="accountService"/>
</bean>
<bean id="accountService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://HOST:1199/AccountService"/>
<property name="serviceInterface" value="example.AccountService"/>
</bean>
那就是我们需要做的在客户端支持远程账户业务。Spring将透明地创建一个调用者并远程地使得账户业务通过RmiServiceExporter可用。在客户端,我们将使用RmiProxyFactoryBean联系这个调用者。