24.3 使用Hessian通过HTTP远程调用服务

Hessian提供一种基于HTTP的二进制远程协议。它由Caucho开发的,可以在 http://www.caucho.com 找到更多有关Hessian的信息。

24.3.1 为Hessian和co.配置DispatcherServlet

Hessian使用一个自定义Servlet通过HTTP进行通讯。使用Spring的DispatcherServlet原理,从Spring Web MVC使用中可以看出,可以很容易的配置这样一个Servlet来暴露你的服务。首先我们要在你的应用里创建一个新的Servlet(以下摘录自web.xml):

<servlet> 
    <servlet-name>remoting</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

<servlet-mapping> 
    <servlet-name>remoting</servlet-name> 
    <url-pattern>/remoting/*</url-pattern> 
</servlet-mapping> 

你可能对Spring的DispatcherServlet很熟悉,这样你将需要在’WEB-INF’目录中创建一个名为’remoting-servlet.xml’(在你的servlet名称后) 的Spring容器配置上下文。这个应用上下文将在下一节中里使用。

或者,可以考虑使用Spring中更简单的HttpRequestHandlerServlet。这允许你在根应用上下文(默认是’WEB-INF/applicationContext.xml’)中嵌入远程exporter定义。每个servlet定义指向特定的exporter bean。在这种情况下,每个servlet的名称需要和目标exporter bean的名称相匹配。

24.3.2 使用HessianServiceExporter暴露你的bean

在新创建的remoting-servlet.xml应用上下文里,我们将创建一个HessianServiceExporter来暴露你的服务:

<bean id="accountService" class="example.AccountServiceImpl"> 
    <!-- any additional properties, maybe a DAO? --> 
</bean> 

<bean name="/AccountService" class="org.springframework.remoting.caucho.HessianServiceExporter"> 
    <property name="service" ref="accountService"/> 
    <property name="serviceInterface" value="example.AccountService"/> 
</bean> 

现在我们准备好在客户端连接服务了。不必显示指定处理器的映射,所以使用BeanNameUrlHandlerMapping把URL请求映射到服务上:因此,服务将通过其包含的bean名称指定的URL导出 DispatcherServlet’s mapping (as defined above): ’http://HOST:8080/remoting/AccountService’ 或者, 在你的根应用上下文中创建一个HessianServiceExporter(比如在’WEB-INF/applicationContext.xml’中):

<bean name="accountExporter" class="org.springframework.remoting.caucho.HessianServiceExporter"> 
    <property name="service" ref="accountService"/> 
    <property name="serviceInterface" value="example.AccountService"/> 
</bean> 

在后一情况下, 在’web.xml’中为这个导出器定义一个相应的servlet,也能得到同样的结果:这个导出器映射到request路径/remoting/AccountService。注意这个servlet名称需要与目标导出器bean的名称相匹配。

<servlet> 
    <servlet-name>accountExporter</servlet-name> 
    <servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class> 
</servlet> 

<servlet-mapping> 
    <servlet-name>accountExporter</servlet-name> 
    <url-pattern>/remoting/AccountService</url-pattern> 
</servlet-mapping> 

24.3.3 在客户端上链接服务

使用HessianProxyFactoryBean,我们可以在客户端链接服务。与RMI示例一样也适用相同的原理。我们将创建一个单独的bean工厂或者应用上下文,并指明SimpleObject使用AccountService来管理accounts的以下bean:

<bean class="example.SimpleObject"> 
    <property name="accountService" ref="accountService"/> 
</bean> 

<bean id="accountService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean"> 
    <property name="serviceUrl" value="http://remotehost:8080/remoting/AccountService"/> 
    <property name="serviceInterface" value="example.AccountService"/> 
</bean> 

24.3.4 对通过Hessian暴露的服务使用HTTP基本认证

Hessian的优点之一是,我们可以轻松应用HTTP基本身份验证,因为这两种协议都是基于HTTP的。你的正常HTTP 服务器安全机制可以通过使用web.xml安全功能来应用。通常,你不会为每个用户都建立不同的安全证书,而是在Hessian/BurlapProxyFactoryBean级别共享安全证书(类似一个JDBCDataSource)。

<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> 
    <property name="interceptors" ref="authorizationInterceptor"/> 
</bean> 

<bean id="authorizationInterceptor" 
        class="org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor"> 
    <property name="authorizedRoles" value="administrator,operator"/> 
</bean> 

这个是我们显式使用了BeanNameUrlHandlerMapping的例子,并设置了一个拦截器,只允许管理员和操作员调用这个应用上下文中提及的bean。

Note: 当然,这个例子并不表现出灵活的安全架构。有关安全性方面的更多选项,请查看Spring Security项目http://projects.spring.io/spring-security/。