`
234390216
  • 浏览: 10193858 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
博客专栏
A5ee55b9-a463-3d09-9c78-0c0cf33198cd
Oracle基础
浏览量:460812
Ad26f909-6440-35a9-b4e9-9aea825bd38e
springMVC介绍
浏览量:1771850
Ce363057-ae4d-3ee1-bb46-e7b51a722a4b
Mybatis简介
浏览量:1395469
Bdeb91ad-cf8a-3fe9-942a-3710073b4000
Spring整合JMS
浏览量:393909
5cbbde67-7cd5-313c-95c2-4185389601e7
Ehcache简介
浏览量:678239
Cc1c0708-ccc2-3d20-ba47-d40e04440682
Cas简介
浏览量:529311
51592fc3-854c-34f4-9eff-cb82d993ab3a
Spring Securi...
浏览量:1178754
23e1c30e-ef8c-3702-aa3c-e83277ffca91
Spring基础知识
浏览量:461973
4af1c81c-eb9d-365f-b759-07685a32156e
Spring Aop介绍
浏览量:150157
2f926891-9e7a-3ce2-a074-3acb2aaf2584
JAXB简介
浏览量:66872
社区版块
存档分类
最新评论

Spring整合Hessian访问远程服务

阅读更多

Spring整合Hessian访问远程服务

目录

1.1      Hessian简介

1.2      整合

1.2.1     概述

1.2.2     服务端整合

1.2.3     客户端整合

1.1     Hessian简介

       Hessian是一个轻量级的Web服务实现工具,它采用的是二进制协议,因此很适合发送二进制数据。它的一个基本原理就是把远程服务对象以二进制的方式进行发送和接收。

1.2     整合

1.2.1 概述

对于Hessian而言,有服务端和客户端,所以我们的整合也需要分服务端的整合和客户端的整合。服务端的整合是通过SpringMVC进行的,而客户端的整合则是通过Springbean进行的。

1.2.2 服务端整合

基于客户端要调用服务端的远程服务,所以我们先来谈一下服务端的整合。Hessian的远程服务是基于接口的,所以我们要作为远程服务的实现类必须要实现一个接口。作为示例,这里我们建立一个叫hessianServerweb项目作为远程服务的服务端,在这个项目中我们建立一个叫做UserService的接口:

package com.tiantian.hessianserver.service;
 
public interface UserService {
 
       public void addUser();
      
       public void updateUser();
      
       public void delUser();
      
       public String findUser(String username);
      
}

 

       然后建立一个它的实现类UserServiceImpl

package com.tiantian.hessianserver.service.impl;
 
import com.tiantian.hessianserver.service.UserService;
 
public class UserServiceImpl implements UserService {
 
       public void addUser() {
              System.out.println("-------------invoke addUser()---------------");
       }
 
       public void updateUser() {
              System.out.println("-------------invoke updateUser()---------------");
       }
 
       public void delUser() {
              System.out.println("-------------invoke delUser()---------------");
       }
      
       public String findUser(String username) {
              System.out.println("-------------invoke findUser---------------");
              return "return: " + username;
       }
 
}

 

       那么接下来我们要做的就是把UserServiceImpl作为一个远程服务进行发布,以致客户端能够进行访问。

       首先我们需要在web.xml中配置一个SpringMVCDispatcherServlet用于接收所有的Web服务请求,这里我们这样配置:

       <servlet>
              <servlet-name>hessianServer</servlet-name>
              <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
              <load-on-startup>1</load-on-startup>
       </servlet>
      
       <servlet-mapping>
              <servlet-name>hessianServer</servlet-name>
              <url-pattern>/api/service/*</url-pattern>
       </servlet-mapping>

 

       可以看到我们这个DispatcherServlet会处理url为“/api/service/*”的请求,通配符“*”就对应着我们的处理器映射。

       接下来就是在SpringMVC的配置文件中利用Hessian来定义我们的远程服务了,这是通过Spring提供的HessianServiceExporter来实现的。我们需要在SpringMVC的配置文件中定义一个类型为HessianServiceExporterbean对象。该bean对象需要接收两个属性,一个是service属性,用于关联真正的service对象,另一个是serviceInterface属性,用于指定当前的服务对应的接口。HessianServiceExporter实现了HttpRequestHandler接口,当我们请求某一个远程服务的时候实际上请求的就是其对应的HessianServiceExporter对象,HessianServiceExporter会把请求的服务以二进制的方式返回给客户端。这里我们在SpringMVC的配置文件中这样定义:

       <bean id="userService" class="com.tiantian.hessianserver.service.impl.UserServiceImpl" />
       <bean name="/userService"
              class="org.springframework.remoting.caucho.HessianServiceExporter">
              <property name="service" ref="userService" />
              <property name="serviceInterface" value="com.tiantian.hessianserver.service.UserService" />
       </bean>

 

       注意看我们的HessianServiceExporter对应的beanname是“/userService”,在SpringMVC的配置文件中,当一个beanname是以“/”开始的时候Spring会自动对它进行BeanNameUrlHandlerMapping。所以这里相当于是我们把“/userService”映射到了HessianServiceExporter,根据上面的配置我们要请求这个远程服务的时候应该请求“/api/service/userService”。虽然说在Spring的配置文件中我们把bean的名称设为以“/”开始时Spring会自动对它进行一个beanName映射,但有一次不知道是哪里影响了,我这样使用的时候Spring没有对它进行自动映射,所以为了保险起见,这里我们最好自己指定一个BeanNameUrlHandlerMapping,代码如下所示:

       <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
       <bean id="userService" class="com.tiantian.hessianserver.service.impl.UserServiceImpl" />
       <bean name="/userService"
              class="org.springframework.remoting.caucho.HessianServiceExporter">
              <property name="service" ref="userService" />
              <property name="serviceInterface" value="com.tiantian.hessianserver.service.UserService" />
       </bean>

 

       注意,因为是根据beanName来进行映射的,所以我们必须要给HessianServiceExporter bean对象指定name属性,而且其对应的name必须以“/”开头,这样我们的客户端才能访问到对应的服务。

1.2.3 客户端整合

对于客户端要使用远程的Hessian服务的,我们需要在Spring的配置文件中定义对应的org.springframework.remoting.caucho.HessianProxyFactoryBean bean对象。     HessianProxyFactoryBean对象需要指定两个属性,一个是serviceInterface属性,表示当前请求的远程服务对应的接口;另一个是serviceUrl属性,表示当前的远程服务对应的服务端请求地址。这里在客户端为了使用hessianServer定义的UserService服务,我们建立一个对应的hessianClient项目,在hessianClient中我们定义一个对应的UserService接口,这个接口的内容跟hessianServer中的UserService接口的内容是一样的。代码如下所示:

package com.tiantian.hessianserver.service;
 
public interface UserService {
 
       public void addUser();
      
       public void updateUser();
      
       public void delUser();
      
       public String findUser(String username);
      
}

 

       之后我们就在当前Spring的配置文件中定义对应的HessianProxyFactoryBean对象。HessianProxyFactoryBean会根据指定的serviceInterfaceserviceUrl属性返回一个serviceInterface对应的代理对象。这里我们的Spring配置文件这样定义:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 
       <bean id="userService"
              class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
              <property name="serviceUrl"
                     value="http://localhost:8080/hessianServer/api/service/userService" />
              <property name="serviceInterface" value="com.tiantian.hessianserver.service.UserService" />
       </bean>
</beans>

 

       可以看到我们通过HessianProxyFactoryBean定义了一个UserService对应的远程代理对象,之后我们就可以在我们的程序中把它作为一个普通的bean对象来使用这个UserService的代理对象了。这里我们定义以下测试代码:

package com.tiantian.hessianclient.test;
 
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.tiantian.hessianserver.service.UserService;
 
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/applicationContext.xml")
public class HessianTest {
 
       @Autowired
       private UserService userService;
      
       @Test
       public void test() {
              userService.addUser();
              userService.updateUser();
              userService.delUser();
              String user = userService.findUser("ZhangSan");
              System.out.println(user);
              System.out.println("---------------------------------finished----------------------------------");
       }
      
}

 

       之后我们启动我们的hessianServer,然后执行上面的测试程序,在服务端会输出如下内容:



 

       在客户端会输出如下内容:



 

       这说明我们已经成功地调用了远程服务UserService

注:

    1.Hessian不支持方法的重载,打个比方现在有一AddService,里面有一add(int a, int b)和一add(long a, long b)方法,然后我们把它发布为一个Hessian服务。那么当我们想要远程访问AddService的add方法时Hessian会报错,抛出异常

com.caucho.hessian.io.HessianProtocolException: '?' is an unknown code

因为默认情况下它是不支持方法的重载,这个时候我们可以在客户端使用的时候新增属性overloadEnabled,值为true。如:

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
       xmlns:mvc="http://www.springframework.org/schema/mvc"  
       xsi:schemaLocation="http://www.springframework.org/schema/beans  
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
     http://www.springframework.org/schema/context  
     http://www.springframework.org/schema/context/spring-context-3.0.xsd">  
   
       <bean id="userService"  
              class="org.springframework.remoting.caucho.HessianProxyFactoryBean">  
              <property name="serviceUrl"  
                     value="http://localhost:8080/hessianServer/api/service/userService" />  
			  <property name="serviceInterface" value="com.tiantian.hessianserver.service.UserService" />
			  <!--新增overloadEnabled属性,并把它的值设置为true,默认是false,则Hessian就能支持方法的重载了。-->
			  <property name="overloadEnabled" value="true" />
       </bean>  
</beans>

 

       2.完整源码请查看附件。

  • 大小: 1.6 KB
  • 大小: 1.1 KB
12
2
分享到:
评论
10 楼 snfdf 2017-09-27  
234390216 写道
snfdf 写道
看了博主的文章,正好解决了我们最近项目的一个问题,但是在用了hessian后又出现另一个问题还要请教博主,客户端在请求服务端得到数据后,例如得到的是一个list对象,但是在准备循环遍历这个list中的对象时却报了一个异常:java.lang.ClassCastException: java.util.HashMap cannot be cast to xxx.xxx.xxx.xxx,而接口方法明明指定了返回值为List<xxx> findAll(),请问博主有碰到这种问题吗?有啥解决办法?谢谢。


没遇到过,在服务端检查一下list中存储的确实是你指定的xxx对象吗?List<XXX>中是可以存储YYY对象的,但是在使用的时候如果你以为存储的是XXX,把YYY当XXX用时就会报类型转换错误。


感谢博主的回复,问题已经解决了,参考了下面zoushaohua84兄的回复,我在写接口的时候两个项目的接口包名是不一致的,不过这确实没有任何影响,数据可以请求到,但我的问题是不但接口包名不一致,实体类的包名也不一致,这就导致从A项目请求到的数据在B项目中无法转换成对应的类型,可能是因为这个原因吧,hessian就当hashmap来处理的,我把两个项目的实体类的包名对应一致这个问题就解决了。
9 楼 234390216 2017-09-26  
snfdf 写道
看了博主的文章,正好解决了我们最近项目的一个问题,但是在用了hessian后又出现另一个问题还要请教博主,客户端在请求服务端得到数据后,例如得到的是一个list对象,但是在准备循环遍历这个list中的对象时却报了一个异常:java.lang.ClassCastException: java.util.HashMap cannot be cast to xxx.xxx.xxx.xxx,而接口方法明明指定了返回值为List<xxx> findAll(),请问博主有碰到这种问题吗?有啥解决办法?谢谢。


没遇到过,在服务端检查一下list中存储的确实是你指定的xxx对象吗?List<XXX>中是可以存储YYY对象的,但是在使用的时候如果你以为存储的是XXX,把YYY当XXX用时就会报类型转换错误。
8 楼 snfdf 2017-09-26  
看了博主的文章,正好解决了我们最近项目的一个问题,但是在用了hessian后又出现另一个问题还要请教博主,客户端在请求服务端得到数据后,例如得到的是一个list对象,但是在准备循环遍历这个list中的对象时却报了一个异常:java.lang.ClassCastException: java.util.HashMap cannot be cast to xxx.xxx.xxx.xxx,而接口方法明明指定了返回值为List<xxx> findAll(),请问博主有碰到这种问题吗?有啥解决办法?谢谢。
7 楼 zoushaohua84 2016-03-14  

如果 接口包路径不一致,可以调用
6 楼 keren 2014-08-30  
如果 接口包路径不一致,或者如果客户端是用其他语言来调用呢,比如php c等,怎么弄。
5 楼 234390216 2014-06-19  
OnTheRoad_lee 写道
这个好像是java project啊,不是web project,那怎么部署到tomcat里??add Deployment时没找到项目

这是基于Maven构建的Web项目。
4 楼 OnTheRoad_lee 2014-06-19  
这个好像是java project啊,不是web project,那怎么部署到tomcat里??add Deployment时没找到项目
3 楼 与天争锋 2013-08-20  
哇!好详细!收下了! 谢谢分享!
2 楼 234390216 2013-05-15  
7454103 写道
有没有尝试 客户端的包路径 和服务器端的路径不一致呢!或者解决办法?

这个没有尝试过,有时间时会试一下,不过估计是不可行的,而且一般也不会有这个需求,真正项目中进行Hessian远程服务调用的时候那些对应的接口一般我们都是会把它拿出来作为一个jar包进行依赖的,而不会像文中示例代码那样把一个接口写两次,这样服务端和客户端用的都是同路径的同一接口。
1 楼 7454103 2013-05-15  
有没有尝试 客户端的包路径 和服务器端的路径不一致呢!或者解决办法?

相关推荐

    Spring 实现远程访问详解——rmi

    Spring为各种远程访问技术提供集成工具类。Spring远程访问通过使用普通POJOs,能更容易的开发远程访问服务。目前,Spring远程访问的主要技术如下: 1. 远程调用RMI(Remote Method Invocation): 通过使用 ...

    hessian远程通信

    本示例是hessian与spring整合的,客户端与服务端相互调用的最完整例子。

    spring jar 包详解

    (9) spring-remoting.jar 这个jar文件包含支持EJB、JMS、远程调用Remoting(RMI、Hessian、Burlap、Http Invoker、JAX-RPC)方面的类。 (10) spring-support.jar 这个jar文件包含支持缓存Cache(ehcache)、JCA、...

    Spring 2.5 jar 所有开发包及完整文档及项目开发实例

    因此,就算你只是为了远程访问(例如,暴露Hessian或者 HTTP调用服务)而使用DispatcherServlet,你也得将'spring-webmvc.jar'(或者 'spring-webmvc-portlet/struts.jar')放到'spring.jar'旁边去。 Spring 2.0的 '...

    Spring 2.0 开发参考手册

    18.2.3. 访问远程SLSB 18.3. 使用Spring提供的辅助类实现EJB组件 19. JMS 19.1. 简介 19.2. 使用Spring JMS 19.2.1. JmsTemplate 19.2.2. 连接工厂 19.2.3. (消息)目的地管理 19.2.4. 消息侦听容器 19.2.5....

    Spring-Reference_zh_CN(Spring中文参考手册)

    2. Spring 2.0 的新特性 2.1. 简介 2.2. 控制反转(IoC)容器 2.2.1. 更简单的XML配置 2.2.2. 新的bean作用域 2.2.3. 可扩展的XML编写 2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@AspectJ 切面的...

    最新最全的spring开发包

     这个jar文件包含支持EJB、JMS、远程调用Remoting(RMI、Hessian、Burlap、Http Invoker、JAX-RPC)方面的类。 (10) spring-support.jar  这个jar文件包含支持缓存Cache(ehcache)、JCA、JMX、邮件服务(Java ...

    spring in action英文版

     4.4 用Spring整合Hibernate  4.4.1 Hibernate概览  4.4.2 管理Hibernate资源  4.4.3 用HibernateTemplate访问Hibernate  4.4.4 HibernateDaoSupport的子类  4.5 Spring和JDO  4.5.1 配置JDO ...

    Spring中文帮助文档

    2.6.4. 将Spring 应用程序上下文部署为JCA adapter 2.6.5. 计划任务 2.6.6. 对Java 5 (Tiger) 支持 2.7. 移植到Spring 2.5 2.7.1. 改变 2.8. 更新的样例应用 2.9. 改进的文档 I. 核心技术 3. IoC(控制反转)...

    spring chm文档

    Spring Framework 开发参考手册 Rod Johnson Juergen Hoeller Alef Arendsen ...18.2.3. 访问远程SLSB 18.3. 使用Spring提供的辅助类实现EJB组件 19. JMS 19.1. 简介 19.2. 使用Spring JMS ...

    Spring in Action(第2版)中文版

    第8章spring和基于pojo的远程服务 8.1spring远程调用概览 8.2与rmi一起工作 8.2.1连接rmi服务 8.2.2输出rmi服务 8.3使用hessian和burlap的远程调用 8.3.1访问hessian/burlap服务 8.3.2用hessian或burlap公开...

    Spring API

    2. Spring 2.0和 2.5的新特性 2.1. 简介 2.2. 控制反转(IoC)容器 2.2.1. 新的bean作用域 2.2.2. 更简单的XML配置 2.2.3. 可扩展的XML编写 2.2.4. Annotation(注解)驱动配置 2.2.5. 在classpath中自动搜索组件...

    Spring in Action(第二版 中文高清版).part2

    第8章 Spring和基于POJO的远程服务 8.1 Spring远程调用概览 8.2 与RMI一起工作 8.2.1 连接RMI服务 8.2.2 输出RMI服务 8.3 使用Hessian和Burlap的远程调用 8.3.1 访问Hessian/Burlap服务 8.3.2 用Hessian或...

    Spring in Action(第二版 中文高清版).part1

    第8章 Spring和基于POJO的远程服务 8.1 Spring远程调用概览 8.2 与RMI一起工作 8.2.1 连接RMI服务 8.2.2 输出RMI服务 8.3 使用Hessian和Burlap的远程调用 8.3.1 访问Hessian/Burlap服务 8.3.2 用Hessian或...

    Spring In Action 简体中文CHM版.rar

    不管什么样的情况,你的应用需要和其他系统交流,远程访问它们的服务。  本册子将涉及与RMI一起工作、使用Hessian和Burlap的远程调用、JMS发送消息、使用Tile设计页面布局、保护Web应用程序、使用JAX-RPC的Web ...

    java开源包1

    Spring4GWT GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java...

    java开源包11

    Spring4GWT GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java...

    java开源包2

    Spring4GWT GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java...

Global site tag (gtag.js) - Google Analytics