`

spring和hessian整合--基于HessianServiceExporter & BurlapServiceExporter

阅读更多

前言:

      近日着手研究了一下Hessian的rmi方案,因为客户端是多种移动终端平台,本来想采用传说中的phprpc(hprose?)的,但看了下官方的文档,发现没有object-c的版本,故而放弃。

      跟着hessian 的官方例子走,跑起来是没有问题的,但我在试着跟spring整合的时候,出了不少的问题。记录一下,方便自己以及路人,呵呵。

 

环境说明:

 

  • spring        version 3.0      RELEASE.
  • Hessian      version  4.0.7  WHATEVER.
  • JEE            version 2.5

实现步骤:

  1. 配置 web.xml ,添加对spring-web中 DispatcherServlet的定义.具体如下:
    <servlet>
            <servlet-name>test-remote</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>/WEB-INF/config/test-remote.xml</param-value>
            </init-param>
            <load-on-startup>4</load-on-startup>
    </servlet>
    
    <servlet-mapping>
            <servlet-name>test-remote</servlet-name>
            <url-pattern>/remote/*</url-pattern>
    </servlet-mapping>
     Tips:
        A.  很多网友都说一定要在WEB-INF下面放入跟servlet-name相对应的 test-remote-servlet.xml 配置文件,实际上是不一定要那么处理的。如果指定了 contextConfigLocation的话,就可以解决这个问题。意味着spring不会强制要求你配置文件的位置。
        B.  DispatcherServlet是可以配置多个的,我这里还有一个test-local,mapping着 "/" 路径,他们之间并不会影响。当然可以单纯的配置多个 servlet-mapping.我只是想验证一下,结果说明确实是可以的。    
  2.  传输对象类Space 的定义:
    package test.remote.dto;
    
    import java.io.Serializable;
    import java.util.Date;
    
    /**
     * Space data transfer object.
     * @author gogo
     * 
     */
    public class Space implements Serializable{
        
      /**
         * auto generated serialVersionUid.
         */
        private static final long serialVersionUID = 5632812127919571530L;  
        
        /** public space name for people in the space.*/
    	private String publicName;
    	private String privateName;
    	private boolean isActive;
    	private Date lastUpdatedTime;
    
    	/**
             *  setter & getter
             */
    	
    	@Override
    	public String toString() {
    	    StringBuilder buffer = new StringBuilder("Space:");
    	    buffer.append("public name:").append(publicName).append(", ");
    	    buffer.append("private name:").append(privateName).append(", ");
    	    buffer.append("is actived:").append(isActive).append(", ");
    	    buffer.append("lastUpdatedTime:").append(lastUpdatedTime.getTime());
    	    return buffer.toString();
    	} 
    }
    
     
  3.   服务接口的定义如下:
       package test.remote.service;
    import java.util.List;
    
    import test.remote.dto.Space;
    
    /**
     * 
     * @author gogo
     *
     */
    public interface SpaceService {
    	
    	List showSpaceNames(); //返回名字集合
    	
    	Space findSpace(String id);//找到空间名字
    	
    	boolean updateSpaceName(String name); //更新空间名字
    	
    }
    
     
  4. 服务接口实现类:
      package test.remote.service.impl;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.remoting.caucho.HessianServiceExporter;
    
    import test.remote.dto.Space;
    import test.remote.service.SpaceService;
    
    /**
     * 这个是一个远程接口的测试实现<br>
     * 该接口会由spring的 {@link HessianServiceExporter}以Http服务的形式暴露.<br>
     * 客户端会依赖Hessian实现
     * @see HessianServiceExporter
     * @author gogo 
     * 
     */
    public class SpaceServiceImpl implements SpaceService{
    	
    	private static final Log log = LogFactory.getLog(SpaceServiceImpl.class);
    	
    	private Space createSpace() {
    		Space space = new Space();
    		space.setPublicName("roosher-space");
    		space.setPrivateName("my-private-room");
    		space.setActive(true);
    		space.setLastUpdatedTime(new Date());
    		return space;
    	}
    
    	public Space findSpace(String id) {
    		// TODO Auto-generated method stub
    		log.debug("find space id is :" + id);
    		return createSpace();
    	}
    
    	public List showSpaceNames() {
    		// TODO Auto-generated method stub
    		List names = new ArrayList<String>();
    		for (int i = 0; i < 10; i++) {
    			names.add("Hello space "+ i);
    		}
    		return names;
    	}
    
    	public boolean updateSpaceName(String name) {
    		// TODO Auto-generated method stub
    		log.debug("updated space name : " + name );
    		return true;
    	}
    	
    }
    
     
  5.  test-remote.xml的内容:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:context="http://www.springframework.org/schema/context"
            xmlns:p="http://www.springframework.org/schema/p"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	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 
    		class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"
                             p:order="1"></bean>
    		
    	<bean id="spaceService" class="test.service.impl.SpaceServiceImpl">
            </bean>
    	
    	<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter">
            </bean>
    
    	<bean name="/SpaceHessian" 
    		class="org.springframework.remoting.caucho.HessianServiceExporter"
    		p:serviceInterface="test.remote.service.SpaceService"
    		p:service-ref="spaceService">
    	</bean>
    	
    	<bean name="/SpaceBurlap"
                 class="org.springframework.remoting.caucho.BurlapServiceExporter"
                 p:serviceInterface="test.remote.service.SpaceService"
                 p:service-ref="spaceService">
            </bean>
    	
    </beans>
     Tips:
         A.  BeanNameUrlHandlerMapping 属性中的 p:order="1",可以不用配置.避免跟自己的冲突.   
         B.  HttpRequestHandlerAdapter 在这里面非常关键,没有它可能会出现这种错误:
            -- No adapter for handler Does your handler implement a supported interface like Controller ?                 HttpRequestHandlerAdapter它的作用就是让spring-mvc放出权限给下面的Exporter自己处理整个HTTP 流程.毕竟HessianServiceExporter也是实现的HttpRequestHandler
  6. 客户端的两种实现:
    A.  就是基于spring的实现,采用org.springframework.remoting.caucho.HessianProxyFactoryBean实现,相关配置如下:
        
    <bean id="spaceServiceHessian"
    		class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
    	<property name="serviceUrl"
    		  value="http://localhost:8080/test/remote/SpaceHessian" />
    	<property name="serviceInterface" value="test.remote.service.SpaceService" />
    </bean>
    
    <bean id="spaceServiceBurlap"
            class="org.springframework.remoting.caucho.BurlapProxyFactoryBean">
            <property name="serviceUrl"
                      value="http://localhost:8080/test/remote/SpaceBurlap" />
            <property name="serviceInterface" value="test.remote.service.SpaceService" />
    </bean>
    
    
     注意到里面的URL了没? 其中 http://localhost:8080/test/remote/SpaceHessian 的/SpaceHessian 对应的是之前在remote-test.xml中配置的<bean name="/SpaceHessian"> </bean>的URI.

    然后通过spring获取上下文之后,就可以直接注入 SpaceService service = context.getBean("spaceServiceBurlap");

    B . 就是基于Hessian 自己提供的客户端,这里展示的是Java版本.
      
  7. package test.remote;
    
    import java.net.MalformedURLException;
    import java.util.List;
    
    import com.caucho.hessian.client.HessianProxyFactory;
    import test.remote.dto.Space;
    import test.remote.service.SpaceService;
    
    /**
     * 连接客户端。测试时要注意 url的ip地址.
     * @see Space
     * @author gogo
     * 
     */
    public class SpaceClient {
    
        public static void main(String[] args) {
            String url = "http://192.168.0.9:8080/test/remote/SpaceHessian";
            HessianProxyFactory factory = new HessianProxyFactory();
            try {
                SpaceService spaceService = (SpaceService) factory.create(
                        SpaceService.class, url);
                System.out.println(spaceService.findSpace("testid"));
                System.out.println(spaceService.updateSpaceName("whatever"));
                
                List spaceNames = spaceService.showSpaceNames();
                System.out.println("\r\nGet space names:");
                for (int i = 0; i < spaceNames.size(); i++) {
                    System.out.print(spaceNames.get(i) + ", ");
                }
                System.out.println();
                System.out.println("space names list finished");
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
        }
    }
    
     如果后台没有什么太大的问题,直接跑起来就可以测试了。
  8. 测试结果:
    Space:public name:roosher-space, private name:my-private-room, is actived:true,
    lastUpdatedTime:1282196778538
    true
    
    Get space names:
    Hello space 0, Hello space 1, Hello space 2, Hello space 3, Hello space 4, Hello space 5
    , Hello space 6, Hello space 7, Hello space 8, Hello space 9,
    space names list finished
     
  9. Cheers! 第一次认真的写博.但愿对大家有所帮助

     

 

 

 

3
0
分享到:
评论
4 楼 andot 2014-03-22  
hprose已经免费开源了,也有objc支持。
3 楼 gogomarine 2011-02-10  
gogomarine 写道
lvff1314 写道
跟你遇到基本相同的情况,移动多平台访问,最初决定使用PHPRPC,后来发现没有Objective-c,而所谓的hprose又不提供下载,故转道hessian,目前我用的最新的4.0.7,server端同样使用的spring进行hessian服务发布,但是遇到了一个比较尴尬的问题,我发现hessian在server端获取session比较困难,仔细查看client源码发现没有cookie机制,后对源码进行扩展增加了对response的header “Set-Cookie”的处理,但仍无效果。。。而且发现,spring通过自己的mvc进行发布的时候并没有调用hessian提供的ServiceContext.begin(...),而在hessian自带的servlet里是调用了该方法以及end方法,故在我们的逻辑里可以使用ServiceContext的getContextRequest()方法获取Request进而获取session,无奈。。。。

关于session的情况你遇到过吗?


打了一大堆字,点错了之后,全部被清掉了~郁闷
你可以参考 http://qieqie.iteye.com/blog/82492


上面那个帖子有点年代了,部分内容在现在好像已经不需要了。
用session无非就是想要有状态,我们可以通过添加请求头来做类似的事情,可能要结合filter来做状态的保存:

在 Hessian 4.0+中,HessianProxy 有个方法 protected void addRequestHeaders(HessianConnection conn),我们可以在每次请求之前,调用这个,然后添加请求头HessianConnection#public void addHeader(String key, String value);

在server那边读取请求头,进行标示就好了~
2 楼 gogomarine 2011-02-10  
lvff1314 写道
跟你遇到基本相同的情况,移动多平台访问,最初决定使用PHPRPC,后来发现没有Objective-c,而所谓的hprose又不提供下载,故转道hessian,目前我用的最新的4.0.7,server端同样使用的spring进行hessian服务发布,但是遇到了一个比较尴尬的问题,我发现hessian在server端获取session比较困难,仔细查看client源码发现没有cookie机制,后对源码进行扩展增加了对response的header “Set-Cookie”的处理,但仍无效果。。。而且发现,spring通过自己的mvc进行发布的时候并没有调用hessian提供的ServiceContext.begin(...),而在hessian自带的servlet里是调用了该方法以及end方法,故在我们的逻辑里可以使用ServiceContext的getContextRequest()方法获取Request进而获取session,无奈。。。。

关于session的情况你遇到过吗?


打了一大堆字,点错了之后,全部被清掉了~郁闷
你可以参考 http://qieqie.iteye.com/blog/82492
1 楼 lvff1314 2011-01-26  
跟你遇到基本相同的情况,移动多平台访问,最初决定使用PHPRPC,后来发现没有Objective-c,而所谓的hprose又不提供下载,故转道hessian,目前我用的最新的4.0.7,server端同样使用的spring进行hessian服务发布,但是遇到了一个比较尴尬的问题,我发现hessian在server端获取session比较困难,仔细查看client源码发现没有cookie机制,后对源码进行扩展增加了对response的header “Set-Cookie”的处理,但仍无效果。。。而且发现,spring通过自己的mvc进行发布的时候并没有调用hessian提供的ServiceContext.begin(...),而在hessian自带的servlet里是调用了该方法以及end方法,故在我们的逻辑里可以使用ServiceContext的getContextRequest()方法获取Request进而获取session,无奈。。。。

关于session的情况你遇到过吗?

相关推荐

    hessian-lite-3.2.1-fixed-2.jar

    com.alibaba:hessian-lite:jar:3.2.1-fixed-2 hessian-lite hessian-lite-3.2.1-fixed-2.jar

    mani.rar_Hessian LLE _LLE matlab_MáS_donoho_matlab laplacian

    mani: MANIfold learning demonstration...(4) Hessian LLE -- D. Donoho & C. Grimes (5) Laplacian -- M. Belkin & P. Niyogi (6) Diffusion Map -- R. Coifman & S. Lafon (7) LTSA -- Zhenyue Zhang & Hongyuan Zha

    hessian-3.3.6-API文档-中英对照版.zip

    赠送jar包:hessian-3.3.6.jar 赠送原API文档:hessian-3.3.6-javadoc.jar 赠送源代码:hessian-3.3.6...人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心使用。 双语对照,边学技术、边学英语。

    hessian-3.3.6-API文档-中文版.zip

    赠送jar包:hessian-3.3.6.jar; 赠送原API文档:hessian-3.3.6-javadoc.jar; 赠送源代码:hessian-3.3.6-sources.jar; 赠送Maven依赖信息文件:hessian-3.3.6.pom; 包含翻译后的API文档:hessian-3.3.6-javadoc-...

    hessian-4.0.63-API文档-中英对照版.zip

    赠送jar包:hessian-4.0.63.jar; 赠送原API文档:hessian-4.0.63-javadoc.jar; 赠送源代码:hessian-4.0.63-sources.jar; 赠送Maven依赖信息文件:hessian-4.0.63.pom; 包含翻译后的API文档:hessian-4.0.63-...

    Hessian RPC-RMI技术 整合Structs Spring Hibernate Ibatis

    本文主要讨论的是如何将Hessian RPC与RMI技术整合到Structs、Spring、Hibernate和Ibatis这四个关键的Java开发框架中,以构建一个高效、灵活的分布式应用程序。 1. **Hessian配置说明**: Hessian的配置通常涉及...

    struts2+ibatis+spring+Hessian 整合项目

    struts2+ibatis+spring+Hessian 整合项目 web项目整合,服务端用hessian协议远程调用服务端的方法,hessian是用spring代理整合,struts2+ibatis+spring的整合项目,用作学习和开发基础平台构建很有用处,工程导入...

    Spring集成Hessian案例

    在IT行业中,Spring框架是Java领域最常用的轻量级应用框架之一,而Hessian则是一种高效的RPC(远程过程调用)协议,它允许服务提供者和消费者之间进行二进制远程方法调用。本案例主要关注如何将Spring与Hessian进行...

    hessian与spring整合的jar包

    当我们将Hessian与Spring进行整合时,主要目标是利用Spring的依赖注入(Dependency Injection, DI)和组件管理能力来简化Hessian服务的创建和管理。以下是一些关键知识点: 1. **Spring核心模块**(spring-core-...

    hessian-3.0.20-src.jar

    hessian是一个轻量级的Java Remoting方案

    hessian-lite

    2. **提升性能**:由于Hessian-lite的高效编码和解码机制,Dubbo可以以更低的带宽消耗和更快的速度处理大量请求,提高了整体系统的吞吐量和响应速度。 3. **降低依赖**:通过将hessian-lite 3.2.1-fixed-2版本安装...

    spring整合hessian进行远程通讯

    在Spring中整合Hessian,首先需要在Spring配置文件中定义Hessian的服务和客户端bean。 1. **Hessian服务端配置**: - 创建一个实现了特定业务接口的类,这个类是远程服务的实现。 - 在Spring配置文件中定义一个`...

    dubbo-hessian-lite

    Hessian-lite 是针对 Hessian 的一个轻量级实现,主要针对移动设备或者资源有限的环境,它简化了 Hessian 协议,降低了内存和性能开销。 Hessian-lite 的核心功能包括: 1. **序列化与反序列化**:能够将 Java 对象...

    Spring整合Hessian访问远程服务

    通过以上步骤,我们完成了Spring和Hessian的整合,实现了远程服务的调用。Hessian的优势在于它的轻量级、高效的二进制序列化,使得网络通信效率更高,同时Spring的管理能力确保了服务的可扩展性和易维护性。 在实际...

    Spring中集成Hessian的问题

    与基于XML的SOAP相比,Hessian的性能更高,因为XML解析和生成的开销较大。Hessian支持两种主要的调用类型:HTTP GET和HTTP POST,以及HTTP之外的TCP/IP连接。 **Spring与Hessian的集成** 在Spring中集成Hessian,...

    hessian-demo示例

    在IT行业中,Hessian是一种高效的二进制RPC(Remote ...同时,结合Spring和Jetty,我们可以快速搭建和部署服务,提高开发效率。在实际应用中,还可以考虑使用Spring Boot自动化配置,进一步简化项目结构和配置。

    Hessian与spring整合

    综上所述,"Hessian与Spring整合"的核心是利用Spring的管理能力,结合Hessian的高效远程调用特性,构建可扩展、易于管理和维护的分布式服务系统。通过这种方式,开发者可以专注于业务逻辑,而无需过于关注底层通信...

    基于spring+hessian框架的webservice实例

    在"基于spring+hessian框架的webservice实例"中,我们将看到如何结合Spring和Hessian来创建和消费Web服务。首先,我们需要创建一个服务接口和服务实现。这个接口定义了可供远程调用的方法,而实现则提供了具体的功能...

Global site tag (gtag.js) - Google Analytics