15.3.2 访问 Hessian/Burlap 服务

回顾一下在 15.2.2 小节中,在使用 RmiProxyFactoryBean 访问 Spitter 服务的客户端代码中,完全不知道这个服务是一个 RMI 服务。事实上,也根本没有任何迹象表明这个服务是一个远程服务。它只是与 SpitterService 接口打交道 —— RMI 的所有细节完全包含在 Spring 配置中这个 bean 的配置中。好处是客户端不需要了解服务的实现,因此从 RMI 客户端转到 Hessian 客户端会变得极其简单,不需要改变任何客户端的 Java 代码。

坏处是,如果你真的喜欢编写 Java 代码的话,那么这一节或许让你大失所望。这是因为在客户端代码中,基于 RMI 的服务与基于Hessian 的服务之间唯一的差别在于要使用 Spring 的 HessianProxyFactoryBean 来代替 RmiProxyFactoryBean。客户端调用基于 Hessian 的 Spitter 服务可以用如下的配置声明:

@Bean
public HessianProxyFactoryBean spitterService() {
  HessianProxyFactoryBean proxy = new HessianProxyFactoryBean();
  proxy.setServiceUrl("http://localhost:8080/Spitter/spitter.service");
  proxy.setServiceInterface(SpitterService.class);
  return proxy;
}

就像基于 RMI 服务那样,serviceInterface 属性指定了这个服务实现的接口。并且,像 RmiProxyFactoryBean 一样,serviceUrl 标识了这个服务的 URL。既然 Hessian 是基于 HTTP 的,当然我们在这里要设置一个 HTTP URL(URL 是由我们先前定义的 URL 映射所决定的)。图 15.7 展示了客户端以及由 HessianProxyFactoryBean 所生成的代理之间是如何交互的。

事实证明,把 Burlap 服务装配进客户端同样也没有太多新意。二者唯一的区别在于,我们要使用 BurlapProxyFactoryBean 来代替 HessianProxyFactoryBean:

@Bean
public BurlapProxyFactoryBean spitterService() {
  BurlapProxyFactoryBean proxy = new BurlapProxyFactoryBean();
  proxy.setServiceUrl("http://localhost:8080/Spitter/spitter.service");
  proxy.setServiceInterface(SpitterService.class);
  return proxy;
}

尽管我们觉得在 RMI、Hessian 和 Burlap 服务之间稍微不同的配置是很无趣的,但是这样的单调恰恰是有好处的。它意味着我们可以很容易在各种 Spring 所支持的远程调用技术之间进行切换,而不需要重新学习一个全新的模型。一旦我们配置了对 RMI 服务的引用,把它重新配置为 Hessian 或 Burlap 服务也是很轻松的工作。

因为 Hessian 和 Burlap 都是基于 HTTP 的,它们都解决了 RMI 所头疼的防火墙渗透问题。但是当传递过来的 RPC 消息中包含序列化对象时,RMI 就完胜 Hessian 和 Burlap 了。因为 Hessian 和 Burlap 都采用了私有的序列化机制,而 RMI 使用的是 Java 本身的序列化机制。如果我们的数据模型非常复杂,Hessian/Burlap 的序列化模型就可能无法胜任了。

我们还有一个两全其美的解决方案。让我们看一下 Spring 的 HTTP invoker,它基于 HTTP 提供了 RPC(像 Hessian/Burlap 一样),同时又使用了 Java 的对象序列化机制(像 RMI 一样)。

Last updated