15.3.1 使用 Hessian 和 Burlap 导出 bean 的功能
Last updated
Last updated
像之前一样,我们希望把 SpitterServiceImpl 类的功能发布为远程服务 —— 这次是一个 Hessian 服务。即使没有 Spring,编写一个 Hessian 服务 也是相当容易的。我们只需要编写一个继承 com.caucho.hessian.server.HessianServlet 的类,并确保所有的服务方法是 public 的(在 Hessian 里,所有 public 方法被视为服务方法)。
因为 Hessian 服务很容易实现,Spring 并没有做更多简化 Hessian 模型的工作。但是和 Spring 一起使用时,Hessian 服务可以在各方面利用 Spring 框架的优势,这是纯 Hessian 服务所不具备的。包括利用 Spring 的 AOP 来为 Hessian 服务提供系统级服务,例如声明式事务。
导出 Hessian 服务
在 Spring 中导出一个 Hessian 服务和在 Spring 中实现一个 RMI 服务惊人的相似。为了把 Spitter 服务 bean 发布为 RMI 服务,我们需要在 Spring 配置文件中配置一个 RmiServiceExporterbean。同样的方式,为了把 Spitter 服务发布为 Hessian 服务,我们需要配置另一个导出 bean,只不过这次是 HessianServiceExporter。
HessianServiceExporter 对 Hessian 服务所执行的功能与 RmiServiceExporter 对 RMI 服务所执行的功能是相同的:它把 POJO 的 public 方法发布成 Hessian 服务的方法。不过,正如图 15.6 所示,其实现过程与 RmiServiceExporter 将 POJO 发布为 RMI 服务是不同的。
HessianServiceExporter(稍后会有更详细的介绍)是一个 Spring MVC 控制器,它接收 Hessian 请求,并将这些请求转换成对被导出 POJO 的方法调用。在如下 Spring 的声明中,HessianServiceExporter 会把 spitterService bean 导出为 Hessian 服务:
正如 RmiServiceExporter 一样,service 属性的值被设置为实现了这个服务的 bean 引用。在这里,它引用的是 spitterServicebean。serviceInterface 属性用来标识这个服务实现了 SpitterService 接口。
与 RmiServiceExporter 不同的是,我们不需要设置 serviceName 属性。在 RMI 中,serviceName 属性用来在 RMI 注册表中注册一个服务。而 Hessian 没有注册表,因此也就没必要为 Hessian 服务进行命名。
配置 Hessian 控制器
RmiServiceExporter 和 HessianServiceExporter 另外一个主要区别就是,由于 Hessian 是基于 HTTP 的,所以 HessianSeriviceExporter 实现为一个 Spring MVC 控制器。这意味着为了使用导出的 Hessian 服务,我们需要执行两个额外的配置步 骤:
在 web.xml 中配置 Spring 的 DispatcherServlet,并把我们的应用部署为 Web 应用;
在 Spring 的配置文件中配置一个 URL 处理器,把 Hessian 服务的 URL 分发给对应的 Hessian 服务 bean。
我们在第 5 章学习了如何配置 Spring 的 DispatcherServlet 和 URL 处理器,所以这些步骤看起来有些熟悉。首先,我们需要一个 DispatcherServlet。还好,这个我们已经在 Spittr 应用的 web.xml 文件中配置了。但是为了处理 Hessian 服务,DispatcherServlet 还需要配置一个 Servlet 映射来拦截后缀为 “*.service” 的 URL:
如果你在 Java 中通过实现 WebApplicationInitializer 来配置 DispatcherServlet 的话,那么需要将 URL 模式作为映射添加到 ServletRegistration.Dynamic 中,在将 DispatcherServlet 添加到容器中的时候,我们能够得到 ServletRegistration.Dynamic 对象:
或者,如果你通过扩展 AbstractDispatcherServletInitializer 或 AbstractAnnotationConfigDispatcherServletInitializer 的方式来配置 DispatcherServlet,那么在重载 getServletMappings() 的时候,需要包含该映射:
这样配置后,任何以 “.service” 结束的 URL 请求都将由 DispatcherServlet 处理,它会把请求传递给匹配这个 URL 的控制器。因此 “/spitter.service” 的请求最终将被 hessianSpitterServicebean 所处理(它实际上仅仅是一个 SpitterServiceImpl 的代理)。
那我们是如何知道这个请求会转给 hessianSpitterSevice 处理呢?我们还需要配置一个 URL 映射来确保 DispatcherServlet 把请求转给 hessianSpitterService。如下的 SimpleUrlHandlerMappingbean 可以做到这一点:
如果不喜欢 Hessian 的二进制协议,我们还可以选择使用 Burlap 基于 XML 的协议。让我们看看如何把一个服务导出为 Burlap 服务。
导出 Burlap 服务
从任何方面上看,BurlapServiceExporter 与 HessianServiceExporter 实际上都是相同的,只不过它使用基于 XML 的协议而不是二进制协议。下面的 bean 定义展示了如何使用 BurlapServiceExporter 把 Spitter 服务导出为一个 Burlap 服务:
正如我们所看到的,这个 bean 与使用 Hessian 所对应 bean 的唯一区别在于 bean 的方法和导出类。配置 Burlap 服务和配置 Hessian 服务是一模一样的,这包括需要准备一个 URL 处理器和一个 DispatcherServlet。
现在让我们看看会话的另一端,如何访问我们使用 Hessian(或 Burlap)所发布的服务。